teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

4

誤植修正

2018/03/16 01:36

投稿

LouiS0616
LouiS0616

スコア35676

answer CHANGED
@@ -15,7 +15,7 @@
15
15
 
16
16
  > 呼び出し先の関数でdata[i]->nameとすれば、
17
17
 
18
- `data[i]`の型は`student`であって、`student&`ではありません。
18
+ `data[i]`の型は`student`であって、`student*`ではありません。
19
19
  非ポインタの構造体変数 の要素を参照するときには、ドット演算子を使わねばなりません。
20
20
 
21
21
  > student型data変数の先頭のアドレスから

3

訂正

2018/03/16 01:36

投稿

LouiS0616
LouiS0616

スコア35676

answer CHANGED
@@ -29,8 +29,17 @@
29
29
  構造体ポインタ変数名->要素名 の 使い分けもいまいち理解できていません。
30
30
  (scanf("%s", *(data[i]).name); としてもエラーが出ました)
31
31
 
32
- どちらも同じです。ただアロー演算子を使った方が素直でしょう。
32
+ ~~どちらも同じです。ただアロー演算子を使った方が素直でしょう。~~
33
+ **訂正: 間接参照演算子`*`よりドット演算子`.`の方が優先順位が高いため、等価ではありません。**
33
34
 
35
+ **追記:**
36
+ 構造体ポインタのメンバにアクセスする、等価な方法は次の二つです。
37
+ - (*構造体ポインタ変数名).要素名
38
+ - 構造体ポインタ変数名->要素名
39
+
40
+ **追記終わり**
41
+
42
+
34
43
  > void student_input(student *data/* あるいは data[] ? */, int count);
35
44
 
36
45
  `student *data`でも`student data[]`でも同じです。

2

追記

2018/03/16 01:35

投稿

LouiS0616
LouiS0616

スコア35676

answer CHANGED
@@ -34,11 +34,12 @@
34
34
  > void student_input(student *data/* あるいは data[] ? */, int count);
35
35
 
36
36
  `student *data`でも`student data[]`でも同じです。
37
- ただ個人的には、後者の方が配列の存在を認識できる分好みです。
37
+ しかし個人的には、後者の方が配列の存在を感じられる分好みです。
38
38
 
39
+ (ポインタが配列を指さないことも充分あり得る。)
40
+
39
41
  結局何が問題か?
40
42
  ---
41
-
42
43
  **ドット演算子を使うべき場面で、アロー演算子を使っていること。**
43
44
 
44
45
  それ以外の問題
@@ -51,9 +52,9 @@
51
52
  ```
52
53
 
53
54
  0. scanfの第二引数以降は、格納先のアドレスです。
54
- data[i].nameはポインタを返すので問題ないですが、yearとsexの読み取り誤りです。
55
+ data[i].nameはポインタを返すので問題ないですが、yearとsexは非ポインタです。
55
- 0. また、文字は`%c`で受け取る必要があります。
56
+ 0. 文字は`%c`で受け取る必要があります。
56
- 0. さらに必要に応じて**バッファのゴミを回収せねばなりません**。
57
+ 0. 必要に応じて**バッファのゴミを回収せねばなりません**。
57
58
 
58
59
  上記の問題をクリアすると次のようになります。
59
60
  ```C
@@ -176,4 +177,6 @@
176
177
  src->name, src->year, src->sex
177
178
  );
178
179
  }
179
- ```
180
+ ```
181
+
182
+ まだまだ改良の余地があるとは思いますが。

1

追記

2018/03/15 18:59

投稿

LouiS0616
LouiS0616

スコア35676

answer CHANGED
@@ -16,7 +16,7 @@
16
16
  > 呼び出し先の関数でdata[i]->nameとすれば、
17
17
 
18
18
  `data[i]`の型は`student`であって、`student&`ではありません。
19
- 非ポインタの構造体変数の要素を参照するときには、ドット演算子を使わねばなりません。
19
+ 非ポインタの構造体変数 の要素を参照するときには、ドット演算子を使わねばなりません。
20
20
 
21
21
  > student型data変数の先頭のアドレスから
22
22
  i個離れたアドレスのname要素にアクセスすると認識しています。
@@ -65,8 +65,13 @@
65
65
  scanf("%c", &data[i].sex);
66
66
  ```
67
67
 
68
- 本当エラーチェックもすべきところですがここは省きます。
68
+ あるいは、一気に読んうのもアリです。
69
+ ```C
70
+ scanf("%s\n%d\n%c\n", data[i].name, &data[i].year, &data[i].sex);
71
+ ```
69
72
 
73
+ 本当はエラーチェックもすべきところですが、ここでは省きます。(c.f. サンプル)
74
+
70
75
  **その他**
71
76
  - student_output と student_print の表記揺れ。
72
77
  - 無駄な変数 txt の存在。 (エラーではなく警告だけど)
@@ -120,4 +125,55 @@
120
125
 
121
126
  return;
122
127
  }
128
+ ```
129
+
130
+ 気が向いたので改造もしてみました。[Wandbox](https://wandbox.org/permlink/Z1Pv4LGyCVde5AjL)
131
+ ```C
132
+ #include <stdio.h>
133
+ #include <stdlib.h>
134
+ #define ARRAY_LEN(arr) (sizeof(arr) / sizeof(*arr))
135
+
136
+ typedef struct {
137
+ char name[64];
138
+ int year;
139
+ char sex; // is_man にする余地あり
140
+ } Student;
141
+
142
+ int scan_student(Student *dst);
143
+ int print_student(const Student *src);
144
+
145
+ int main(void) {
146
+ Student data[3];
147
+ for(size_t i = 0; i < ARRAY_LEN(data); ++i) {
148
+ scan_student(&data[i]);
149
+ print_student(&data[i]);
150
+ }
151
+
152
+ return 0;
153
+ }
154
+
155
+ int scan_student_without_check(Student *dst) {
156
+ return scanf(
157
+ "%s\n%d\n%c\n",
158
+ dst->name, &dst->year, &dst->sex
159
+ );
160
+ }
161
+ int scan_student(Student *dst) {
162
+ int ret = scan_student_without_check(dst);
163
+ if(ret != 3) {
164
+ fprintf(stderr, "Cannot read student data.\n");
165
+ exit(1);
166
+ }
167
+
168
+ return ret;
169
+ }
170
+
171
+ int print_student(const Student *src) {
172
+ return printf(
173
+ "[名前]\t%s\n"
174
+ "[年齢]\t%d\n"
175
+ "[性別]\t%c\n",
176
+ src->name, src->year, src->sex
177
+ );
178
+ }
123
179
  ```