2013-07-01 89 views
1

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

现在我不明白如何定义字符串数组影响读取输入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"); 

回答

1

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

的C FAQ定义“未定义行为”是这样的:

任何事情都有可能发生;该标准没有规定任何要求。 程序可能无法编译,或者它可能无法正确执行(或者 崩溃或无声地生成不正确的结果),或者它可能偶尔执行程序员预期的操作。

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

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

它的UB。有时候你会得到你认为不适合的结果,并且你认为它的工作原理。这就是调试器派上用场的地方。几乎每次都使用它们,尤其是在开始阶段。其他建议w.r.t您的程序:

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

继续阅读THIS ARTICLE,它有足够的信息来清除你的疑惑。

1

声明一个指针在内存中没有分配缓冲区并没有初始化,所以您要取消引用未初始化的指针(str),这导致一个未定义的行为。

请注意,scanf会导致潜在的缓冲区溢出,如果在读取字符串时不谨慎使用。我建议你阅读this page了解如何避免它的一些想法。

+0

我明白你在说什么,但通过这样的指针直到现在对我来说工作得很好。我从此不会这样做。但让我感到困惑的是,如何初始化str_arr的字符串数组会影响scanf的工作。程序崩溃时,它的一个空字符串,并工作得很好,当其非空。 –

+0

'str_arr'的初始化定义了它的大小,以及你可以放入多少,你用“hello”初始化它,它会分配一个由6个字符组成的数组(包括空终止符),如果你用“”初始化它“ ,它只会分配一个字符,所以对该数组的任何写入都将超出数组边界。 – MByD

+0

我完成了。但我没有得到它如何影响一个字符串读入一个不同的字符指针,这是str。 @Matteo Italia –

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,对分配一无所知。

+0

我明白你在说什么,但通过这样的指针直到现在对我来说工作得很好。我从此不会这样做。但让我感到困惑的是,如何初始化str_arr的字符串数组会影响scanf的工作。程序崩溃时,它的一个空字符串,并工作得很好,当其非空。 –