このような単純なコードには多くの問題があります。
まず、注意してください
city1 = malloc(sizeof (char *));
の配列ではなく、単一の インスタンスのみを割り当てます。基本的に、それぞれに単一のポインターを割り当てて保持します。それぞれが へのポインタを保持したい場合は、次のように記述する必要があります。char *
char *
city1
city2
char
city1
city2
N
char
city1 = malloc(sizeof (char *) * N);
また
city1 = malloc(sizeof *city1 * N);
私が好むもの。の型は*city1
ischar *
なのでsizeof *city1
==sizeof (char *)
です。の型が変更された場合、式でcity1
その変更を複製する必要はありませんsizeof
。
そう:
city1 = malloc(sizeof *city1 * N);
city2 = malloc(sizeof *city2 * N);
ただし、どちらの配列の要素も意味のある場所を指していません。名前ごとにメモリを割り当て、それに応じてポインターを割り当てる必要があります。
city1[i] = malloc(sizeof *city1[i] * 10);
の型はcity1[i]
ですので、char *
の型は*city[i]
ですchar
。
本当の問題の 1 つは、ループの構造にあります。
city1[0] = (char*)malloc(sizeof(char)*10);
city2[0] = (char*)malloc(sizeof(char)*10);
while(fscanf(data, "%s %s %d",city1[i],city2[i], &distance)!=EOF){
city1[i] = (char*)malloc(sizeof(char)*10);
city2[i] = (char*)malloc(sizeof(char)*10);
printf("%s\n%s\n%d\n", city1[i], city2[i], distance);
i++;}
最初のループでは 0 であるためi
、最初の 2 行に格納されているポインターを上書きすることになります。つまり、最初の都市名を書き込んだメモリを追跡できなくなります。次に、をインクリメントi
するため、次回はループcity1[i]
を通過し、割り当てたばかりのメモリを指して city2[i]
いません。
ロジックを少し再編成することをお勧めします。ここで、2 つのことを追跡する必要があります。city1
とで割り当てた要素の数city2
、および入力ファイルの最後にいるかどうか。私だったら、次のようにします。
for (i = 0; i < N; i++)
{
// first, allocate memory for the current array elements
city1[i] = malloc(...);
city2[i] = malloc(...);
// *then* read from the input file into those array elements
if (fscanf(...) != EOF)
{
printf(...);
}
else
{
break;
}
}
これは、配列の終わり (for ループの条件) を通過するか、入力ストリームで EOF に遭遇するまで、入力ファイルをループします (これにより、break
ステートメントが実行され、すぐにループが終了します)。
すべてを動的に割り当てることで、自分の生活をより困難にしていると思います。最初のパスでは、配列の固定サイズを想定したいだけかもしれません。スマートは後で追加できます。都市名の長さが 9 文字を超えないことがわかっていて、N を超える都市を扱っていないことがわかっている場合は、すべてを静的に宣言するだけです。
char city1[N][10];
char city2[N][10];
...
while (i < N && fscanf(data, "%s %s %d\n", city1[i], city2[i], &distance) != EOF)
{
printf("%s\n%s\n%d\n", city1[i], city2[i], distance);
}
最終的には、配列を動的に割り当てて拡張する方法を学びたいと思うでしょうが、その前に練習が必要であることは明らかです。歩く前に走る必要はありません。