2014-02-24 2 views
2

저는 텍스트 파일을 구문 분석하려고하며 각 단어를 키로 단어와 함께 값과 해시 테이블에 추가하려고합니다. 이 문제는 읽기 부분 인 것으로 입증되고 있습니다. 파일은 구두점과 특수 문자가 포함되어있어 매우 큰 "일반"텍스트 파일입니다. 나는 단어 경계로 읽은 모든 비 알파벳 문자를 다뤄야한다. 나는 기본적인 것을 이것으로 가고 있습니다 그러나C - 단어 경계로 알파벳이 아닌 문자를 읽으십시오.

char buffer[128]; 
while(fscanf(fp, "%127[A-Za-z]%*c", buffer) == 1) { 
    printf("%s\n", buffer); 
    memset(buffer, 0, 128); 
} 

, 실제로 공백 앞에 비 알파벳 문자를 명중 할 때마다 초크 (예를 들어,로 읽을 것이다 "는, 고양이) (갈색이었다" "가 고양이가 "). 나는 그 문제가 그 코드와 어떤 관련이 있는지 알고 있지만, 그 문제를 해결하는 방법을 모르겠습니다. 전체 라인을 읽고 수동으로 파싱하는 것이 더 낫지 않습니까? scanf을 시도하고 있습니다. 왜냐하면이 형식 문자열을 사용하여 수행 할 수있는 미니 정규식에 대한 좋은 후보라고 느꼈기 때문입니다.

+5

% "[A-Za-z] % * [^ A-Za-z]"'쉬운 수정으로. – BLUEPIXY

+0

감사! 그것은 내가 필요로했던 것을했다. –

+1

fscanf (fp, "% 127 [A-Za-z]", 버퍼) == {while (fscanf (fp, "% * *^A-Za-z" '% 127 [A-Za-z] % * [^ A-Za-z] "'는 아닙니다. 두 접근법 모두 선택적 글자 그룹으로 처리 할 수 ​​있습니다. 그 뒤에는 비 문자가 뒤 따른다. – chux

답변

4

isalpha(), fgetc() 및 간단한 상태 기계의 사용을 제안하십시오.

#include <assert.h> 
#include <ctype.h> 
#include <stdio.h> 

int AdamRead(FILE *inf, char *dest, size_t n) { 
    int ch; 
    do { 
    ch = fgetc(inf); 
    if (ch == EOF) return EOF; 
    } while (!isalpha(ch)); 

    assert(n > 1); 
    n--; // save room for \0 
    while (n-- > 0) { 
    *dest++ = ch; 
    ch = fgetc(inf); 
    if (!isalpha(ch)) break; 
    } 

    ungetc(ch, inf); // Add this is something else may need to parse `inf`. 
    *dest = '\0'; 
    return 1; 
} 

char buffer[128]; 
while(AdamRead(fp, buffer, sizeof buffer) == 1) { 
    printf("%s\n", buffer); 
} 

참고 : "%127[A-Za-z]%*[^A-Za-z]" 경로를 이동하려면, 코드가 선도가 아닌 문자를 다루는 한 번 fscanf(fp, "*[^A-Za-z]"); 시작해야 할 수 있습니다.

+0

왜 우리는'ungetc (ch, inf);'가 필요한가? 'ch'는 영문자가 아닌 문자로 다음 번에'AdamRead '호출에서 버려 질 것입니다. – ajay

+0

@aday'ungetc (ch, inf)'는 비 문자 스캔을 시작할 것으로 예상되는'AdamRead()'다음에 _different_ 함수가 호출되면 유용합니다. – chux

+1

@ajay 또한'ch' _ 문자가 될 수도 있습니다. 'n'이 0이되어 while 루프가 중단되었을 수 있습니다. 버퍼가 채워질 때 수행 할 작업에 대한 OP 정의가 열려 있습니다. 이 잠재적 인 편지를 되돌려 놓으면 다음 함수 호출에서 읽을 기회가 생깁니다. – chux

0

덧글에 언급 된 것과는 다른 방법이 있습니다. 비록 그것이 더 나을지 모르겠다. fgets을 사용하여 파일에서 행을 읽고 POSIX 함수 strtok_r을 사용하여 행을 토큰화할 수 있습니다. 여기에 r은 thread-safe하게 만드는 재진입 함수임을 의미합니다. 그러나 파일에서 행이 가질 수있는 최대 길이를 알아야합니다. 그것은 다른 목적을 위해 필요한 경우 당신이 그것의 사본을 보관해야하므로

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

#define MAX_LEN 100 

// in main 

char line[MAX_LEN]; 
char *token; 
const char *delim = "[email protected]#$%^&*"; // all special characters 
char *saveptr;  // for strtok_r 
FILE *fp = fopen("myfile.txt", "r"); 

while(fgets(line, MAX_LEN, fp) != NULL) { 
    for(; ; line = NULL) { 
     token = strtok_r(line, delim, &saveptr); 
     if(token == NULL) 
      break; 
     else { 
      // token is a string. 
      // process it 
     } 
    }  
} 

fclose(fp); 

strtok_r는, 첫 번째 인자 line을 수정합니다.

관련 문제