回答編集履歴

7

アドレス・ポインタを使った説明表現をもう少し正確っぽく

2023/07/16 17:54

投稿

jimbe
jimbe

スコア13320

test CHANGED
@@ -6,13 +6,13 @@
6
6
  大量に修正してイッパツでコンパイルエラーも無く思った通りに動作させられることは滅多にありません。
7
7
 
8
8
  配列の引数の書き方が分かっておられないようです。
9
- **配列の引数はポインタになります。そして、配列は配列名だけでポインタを表します。**
9
+ **配列の引数は先頭アドレスの受け渡しになります。そして、配列は配列名だけで先頭アドレスを表します。**
10
- `int a[MAXDATA]` は `a` だけでポインタになりますので、`file(&a[MAXDATA], n);` は `file(a, n);` と書かなくてはなりません。
10
+ `int a[MAXDATA]` は `a` だけで先頭アドレスになりますので、`file(&a[MAXDATA], n);` は `file(a, n);` と書かなくてはなりません。
11
- **関数側はポインタを貰う**のですから `int file(int a[MAXDATA], int n){` では無く `int file(int *a, int n){` となります。
11
+ **関数側はアドレスを貰う**のですから `int file(int a[MAXDATA], int n){` では無く `int file(int *a, int n){` とポインタになります。
12
12
 
13
13
  また、関数の名前は基本的に動詞にしたほうが良いです。 file() という関数はファイルをどうするのか分かりませんが、 read() なら何かを読むらしいとか、もっとはっきり readFromFile() という名前ならファイルから読む関数であることが明白になります。
14
14
 
15
- file 関数の第二引数 n は何の為にあるのでしょうか。もし n も file 関数から返すデータとするつもりなら、こちらもポインタにする必要があります。
15
+ file 関数の第二引数 n は何の為にあるのでしょうか。もし n も file 関数から返すデータとするつもりなら、こちらもアドレス(とポインタ)にする必要があります。
16
16
  **引数の変数に値を設定しても呼び出し側の変数の値は変わりません**
17
17
  `file(&a[MAXDATA], n);` → `file(a, &n);`
18
18
  `int file(int a[MAXDATA], int n){` → `int file(int *a, int *n){`

6

表現を修正

2023/07/16 17:46

投稿

jimbe
jimbe

スコア13320

test CHANGED
@@ -1,8 +1,8 @@
1
1
  >色々いじったらコンパイルでエラーが多く出た
2
2
 
3
3
  コンパイルエラーが出たなら、何が悪いのかを探して直さなければなりません。
4
- 一気に全てを修正してからコンパイルしたのではどこで何が悪いのか探すのが面倒になります。
4
+ 一気に全てを変更からコンパイルしたのではどこで何が悪いのか探すのが面倒になります。
5
- 少ししてコンパイルしエラーがあったら直しコンパイルエラーが無くなったら動かして確認するのを繰り返す必要があります。
5
+ 少し変更してコンパイルしエラーがあったらエラーだけを追及して直しコンパイルエラーが無くなったら動かして変更を確認するのを繰り返す必要があります。
6
6
  大量に修正してイッパツでコンパイルエラーも無く思った通りに動作させられることは滅多にありません。
7
7
 
8
8
  配列の引数の書き方が分かっておられないようです。

5

コード例追加

2023/07/16 14:40

投稿

jimbe
jimbe

スコア13320

test CHANGED
@@ -31,4 +31,90 @@
31
31
  binary 関数の第一引数 potision も、引数から削除して関数値でしょう。第三引数 max は削除、関数内で `int max = n-1;` を追加すれば良いでしょう。
32
32
  binary 関数は search 関数と名前を変えたほうが良いと思います。
33
33
 
34
+ ---
35
+ ```c
36
+ #include <stdio.h>
37
+ #include <stdlib.h>
38
+ #define MAXDATA 10000
34
39
 
40
+ //データをファイルから読み込む
41
+ //a: データを格納する配列
42
+ //関数値: 配列に格納した件数
43
+ int readFromFile(int *a) {
44
+ char filename[20];
45
+ printf("file name = ");
46
+ scanf("%s", filename);
47
+
48
+ FILE *fin = fopen(filename, "r");
49
+ if(fin == NULL) {
50
+ printf("ファイルをオープンできません\n");
51
+ return -1;
52
+ }
53
+
54
+ int n = 0;
55
+ while(fscanf(fin, "%d", &a[n]) == 1) n++;
56
+
57
+ fclose(fin);
58
+
59
+ return n;
60
+ }
61
+
62
+ //昇順に並び替える
63
+ //a: データ配列
64
+ //n: 配列内の有効件数
65
+ void sort(int *a, int n) {
66
+ for(int i = 0; i < n - 1; i++) {
67
+ int j = i;
68
+ for(int k = i + 1; k < n; k++) {
69
+ if(a[j] > a[k]) {
70
+ j = k;
71
+ }
72
+ }
73
+ int tmp = a[j];
74
+ a[j] = a[i];
75
+ a[i] = tmp;
76
+ }
77
+ for(int i = 0; i < n; i++) {
78
+ printf("%d\n", a[i]);
79
+ }
80
+ }
81
+
82
+ //データを検索する
83
+ //a: 昇順のデータ配列
84
+ //n: 配列内の有効件数
85
+ //x: 探すデータ
86
+ //関数値: データが見つかったら配列のインデックスを返す. 無かったら -1 を返す
87
+ int search(int *a, int n, int x) {
88
+ int min = 0; //最小値のインデックス
89
+ int max = n - 1; //最大値のインデックス
90
+
91
+ while(min <= max) {
92
+ int mid = (max + min) / 2;
93
+ if(a[mid] == x) return mid;
94
+
95
+ if(a[mid] < x) {
96
+ min = mid + 1;
97
+ } else {
98
+ max = mid - 1;
99
+ }
100
+ }
101
+ return -1;
102
+ }
103
+
104
+ int main(void) {
105
+ int a[MAXDATA];
106
+ int n = readFromFile(a);
107
+ if(n < 0) exit(1); //オープンでエラーなら終わる必要がある
108
+
109
+ sort(a, n);
110
+
111
+ int x;
112
+ while(scanf("%d", &x) == 1) {
113
+ int position = search(a, n, x);
114
+ printf(" x=%d ---> %d\n", x, position);
115
+ }
116
+
117
+ printf("またお会いしましょう\n");
118
+ return 0;
119
+ }
120
+ ```

4

追加

2023/07/16 14:28

投稿

jimbe
jimbe

スコア13320

test CHANGED
@@ -25,4 +25,10 @@
25
25
  オープンに失敗した場合は(正常に読めた場合にはあり得ない) -1 を返すようにしたほうが良いでしょう。
26
26
 
27
27
  sort 関数の第三引数 `max` も file 関数の `n` と同じでしょうか。
28
- sort 関数は int 型の返り値が無ければならないのに return 文がありません。第三引数を無くして `return i;` でしょうか。
28
+ sort 関数は int 型の返り値が無ければならないのに return 文がありません。第三引数を無くして `return i;` でしょうか。 でも i は n と同じ値です。返す意味があるでしょうか。
29
+ ・・・恐らく、検索の方の処理を見る限りは必要無いでしょうね。sort 関数を void 型にして return 文は無しで良いと思います。
30
+
31
+ binary 関数の第一引数 potision も、引数から削除して関数値でしょう。第三引数 max は削除、関数内で `int max = n-1;` を追加すれば良いでしょう。
32
+ binary 関数は search 関数と名前を変えたほうが良いと思います。
33
+
34
+

3

修正

2023/07/16 13:59

投稿

jimbe
jimbe

スコア13320

test CHANGED
@@ -6,13 +6,14 @@
6
6
  大量に修正してイッパツでコンパイルエラーも無く思った通りに動作させられることは滅多にありません。
7
7
 
8
8
  配列の引数の書き方が分かっておられないようです。
9
- 配列の引数はポインタになります。そして、配列は配列名だけでポインタを表します。
9
+ **配列の引数はポインタになります。そして、配列は配列名だけでポインタを表します。**
10
10
  `int a[MAXDATA]` は `a` だけでポインタになりますので、`file(&a[MAXDATA], n);` は `file(a, n);` と書かなくてはなりません。
11
- 関数側はポインタを貰うのですから `int file(int a[MAXDATA], int n){` では無く `int file(int *a, int n){` となります。
11
+ **関数側はポインタを貰う**のですから `int file(int a[MAXDATA], int n){` では無く `int file(int *a, int n){` となります。
12
12
 
13
13
  また、関数の名前は基本的に動詞にしたほうが良いです。 file() という関数はファイルをどうするのか分かりませんが、 read() なら何かを読むらしいとか、もっとはっきり readFromFile() という名前ならファイルから読む関数であることが明白になります。
14
14
 
15
15
  file 関数の第二引数 n は何の為にあるのでしょうか。もし n も file 関数から返すデータとするつもりなら、こちらもポインタにする必要があります。
16
+ **引数の変数に値を設定しても呼び出し側の変数の値は変わりません**
16
17
  `file(&a[MAXDATA], n);` → `file(a, &n);`
17
18
  `int file(int a[MAXDATA], int n){` → `int file(int *a, int *n){`
18
19
  file 関数内では n がポインタになったため、 `n` を全て `*n` にする必要があります。(`n=0;` → `*n=0;` 等)

2

追加

2023/07/16 13:57

投稿

jimbe
jimbe

スコア13320

test CHANGED
@@ -23,4 +23,5 @@
23
23
  ただし・・・file 関数では ファイルのオープンに失敗した場合も `return 1;` としているので、これでは1件正常に読めた場合と区別が付きません。
24
24
  オープンに失敗した場合は(正常に読めた場合にはあり得ない) -1 を返すようにしたほうが良いでしょう。
25
25
 
26
-
26
+ sort 関数の第三引数 `max` も file 関数の `n` と同じでしょうか。
27
+ sort 関数は int 型の返り値が無ければならないのに return 文がありません。第三引数を無くして `return i;` でしょうか。

1

追加

2023/07/16 13:50

投稿

jimbe
jimbe

スコア13320

test CHANGED
@@ -11,3 +11,16 @@
11
11
  関数側はポインタを貰うのですから `int file(int a[MAXDATA], int n){` では無く `int file(int *a, int n){` となります。
12
12
 
13
13
  また、関数の名前は基本的に動詞にしたほうが良いです。 file() という関数はファイルをどうするのか分かりませんが、 read() なら何かを読むらしいとか、もっとはっきり readFromFile() という名前ならファイルから読む関数であることが明白になります。
14
+
15
+ file 関数の第二引数 n は何の為にあるのでしょうか。もし n も file 関数から返すデータとするつもりなら、こちらもポインタにする必要があります。
16
+ `file(&a[MAXDATA], n);` → `file(a, &n);`
17
+ `int file(int a[MAXDATA], int n){` → `int file(int *a, int *n){`
18
+ file 関数内では n がポインタになったため、 `n` を全て `*n` にする必要があります。(`n=0;` → `*n=0;` 等)
19
+ ですが、コードを見れば file 関数は `return n;` としているので呼び出し側は関数値として n を得ることが出来ますから、いっそ第二引数 n は無くしたほうが簡単でしょう。
20
+ `file(&a[MAXDATA], n);` → `n=file(a);`
21
+ `int file(int a[MAXDATA], int n){` → `int file(int *a){`
22
+ これなら file 関数内で n を *n にする必要はありません。
23
+ ただし・・・file 関数では ファイルのオープンに失敗した場合も `return 1;` としているので、これでは1件正常に読めた場合と区別が付きません。
24
+ オープンに失敗した場合は(正常に読めた場合にはあり得ない) -1 を返すようにしたほうが良いでしょう。
25
+
26
+