2017-03-02 28 views
0

掃描我的工作是要讀的字符串的多條線路,並將它們整理到字符串數組程序時忽略換行字符。scanf函數從輸入文件

我試圖手動讀取第一行和循環應該退出,一旦讀取新行字符「\ n」。當我在終端中手動輸入字符串,但在輸入文件中讀取(通過終端)時,它不會讀取換行符,並且循環繼續。

char array[20][20]; 
char letter = 'a'; 
for (int i = 0; letter != '\n'; i++) { 
    scanf("%s",array[i]); //store the word into an array of words 
    printf("Scanned %s\n",array[i]); 
    scanf("%c",&letter);  //look for space or new line character 
} 

它可以從文件中讀取數據時,當我手動輸入這樣的文字,而不是:

word word1 word2 
word3 word4 word5 

當手動輸入,我將進入第一線,「字字詞1字詞2」,打輸入,它會掃描該行並結束程序。

當使用文件,則返回:

$ ./potw18 < input.txt 
Scanned word 
Scanned word1 
Scanned word2 
Scanned word3 
Scanned word4 
Scanned word5 
Scanned 
Scanned ▒ 
Scanned 
Scanned ▒ 
Scanned 
Scanned ▒8.▒ 
Scanned 
Scanned ▒8.▒ 
Scanned 

而且仍在繼續。

+0

請問您可以在這裏發佈'array'的定義嗎? –

+1

請將[mcve]和示例文本文件一起發佈 –

+0

使用示例和數組定義更新了OP。 –

回答

1

你可以只讀取fgets(3)每一行,直到它返回NULL,這表明線是沒有讀過。你也可以使用getline(3)來做到這一點,這是一個POSIX C函數,旨在有效地讀取行。在獲取每個字而言,可以使用strtok(3)strchr(3)在上線的每個空間解析每個單詞,並安全地把它添加到您的二維字符數組。使用scanf()只就更難做到這一點,如@邁克爾伯爾的後徹底有道理的。

下面是從文件中讀取線與stdin,並存儲在一個字符串數組所找到的字的基本示例:

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

#define NUMWORDS 20 
#define WORDLEN 20 
#define LINESIZE 100 

#define WORDSIZE(x) (sizeof x[0]) 
#define ARRSIZE(x) (sizeof x/sizeof x[0]) 

int main(void) { 
    char array[NUMWORDS][WORDLEN]; 
    char line[LINESIZE]; 
    char *word = NULL, *currline = NULL; 
    const char *delim = " \n"; 
    size_t numwords = 0; 

    while (fgets(line, sizeof line, stdin) != NULL) { 
     currline = line; 

     word = strtok(currline, delim); 
     while (word != NULL) { 
      if (numwords < ARRSIZE(array) && strlen(word) < WORDSIZE(array)) { 
       strcpy(array[numwords], word); 
       numwords++; 
      } 
      word = strtok(NULL, delim); 
     } 
    } 

    for (size_t i = 0; i < numwords; i++) { 
     printf("array[%zu] = %s\n", i, array[i]); 
    } 

    return 0; 
} 

上面代碼使用strtok()米它是一個字符串功能你必須小心。這裏最好使用strchr()

+0

這工作完美。感謝您的幫助! –

-1
char array[20][20]; 
char letter = 'a'; 
for (int i = 0; letter != '\n'; i++) { 
    gets(array); //store the word into an array of words 
    letter = array[i]; 
    scanf("%c",&letter);  
} 

通過使用gets它應該工作。

+2

'gets(array);'是現在已經過時的函數'gets()'的錯誤用法。自C11以來,該功能已從C中刪除,過去6年不應用於新代碼。 – chux

+1

'letter = array [i];',我不認爲這是有道理的。也可以(即使過時)讀取整個行。他將不得不在空間分開。 –

2

我預測文件input.txt具有:

  • 在第一行的末尾空格(比換行符其它),和
  • 是相似的或僅僅在末端不具有換行第二行

由於第一個點,scanf("%c",&letter);讀取的不是換行符(例如空格),所以程序繼續到第二行。

讀完最後一個單詞後,文件中沒有任何文件可以讀取scanf(),因此每次調用它時都會返回一個錯誤。該計劃不檢查這些錯誤,並盲目跋涉。

個人而言,我不使用scanf()除了快速正葷一斷碼的一個巨大的風扇。對於任意輸入而言,這太容易出錯。我建議將行讀入緩衝區,然後使用sscanf()strtok()或更好的解析方法(基本上,類似於@ RoadRunner的答案所述)。

+0

這是一個很好的理論,但我已經仔細檢查了輸入文件,除了第一行和第二行之間的換行符之外沒有空格。 –

0

使用scanf掃描字符並使用isspace測試字符是否爲空格。 break當字符爲換行符時。
如果字符不是空白,則使用ungetc將字符替換爲輸入流,然後使用scanf這個詞。 %19s可防止將太多字符掃描到陣列中。

#include <ctype.h> //header for isspace 

while (scanf ("%c", &letter) == 1) { 
    if (isspace (letter)) { 
     if (letter == '\n') { 
      break; 
     } 
    } 
    else { 
     ungetc (letter, stdin);//replace letter in input stream 
     if (scanf ("%19s", array[i]) == 1) 
     { 
      i++; 
      if (i >= 20) { 
       break; 
      } 
     } 
    } 
}