为什么输出是用户的最后一个字符串?

#include #include int main() { int in,i,j; char *arr[100],str[14]; scanf("%d",&in); i=0; while(i<in) { scanf("%s",str); arr[i]=str; // printf("%s\n",arr[i]); i++; } i=0; while(i<in) { printf("%s\n",arr[i++]); } return 0; } 

/ *在这段代码中,我从用户那里获取输入字符串,并希望将其打印回来,但它正在打印用户输入的最后一个字符串.WHY ?? * /

您将每个字符串存储在同一位置,每次都覆盖前一个字符串。 不要那样做。 str是一个缓冲区,数组arr中的所有指针都指向它。

你的问题是arr[i]=str; 声明。

str是一个静态分配的数组, 所有 arr[i]都存储它的基地址。

由于str的值在每次调用scanf()被覆盖,在你的情况下,只有访问任何 arr[i]才会打印存储在str的最后一个值。

你需要做什么

  1. 动态分配内存到arr[100]
  2. 使用strcpy()将用户输入从str复制到arr[i]

注意:最后不要忘记free()分配的内存。

因为您将内存地址分配给指针数组。 所以数组的地址不会改变。 每个指针数组都指向同一个地址。

当新值获得时,它将该值放在数组中相同的地址位置。

所以所有的值都保持不变。 所以避免这种情况你可以使str成为指针。 并动态地将内存分配给该指针。

char *str; 在while循环中进行分配str=malloc(MAX);

 while(i 

100是一个例子。 你可以使用你需要的价值。

在循环中尝试这样的事情。

 while(i 

因为你继续对所有字符串使用相同的char[] str

相反,您可能希望为每个字符串分配一个新的内存块。 使用后不要忘记再次释放它们。

你可以在循环中检查它

 while(i 

而且你看到不仅字符串是相同的,而且它的地址也是如此。

您需要为每个字符串arr[i]分配内存,然后使用strcpy作为复制字符串。

在循环中添加如下所示的代码。

 arr[i]=malloc(strlen(str)+1); strcpy(arr[i],str); 

也永远不会忘记在程序结束时为上面的分配释放内存。

除了其他响应之外,还有一些替代方法可以用来读取字符串输入,您可以使用它们来简化程序中需要跟踪的内容。 正如其他人所建议的那样,不要将arr声明为char *arr[100] ,而是将其声明为pointer-to-pointer-to-char

 char **arr = NULL; 

这允许您分配一个字符指针数组。 您可以选择使用malloc进行分配,也可以选择仅使用calloc将所有指针分配并初始化zero/NULL

 arr = calloc (100, sizeof *arr); 

通过使用calloc ,这允许稍后只迭代那些包含字符串的指针。 这进一步消除了必须要求输入的字符串数量(或跟踪输入的字符串数量)。

分配指针后,需要分配空间来容纳每个字符串。 虽然对malloc (或calloc )的另一个调用以及对strcpy (或strncpy )的调用没有任何问题,但您可以使用string.h提供的函数strdup同时执行这两个strdupstrdup唯一需要注意的是它为你分配内存。 因此,您有责任在不再需要时释放该内存。

将各个部分放在一起,以及有关scanf字符串的注释中的信息,您可以按如下方式实现字符串集合。 注意您只需输入任意数量的字符串(最多分配100个指针),然后在完成后按空白行上的[enter]

 #include  #include  #include  int main () { int i = 0; /* always initialize your variables */ char **arr = NULL; char str[14] = { 0 }; arr = calloc (100, sizeof *arr); /* create 100 pointers to char* */ printf ("\nEnter strings ( [enter] alone when done )\n\n"); while (printf (" input: ") && scanf ("%[^\n]%*c", str) >= 1) arr[i++] = strdup (str); /* strdup allocates and copies */ printf ("\nThe strings entered were:\n\n"); i = 0; /* print the array */ while (arr[i]) { printf (" arr[%2d]: %s\n", i, arr[i]); i++; } i = 0; /* free memory allocated */ while (arr[i]) free (arr[i++]); if (arr) free (arr); return 0; } 

输出:

 $ ./bin/str_array Enter strings ( [enter] alone when done ) input: string 1 input: string 2 input: string 3 input: The strings entered were: arr[ 0]: string 1 arr[ 1]: string 2 arr[ 2]: string 3 

有很多方法可以解决这个问题。 比较所有答案并为您的collections添加不同的方法。 总有一个地方会有一个人会比另一个人受益,反之亦然。 请注意,在上面的代码中,您应该检查是否有任何使用callocmallocstrdup分配成功,并在失败时处理错误。 您还应该检查何时进入第99个sting并根据需要重新分配指针数。 为清楚起见,省略了这些检查。

valgrind内存使用总结

养成使用valgrind始终validation内存使用情况的习惯。 它会指出你已经分配了你未能释放的内存的任何地方。 虽然像这样的一小段代码中的内存将在exit释放,但是在更长的代码中,无法跟踪分配的内存会导致程序在不再需要内存后使用大量内存(内存)泄漏)。 使用valgrind快速检查会发现任何问题或确认一切顺利:

 ==28677== HEAP SUMMARY: ==28677== in use at exit: 0 bytes in 0 blocks ==28677== total heap usage: 4 allocs, 4 frees, 827 bytes allocated ==28677== ==28677== All heap blocks were freed -- no leaks are possible ==28677== ==28677== For counts of detected and suppressed errors, rerun with: -v ==28677== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2) 

如果您有任何疑问,请告诉我。