1

我为字符串定义了一个数组。如果我以第一个元素不是空字符串的方式定义它,它工作正常。当它是一个空字符串时,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");
4

3 回答 3

1

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

请注意,scanf如果在读取字符串时不小心使用,将导致潜在的缓冲区溢出。我建议您阅读此页面以获取有关如何避免它的一些想法。

于 2013-07-01T19:12:05.593 回答
1

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

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

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

这基本上意味着任何事情都可能发生。当你这样做时:

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

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

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

继续阅读这篇文章,它有足够的信息来消除你的疑惑。

于 2013-07-03T07:04:35.580 回答
0

您正在传递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");

请记住,char *在 C 中并不等同于string在其他语言中 -char *只是一个指向 的指针char,它对分配一无所知。

于 2013-07-01T19:15:01.987 回答