2012-03-09 8 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

Вы пытались выполнить [debug] (http://en.wikipedia.org/wiki/GNU_Debugger) свой код? – Zeta

+0

, пожалуйста, разместите реализацию check_list() –

ответ

3

Вы хотите, чтобы токенизировать строку вместо реализации своего собственного алгоритма и добавить части в свой список. Использовать strtok (ref).

Из приведенной выше ссылке .. Пример:

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

int main() 
{ 
    char str[] ="- This, a sample string."; 
    char * pch; 
    printf ("Splitting string \"%s\" into tokens:\n",str); 
    pch = strtok (str," ,.-"); 
    while (pch != NULL) 
    { 
    printf ("%s\n",pch); 
    pch = strtok (NULL, " ,.-"); 
    } 
    return 0; 
} 

Выход:

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; 
} 

Compile и видеть результат:

$ 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 
Смежные вопросы