当第一个早期定义的字符串数组的字符串为null时,scanf()不读取输入字符串

我为字符串定义了一个数组。 如果我以第一个元素不是空字符串的方式定义它,它工作正常。 当它是一个空字符串时,另一个字符串的下一个scanf()停止读取输入字符串,程序停止执行。

现在我不明白如何定义字符串数组会影响scanf()读取输入。

  char *str_arr[] = {"","abc","","","b","c","","",""}; // if first element is "abc" instead of "" then works fine int size = sizeof(str_arr)/sizeof(str_arr[0]); int i; printf("give string to be found %d\n",size); char *str; scanf("%s",str); printf("OK\n"); 

实际上,你的错误是我的兄弟。 str_arr的初始化不会影响scanf()的工作,但是看起来你可能喜欢它但实际上并不是这样。 如其他答案中所述,这称为未定义行为C本身中未定义行为非常模糊

C FAQ定义了“未定义的行为”,如下所示:

任何事情都可能发生; 标准没有要求。 程序可能无法编译,或者可能无法正确执行(崩溃或静默生成不正确的结果),或者它偶然可能完全符合程序员的意图。

它基本上意味着一切都可能发生 当你这样做时:

 char *str; scanf("%s",str); 

它是一个UB。 有时你会得到你不应该得到的结果,你认为它的工作。这就是调试器派上用场的地方。几乎每次都使用它们,特别是在开始时。 您的计划的其他建议:

  • 而不是scanf()使用fgets()来读取字符串。 如果你想使用scanf,那就像scanf("%ws",name);一样使用它scanf("%ws",name); 其中name是字符数组, w是字段宽度。
  • 使用-Wall选项编译以获取所有警告,如果您已经使用它,您可能会收到warning that you are using str uninitialized

继续阅读本文,它有足够的信息来消除你的疑虑。

声明指针不会在内存中为它分配缓冲区并且不会对其进行初始化,因此您尝试取消引用未初始化的指针( str ),这会导致未定义的行为。

请注意,如果在读取字符串时未小心使用, scanf将导致潜在的缓冲区溢出。 我建议你阅读本页 ,了解如何避免它的一些想法。

您正在向scanf传递未初始化为任何特定内容的指针,因此scanf将尝试将用户提供的字符写入某个随机内存位置; 这是否会导致崩溃或其他原因主要取决于运气(以及编译器如何决定设置堆栈,我们也可能将其视为“运气”)。 从技术上讲,这被称为“未定义的行为” – 即就C标准而言,任何事情都可能发生。

要解决您的问题,您必须将scanf传递给一个足够大的缓冲区,以容纳您计划接收的字符串:

 char str[101]; scanf("%100s",str); /* the "100" bit tells to scanf to avoid reading more than 100 chars, which would result in a buffer overflow */ printf("OK\n"); 

并且记住C中的char * 等同于其他语言中的stringchar *只是指向char的指针, char分配一无所知。