2012-10-09 32 views
0

所以我不能真正弄清楚为什么scanf搞乱了一个[0]。当我打印出数组时,一个[0]是空的,我想要一个[0]它存储在[1]中。使用scanf for循环与fgets返回一个[0]为空

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char *argv[]) 
{ 
    char *a[128]; 
    int i; 
    int num; 

    scanf("%d", &num); 

    for (i = 0; i < 2; i++) { 
     a[i] = malloc(50*sizeof(char)); 
     fgets(a[i], 100, stdin); 
    } 

    printf("[0] = %s [1] = %s", a[0], a[1]); 

    return 0; 
} 
+0

您的输入是什么? –

+0

说我输入:1 [enter]这是一个字符串[enter] – user1455112

回答

3

scanf()搞乱你a[0],至少不是在你似乎认为,通过某种方式破坏其存储区域的方式。混合输入的不同“方法”,这是一个非常重要的问题。

你的scanf/fgets组合实际发生的事情是,scanf获取整数,但没有读取在该数字末尾输入的换行符,因此第一个fgets选择了这个。

ISO标准状态它因而(在指定的序列中):

输入的空白​​字符(由isspace为函数指定)被跳过,除非本说明书中包括[,C或N中符。

从流中读取输入项目,除非规范包含n说明符。输入项被定义为输入字符的最长序列,其不超过任何指定的字段宽度,并且是匹配输入序列的或者是匹配输入序列的前缀。

输入项目保持未读状态后的第一个字符(如果有的话)。

第一段和最后一段很重要。第一种意思是跳过前导空格,最后意思是尾随空格留在输入流中以待稍后读取。


不过,我会告诉你什么可能搞砸了(根据您输入线的长度),这是事实,你分配每个a[i] 50个字符空间,然后读取最多100个字符进去。这就是未定义的行为。


如果你想正确处理缓冲区的大小强大的输入解决方案,检测太长线,扔掉那些线的余等见this answer

另外,如果你想模仿与非基于行的scanf线为基础的行为(而你确定你的线总是小于100字节),你可以改变:

scanf("%d", &num); 

纳入:

char junk[100]; 
scanf ("%d", &num); 
fgets (junk, sizeof (junk), stdin); 

因此它抓住并抛弃其余的线。

而且您应确保fgets的最大大小参数与可用内存量相匹配(例如在上面的代码中使用sizeof)。

另外一件事,请不要将代码乘以sizeof(char) - 该值为总是 1按照标准复杂化。