2010-02-15 47 views
6

Tôi đang cố đếm số từ trong một tệp bằng strtok().Hành vi strtok() bất ngờ

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

Điều này gây ra vòng lặp vô hạn. Tại sao?

+0

bằng cách sử dụng 'fgets (sLine, STRMAX, fptr)' không 'STRMAX-1' – user102008

Trả lời

8

Bạn cần hai cuộc gọi, lần thứ hai bạn cần chuyển số NULL đến strtok.

Thay vì:

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

làm

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

Edit: Full source:

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

Với tập tin đầu vào của bạn, tôi nhận được kết quả như 16.

Chỉnh sửa # 2: Sửa đổi nguồn của bạn:

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

Tôi nhận được cùng một kết quả - 16.

+0

Điều đó không phản ánh chính xác số lượng từ trong tập tin văn bản của tôi, theo như tôi có thể nói. – Pieter

+1

@Pieter: Bạn cần gọi 'strtok' lần thứ hai. Đó là cách nó hoạt động. Và tham số đầu tiên phải là 'NULL' cho cuộc gọi thứ hai (thường được bao bọc trong một vòng lặp). Bạn có thể cần phải sắp xếp lại số lượt truy cập. Mã tôi đăng được dự định để chỉ cách gọi 'strtok'. – dirkgently

+0

@Pieter "theo như tôi có thể nói" là một chút phản hồi mơ hồ, hãy thử với một tệp văn bản có số từ đã biết và sử dụng nó để xác minh thời gian hoặc không giải pháp hoạt động. –

Các vấn đề liên quan