2016-11-11 121 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])); 
}