回答編集履歴
4
誤植修正
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
訂正
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
追記
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.
|
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
追記
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
|
```
|