2010-02-15 2 views
6

Я пытаюсь подсчитать количество слов в файле с помощью strtok().Неожиданное поведение strtok()

/* 
* code.c 
* 
* WHAT 
*  Use strtok() to count the number of words in a file. 
*/ 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#define STRMAX 128 

int main() { 
    /* Declarations */ 
    FILE* fptr; 
    int iCntr = 0; 
    char sLine[STRMAX]; 
    char* cPToken; 

    /* Read file */ 
    /* Error handler */ 
    if ((fptr = fopen("/home/ubuntu/Dropbox/Unief/C/H18/Opdr01/Debug/test.txt", "r")) == NULL) { 
     printf("Couldn't read test.txt.\n"); 
     exit(0); 
    } else { 
     while (fgets(sLine, STRMAX-1, fptr) != NULL) {     /* Read line */ 
      while ((cPToken = strtok(sLine, ".,; !?\r\n")) != NULL) { /* Split into words */ 
       iCntr++; 
      } 
     } 
     printf("Number of words: %d\n", iCntr); 
    } 

    /* Always clean up your mess */ 
    fclose(fptr); 
    return 0; 
} 

Это вызывает бесконечный цикл. Зачем?

+0

кстати использовать 'fgets (Sline, STRMAX, fptr)' 'не STRMAX-1' – user102008

ответ

8

Вам нужно два вызова, во второй раз вам необходимо передать NULL в strtok.

Вместо:

while ((cPToken = strtok(sLine, ".,; !?\r\n")) != NULL) { /* Split into words */ 
       iCntr++; 
} 

сделать

cPToken = strtok(sLine, ".,; !?\r\n"); 
while (cPToken != NULL) { /* Split into words */ 
    iCntr++; /* we have a valid word */ 
    cPToken = strtok(NULL, ".,; !?\r\n");   
} 

Edit: Полный источник:

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

size_t wcount(const char *fname, const char *delim) { 
    char buf[ 512 ]; 
    size_t nw = 0; 
    FILE *fp = fopen(fname, "r"); 
    if (fp) { 
     while (fgets(buf, sizeof buf, fp) != NULL) { 
      for (char *w = strtok(buf, delim); w; w = strtok(NULL, delim)) 
       nw++; 
     } 
     fclose(fp); 
    } 
    return nw; 
} 

int main(int argc, char* argv[]) 
{ 
    printf("%u\n", wcount("C:\\sample.txt", ".,; !?\r\n")); 
    return 0; 
} 

С вашего входного файла, я получаю результат в 16

Редактировать # 2: изменение источника:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#define STRMAX 128 

int main() { 
    /* Declarations */ 
    FILE* fptr; 
    int iCntr = 0; 
    char sLine[STRMAX]; 
    char* cPToken; 

    /* Read file */ 
    /* Error handler */ 
    if ((fptr = fopen("c:\\test.txt", "r")) == NULL) { 
     printf("Couldn't read test.txt.\n"); 
     exit(0); 
    } else { 
     while (fgets(sLine, STRMAX-1, fptr) != NULL) {     /* Read line */ 
      cPToken = strtok(sLine, ".,; !?\r\n"); 
      while (cPToken != NULL) { /* Split into words */ 
       iCntr++; 
       cPToken = strtok(NULL, ".,; !?\r\n"); 
      } 
     } 
     printf("Number of words: %d\n", iCntr); 
    } 

    /* Always clean up your mess */ 
    fclose(fptr); 
    return 0; 
} 

я получаю тот же результат - 16.

+0

Это не точно отражают количество слов насколько мне известно, в текстовом файле. – Pieter

+1

@Pieter: Вам нужно называть 'strtok' второй раз. Вот как это работает. И первый параметр должен быть «NULL» для второго вызова (который обычно завершается в цикле). Возможно, вам потребуется изменить шаг счетчика. Код, который я опубликовал, должен был показать, как вызывать только 'strtok'. – dirkgently

+0

@Pieter «насколько я могу сказать» - это немного смутная обратная связь, попробуйте текстовый файл с известным количеством слов и используйте его для проверки того, работает ли решение. –

Смежные вопросы