这么简单的代码有很多问题。
首先,请注意
city1 = malloc(sizeof (char *));
只分配一个单个 char * 实例,而不是char * 的数组。您基本上已经分配了city1 和city2 来分别保存一个指向char 的指针。如果你想让city1 和city2 分别持有N 指向char 的指针,那么你需要把它写成
city1 = malloc(sizeof (char *) * N);
或
city1 = malloc(sizeof *city1 * N);
我更喜欢。 *city1 的类型是 char *,所以 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。
一个真正的问题在于循环的结构:
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++;}
由于i 在第一次循环中为 0,因此您最终会覆盖存储在前两行中的指针,这意味着您忘记了将第一个城市名称写入的内存。然后你增加i,所以下一次循环city1[i] 和city2[i] 是不是 指向你刚刚分配的内存。
您可能想稍微重新组织一下您的逻辑。我们现在需要跟踪两件事;我们在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);
}
最终您将想学习如何动态分配和扩展数组,但很明显在此之前您需要一些练习。走之前不需要跑。