2012-03-09 18 views
2

私はC言語ではかなり新しく、ポインタを使うのとかなり混乱します。C - 文字列から単語を抽出する

私はASCII文字列から単語を抽出しようとしています。 たとえば、文字列が@@ Hello..world >>の場合、文字列から "Hello"と "world"という単語を取り出し、それらをリンクリストに追加したいとします。

単語は任意の文字列として定義され、各単語は最大64バイトです。また、関数isspace()がゼロ以外の値を返す文字は空白と見なされます。

基本的には、fscanfを使用してファイルから文字列をスキャンしてから、各文字列に対して関数read_words(char * s)を呼び出して適切な単語を文字列から取り出し、リンクリストに追加しますつかいます。

ここで私のコードは、ポインタと関係があるエラーを投げているようです。

struct node { 
    char *val; 
    struct node *next; 
    int count; 
} *words = NULL; 


void read_words(char *s) 
{ 
    struct node *tmp; 
    char word[64+1]; 
    int i, check, wordStarted = 0, count = 0; 

    for (i = 0; s[i] != '\0'; i++) 
    { 
      if ((isspace(s[i]) != 0) || !isalpha(s[i])) 
      { 
        if (wordStarted == 1) 
        { 
          check = check_list(word); 
          if (check != 1) { 
            word[count] = '\0'; 
            tmp = malloc(sizeof(struct node)); 
            tmp->val = word; 
            tmp->count = 1; 
            tmp->next = words; 
            words = tmp; 
          } 
          count = 0; 
          wordStarted = 0; 
        } 
      } 
      else 
      { 
        word[count++] = s[i]; 
        wordStarted = 1; 
      } 
    } 

} 

これについてのお手伝いをさせていただきます。

ありがとうございました!

+0

は 'strtok'を試してみてください。任意の数の分割文字に基づいて文字列を部分に分割します。 – chris

+0

コードを[デバッグ](http://en.wikipedia.org/wiki/GNU_Debugger)しようとしましたか? – Zeta

+0

check_list()の実装を投稿してください –

答えて

3

独自のアルゴリズムを実装する代わりに、文字列をトークン化してリンクされたリストに追加することをお勧めします。 strtokref)を使用してください。

例..上記のリンクから:

​​

出力:

Splitting string "- This, a sample string." into tokens: 
This 
a 
sample 
string 
0

ANSI C.

使用はstrtok()のためのよりよい解決策 it

  1. 原点配列が変更されます。
  2. "\ n"、 "\ t"などの文字は無視されます。

次の試してみて、詳細についてはコメントをお読みください。

#include <stdio.h>  // printf 
#include <string.h>  // strlen, strncpy 
#include <ctype.h>  // isalnum 
#include <stdlib.h>  // malloc, calloc 

/* 
    A logical type 
*/ 
typedef enum { 
    false, 
    true, 
} bool; 


/* 
    A Struct for hold 2D-array with count items 
*/ 
typedef struct _ListWithLength { 
    char **list; 
    size_t length; 
} ListWithLength; 


/* 
    Parse a text and return pointer to a ListWithLength words and count it 
*/ 
ListWithLength* getWords(char *text) { 

    // a variable for count words 
    int count = 0; 

    // keep length of the text 
    size_t text_len = strlen(text); 

    // a flag indicating the a beginning of a word 
    bool new_word = false; 

    // an index of a start found a word 
    int index_start_word = 0; 

    // 2D-array for found word 
    // it will be same memory size as the original text 
    char **words = malloc(text_len * sizeof(char)); 

    for (int i = 0; i <= text_len; ++i) { 

     // if found ascii letter or digits and new no traced early 
     // keep index of beginning a new word 
     // and change the flag 
     if (isalnum(text[i]) != 0) { 
      if (new_word == false) { 
       new_word = true; 
       index_start_word = i; 
      } 

     // if it is not ascii letter or digits and a word traced early 
     // it means the word ended 
     } else { 
      if (new_word == true) { 

       // allocate a memory for a new word in the array of words 
       words[count] = malloc(i - index_start_word * sizeof(char) + 1); 

       // copy the found word from the text by indexes 
       strncpy(words[count], text + index_start_word, i - index_start_word); 

       // change the flag 
       new_word = false; 

       // increase the counter of words 
       count++; 
      } 
     }; 
    } 

    // bind the found words and it count to a structure and return it 
    ListWithLength *list_with_length = malloc(sizeof(ListWithLength)); 

    list_with_length->length = count; 
    list_with_length->list = words; 

    return list_with_length; 
} 


/* 
    Print information of a ListWithLength 
*/ 
void printListWithLength(ListWithLength *list_with_length) { 
    printf("Total items: %li\n", list_with_length->length); 
    puts("----------------------"); 
    for (int i = 0; i < list_with_length->length; ++i) { 
     printf("%d. %s\n", i + 1, list_with_length->list[i]); 
    } 
} 


int main(int argc, char const *argv[]) 
{ 

    char c_keywords[300] = "auto else long switch\ 
    break\t enum \t register typedef\ 
    \ncase extern, return union\ 
    ?char float. short unsigned\ 
    const !for signed void\ 
    continue goto sizeof volatile\ 
    .default???? if static while\ 
    do int struct,,,, _Packed\ 
    double......."; 

    ListWithLength *list_with_length = getWords(c_keywords); 
    printListWithLength(list_with_length); 

    return 0; 
} 

コンパイルし、その結果を参照してください。

$ gcc -Wall -ansi -std=c11 -o main main.c 
$ ./main 
Total items: 33 
---------------------- 
1. auto 
2. else 
3. long 
4. switch 
5. break 
6. enum 
7. register 
8. typedef 
9. case 
10. extern 
11. return 
12. union 
13. char 
14. float 
15. short 
16. unsigned 
17. const 
18. for 
19. signed 
20. void 
21. continue 
22. goto 
23. sizeof 
24. volatile 
25. default 
26. if 
27. static 
28. while 
29. do 
30. int 
31. struct 
32. Packed 
33. double 
関連する問題