2015-04-05 22 views
-1

文本文件包含: 「由查爾斯·達爾文我想從文件中讀取包含段落文本,分詞,然後分配到一個數組

從雙城記開幕這是最好的時代,這是最壞的時代,這是時代的智慧 ,這是愚蠢的時代。那是 信仰的時期,那是懷疑的時期「。

我不知道我錯在哪裏。

#include <stdio.h> 
#include <stdlib.h> 
#include<string.h> 
#define max_words 20 
#define max_story_words 1000 
#define max_word_length 80 

int main() 
{ 
    char story[max_story_words][max_word_length],ch; 
    int num_words=1; 
    FILE *file_story=fopen("TwoCitiesStory.txt", "r"); 
    if (file_story==NULL) 
     printf("Unable to open %s\n","TwoCitiesStory.txt"); 
    else{ 
     ch=fgetc(file_story); 
     while(ch!=EOF){ 
      if(ch==' '||ch=='\n') 
       num_words++; 
       ch=fgetc(file_story); 
     } 
     int i=0; 
     //assigning each words to story[i] 
     while (i<max_story_words && fgets(story[i], max_word_length, file_story) != NULL) { 
      if(story[i][strlen(story[i])-1]=='\n'||story[i][strlen(story[i])-1]==' '||story[i][strlen(story[i])-1]==','|| 
       story[i][strlen(story[i])-1]=='!'||story[i][strlen(story[i])-1]=='.'||story[i][strlen(story[i])-1]==':'|| 
       story[i][strlen(story[i])-1]==';'||story[i][strlen(story[i])-1]=='?'||story[i][strlen(story[i])-1]=='-'|| 
       story[i][strlen(story[i])-1]=='?') 
       //remove a newline here 
       story[i][strlen(story[i])-1]='\0'; 
      i++; 
     } 
     for(int i=0;i<num_words;i++){ 
     printf("story[%d]: %s\n",i,story[i]); 
     } 
     printf("%d",num_words); 
    } 
     return (EXIT_SUCCESS); 
} 

回答

1

與您的代碼的最大問題是:(1)您未退file_story你讀的流EOF計數話後,和(2)你不記號化的fgets讀入字,每個線然後分配到story[i]fgets會一次讀取整行(這是你想要的)。但是,您可以根據自己的意願將每行分隔成單詞並刪除標點符號。

要做到這一點,你想要麼strtokstrsepstrtok非常適合這項工作。仔細選擇分隔列表將允許您將行分成單詞並同時將單詞分配給story[i]

此外,對於天上的緣故,讓你的代碼的呼吸......是的,你們可以一起補習的一切,並刪除所有的空間,這是接近混淆在我的書。間距線和擴展語法有點讓你的代碼更具可讀性。 (你甚至可能會發現它有助於讓你更容易編碼)但每個人都有自己的代碼。如果你喜歡它濃縮,那很好。

查看以下內容,讓我知道如果你有問題。我更改了代碼以將文件名作爲參數,所以它不是硬編碼的。您運行程序並將文件名放在命令行中。祝你好運:

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

#define max_words 20 
#define max_story_words 1000 
#define max_word_length 80 

int main (int argc, char **argv) 
{ 
    if (argc < 2) { 
     fprintf (stderr, "Error: insufficient input, usage: %s filename\n", argv[0]); 
     return 1; 
    } 

    char story[max_story_words][max_word_length] = {{0}}; 
    char line[max_story_words] = {0}; 
    char *p; 
    char ch = 0; 
    char *punct="\n ,!.:;?-"; 
    int num_words = 1; 
    int i = 0; 
    FILE *file_story = fopen (argv[1], "r"); 

    if (file_story==NULL) { 
     printf("Unable to open '%s'\n",argv[1]); 
     return (EXIT_FAILURE); 
    } 

    /* count words */ 
    while ((ch = fgetc (file_story)) != EOF) { 
     if (ch == ' ' || ch == '\n') 
      num_words++; 
    } 

    /* you already read file_story to EOF, so you must rewind to 
     reset the EOF condition and place the file pointer at the start */ 
    rewind (file_story); 

    i = 0; 
    /* read each line in file */ 
    while (fgets (line, max_word_length, file_story) != NULL) 
    { 
     /* tokenize line into words removing punctuation chars in punct */ 
     for (p = strtok (line, punct); p != NULL; p = strtok (NULL, punct)) 
     { 
      /* convert each char in p to lower-case with tolower */ 
      char *c = p; 
      for (; *c; c++) 
       *c = tolower (*c); 

      /* manually convert each char in p to lower-case */ 
      // char *c = p;  /* save start address of p */ 
      // for (; *c; c++) 
      //  if ('A' <= *c && *c <= 'Z') 
      //   *c += 32; 

      /* copy token (word) to story[i] */ 
      strncpy ((char *)story[i], p, strlen (p)); 
      i++; 
     } 
    } 

    /* output array */ 
    for(i = 0; i < num_words; i++) 
     printf ("story[%d]: %s\n", i, story[i]); 

    printf("\ntotal words: %d\n\n",num_words); 

    return (EXIT_SUCCESS); 
} 

上圖:我選擇包括使用tolower的字符轉換爲小寫字母的代碼。如果你剛剛學習C語言,那麼最好在開始編寫自己的代碼之前熟悉所有的字符處理函數。 (我已經離開了包括手動轉換,但評論,所以你可以借鑑一下爲好)

+0

感謝您的幫助。我只是一個初學者。如果我想在存儲到數組之前將單詞的所有字母轉換爲小寫,該怎麼辦? (int i = 0; i = 65 && story [j] <= 90) story [j] + = 32;} } @david – 2015-04-05 14:28:19

+0

將'#include '作爲頭文件,然後更改'strncpy((char *)story [i],p,strlen(p));'將所有字符轉換爲較低值。我會更新這個例子。你已經做出了正確的選擇來學習C,沒有其他人提供C做的權力和控制權,但是擁有這樣強大的權力是責任。學習C是一個旅程,而不是一場競賽。旅行愉快。 – 2015-04-05 16:00:41

+0

另外,手動完成時不需要添加'#include '。看看ASCII字符[** ASCII碼 - 擴展ASCII表**](http://www.ascii-code.com/)。請注意,所有小寫字符的值都比「大寫」字符的「32」更大。因此,您只需檢查字符串中的每個字母,如果它是大寫字母,則將「32」添加到它的值以將其更改爲小寫字母。 (在'ctype.h'中也有一個'tolower(char p)'函數,你可以使用任何一種方法('add 32'或者爲你的字符串中的每個字符調用'tolower(ch)') – 2015-04-05 16:10:59

相關問題