2016-11-11 98 views
6

我想读取可能包含或不包含空格前缀的字符串。 “你好,世界”。通过用户输入的数字选择菜单进行以下操作。这只是我试图做的一个小副本。阅读C中的空格字符串

#include <stdio.h> 
#include <string.h> 

int main(void){ 
    char line[3][80]; 

    strcpy(line[0],"default line 1\n"); 
    strcpy(line[1],"default line 2\n"); 
    strcpy(line[2],"default line 3\n"); 

    for(int i = 0; i < 3; i++){ 
    printf("%s", line[i]); 
    } 

    int option = 0; 
    printf("would you like to replace line 1? (1 for yes)\n"); 
    scanf("%d",&option); 
    if(option==1){ 
    printf("what would you like to replace the line with?\n"); 
    fgets(line[0],strlen(line[0]),stdin); 
    } 

    for(int i = 0; i < 3; i++){ 
    printf("%s", line[i]); 
    } 
} 

为什么我进入1后更改线路,它打印问我想要什么来取代它,会自动进入什么然后打印与第一个为空字符串的声明?

我也已经尝试阅读sscanf("%[^\n\t]s", line[0]);没有任何运气的行。有任何想法吗?

+0

我猜想,'fgets'读一个EOF(文件结束)作为流的第一个字符。 – 2016-11-11 16:09:54

+0

我很肯定,在询问用户是否想要替换该行时,它与'scanf(“%d”,&option)“有关系,但是我不知道是否有办法解决这个问题。 – TheBoxOkay

+2

与你的问题没有直接关系,但'strlen(line [0])'应该被'80'替代。缓冲区的大小不是它所包含的字符串的长度,而是这里“80”的缓冲区的总长度。 –

回答

10

这是因为

scanf("%d",&option); 

离开\n字符标准输入,并通过第一次调用fgets()消耗。这就是为什么最好完全避免C中的scanf()

你可以解决它:

scanf("%d",&option); 
    getchar(); /* consume the newline */ 

但我建议使用fgets()阅读option以及然后你可以使用strtol()把它转换成一个整数。

请注意,该声明不可能是您想要的(这限制了您可以读入line[0]的内容)。

fgets(line[0],strlen(line[0]),stdin); 

你可能想用的是:

fgets(line[0],sizeof line[0],stdin); 

,这样就可以读取高达的line[0]实际大小。

请阅读的C FAQ中还有:http://c-faq.com/stdio/scanfprobs.html

+3

我确认,'scanf'很糟糕,这些问题很常见。谷歌_scanf是evil_(没有玩笑)的更多信息。 –

+0

非常感谢,完美的工作! – TheBoxOkay

2

你的问题是,'\n'焦炭左转进入stdinfgets消耗。

我建议你总是使用fgets读的投入,所以

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

int main(void) 
{ 
    char line[3][80]; 
    char temp[3]; 

    strcpy(line[0],"default line 1\n"); 
    strcpy(line[1],"default line 2\n"); 
    strcpy(line[2],"default line 3\n"); 

    for(int i = 0; i < 3; i++){ 
     printf("%s", line[i]); 
    } 

    int option = 0; 
    printf("would you like to replace line 1? (1 for yes)\n"); 
    fgets(temp,sizeof(temp),stdin); 
    option = atoi(temp); 

    if(option==1){ 
     printf("what would you like to replace the line with?\n"); 
     fgets(line[0],sizeof(line[0]),stdin); 
    } 

    for(int i = 0; i < 3; i++){ 
    printf("%s", line[i]); 
    } 
} 
3

使用fgets()通常似乎比scanf()纠缠容易出错少,但如果用户输入一个字符串,只要或长于指定的最大字符数,则直到并包括换行符的任何额外字符将保留在输入流中。出于这个原因,我通常编写自己的gets()版本来获取用户的输入字符串,如果我需要数字输入,我使用strtol()。这里有这样的功能的例子:适用于有机磷农药问题

char * s_gets(char *st, int n) 
{ 
    char *ret; 
    int ch; 

    ret = fgets(st, n, stdin); 
    if (ret) { 
     while (*st != '\n' && *st != '\0') 
      ++st; 
     if (*st) 
      *st = '\0'; 
     else { 
      while ((ch = getchar()) != '\n' && ch != EOF) 
       continue;   // discard extra characters 
     } 
    } 
    return ret; 
} 

,我可能会做这样的事情:

#include <stdlib.h>    // for strtol() 

... 

char buf[80]; 
int option = 0; 

printf("would you like to replace line 1? (1 for yes)\n"); 
s_gets(buf, sizeof(buf)); 
option = strtol(buf, NULL, 10); 

if(option==1){ 
    printf("what would you like to replace the line with?\n"); 
    s_gets(line[0],sizeof(line[0])); 
}