2013-04-07 2 views
3

현재 다음 코드를 사용하여 텍스트 파일의 각 단어를 검사하고 변수에 넣은 다음 다음 단어로 이동하기 전에 몇 가지 조작을 수행합니다. 괜찮아요,하지만 A-Z/a-z. 아래에 속하지 않는 모든 문자를 제거하려는 경우 예 : "he5llo" 입력 한 경우 출력을 "hello" 수 있습니다. fscanf을 수정하지 못하면 스캔 한 변수에이를 수행하는 방법이 있습니까? 감사.C에서 fscanf 문자열의 특수 문자 제거하기

while (fscanf(inputFile, "%s", x) == 1) 
+0

'난 것이 잠재적 인 버퍼 오버런입니다. 'char x [100]'을 가지고있을 때 항상 예를 ​​들어'fscanf (inputFile, "% 99s", x)'를 사용해야합니다. – hyde

답변

3

에 포함 된 모든 문자를 검사 isalpha() 기능을 사용할 수 있습니다. 이해를 위해서 먼저 간단한 버전 :

// header needed for isalpha() 
#include <ctype.h> 

void condense_alpha_str(char *str) { 
    int source = 0; // index of copy source 
    int dest = 0; // index of copy destination 

    // loop until original end of str reached 
    while (str[source] != '\0') { 
    if (isalpha(str[source])) { 
     // keep only chars matching isalpha() 
     str[dest] = str[source]; 
     ++dest; 
    } 
    ++source; // advance source always, wether char was copied or not 
    } 
    str[dest] = '\0'; // add new terminating 0 byte, in case string got shorter 
} 

그것은, isalpha() 테스트와 일치하는 문자를 복사 건너 뛰는 때문에하지 않는 사람들을 제거, 현재 위치에서 문자열을 통해 이동합니다. 코드를 이해하려면 C 문자열이 단지 char 배열이고 바이트 값 0이 문자열의 끝을 표시한다는 사실을 깨닫는 것이 중요합니다. 또 다른 중요한 세부 사항은 C 배열과 포인터가 여러 가지 (전부는 아님!) 방법으로 동일하다는 것입니다. 따라서 포인터는 배열과 마찬가지로 색인을 생성 할 수 있습니다. 또한이 간단한 버전은 문자열이 실제로 변경되지 않는 경우에도 문자열의 모든 바이트를 다시 쓰게됩니다.


그런 다음 전용 메모리를 할 것 매개 변수로 전달 필터 기능을 사용하여,보다 완벽한 기능을 갖춘 버전, str을 변경하는 경우, 기록 및 대부분의 라이브러리 문자열 함수와 같은 str에 대한 포인터를 반환하는 것은 수행

char *condense_str(char *str, int (*filter)(int)) { 

    int source = 0; // index of character to copy 

    // optimization: skip initial matching chars 
    while (filter(str[source])) { 
    ++source; 
    } 
    // source is now index if first non-matching char or end-of-string 

    // optimization: only do condense loop if not at end of str yet 
    if (str[source]) { // '\0' is same as false in C 

    // start condensing the string from first non-matching char 
    int dest = source; // index of copy destination 
    do { 
     if (filter(str[source])) { 
     // keep only chars matching given filter function 
     str[dest] = str[source]; 
     ++dest; 
     } 
     ++source; // advance source always, wether char was copied or not 
    } while (str[source]); 
    str[dest] = '\0'; // add terminating 0 byte to match condenced string 

    } 

    // follow convention of strcpy, strcat etc, and return the string 
    return str; 
} 

예 필터 함수 :

int isNotAlpha(char ch) { 
    return !isalpha(ch); 
} 

예 호출

char sample[] = "1234abc"; 
condense_str(sample, isalpha); // use a library function from ctype.h 
// note: return value ignored, it's just convenience not needed here 
// sample is now "abc" 
condense_str(sample, isNotAlpha); // use custom function 
// sample is now "", empty 

// fscanf code from question, with buffer overrun prevention 
char x[100]; 
while (fscanf(inputFile, "%99s", x) == 1) { 
    condense_str(x, isalpha); // x modified in-place 
    ... 
} 

참조 :

읽기 int isalpha (int c); 수동 : C는 알파벳 문자인지

확인합니다.
반환 값 :
실제로 c가 알파벳 문자 인 경우 0과 다른 값 (즉, true)입니다. 0 일 경우 (즉, 거짓)

+1

@RandyHoward 만약 당신이 잘못 생각한 대신 어떻게 응답해야합니다 .. 하이 드는 OP가 숙제 나 자기 학습 목적을 요구하는지 모르겠다. hyde 그냥 돕고. –

+0

@hyde 나는 OP가 도움이 될 수 있도록 항상 코드를 설명 할 것을 제안합니다. –

+0

답변을 건네 주지만, 내가 제시 한 예를 완전히 이해하지는 못하지만, 제게 사용하기 위해 투쟁 할 것입니다. 접근. – user2254988

0

당신은 당신이 같은 함수에 x을 줄 수있는 문자열

0

scanf 가족 기능은 이러한 기능을 수행하지 않습니다. 문자열을 반복하고 각 문자를 확인하려면 isalpha을 사용해야합니다. 그리고 문자열의 끝을 앞으로 복사하여 문자를 memmove으로 "제거"합니다.

아마 scanf이 가능합니다. 대부분의 경우 scanf과 친구들은 일치하지 않으면 공백이 아닌 문자를 다시 입력 스트림으로 푸시합니다.

이 예제에서는 scanf을 스트림의 정규식 필터로 사용합니다.* 변환 수정자를 사용하면 부정 된 패턴의 저장 대상이 없음을 의미합니다. 그냥 먹 혔어.

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

int main(){ 
    enum { BUF_SZ = 80 }; // buffer size in one place 
    char buf[BUF_SZ] = ""; 
    char fmtfmt[] = "%%%d[A-Za-z]"; // format string for the format string 
    char fmt[sizeof(fmtfmt + 3)]; // storage for the real format string 
    char nfmt[] = "%*[^A-Za-z]";  // negated pattern 

    char *p = buf;        // initialize the pointer 
    sprintf(fmt, fmtfmt, BUF_SZ - strlen(buf)); // initialize the format string 
    //printf("%s",fmt); 
    while(scanf(fmt,p) != EOF     // scan for format into buffer via pointer 
     && scanf(nfmt) != EOF){     // scan for negated format 
     p += strlen(p);       // adjust pointer 
     sprintf(fmt, fmtfmt, BUF_SZ - strlen(buf)); // adjust format string (re-init) 
    } 
    printf("%s\n",buf); 
    return 0; 
} 
0

저는 비슷한 프로젝트를 진행하고 있으므로 손에 익숙해졌습니다. 단어를 다른 부분으로 떼어 내십시오. 당신은

if(!isPunct(x)) 

사용 1 인덱스를 증가, 임시 문자열 홀더에 그 새 문자열을 추가 할 수 있습니다

빈 공간은 각 단어 CIN에 문제가되지 않습니다. 배열과 같은 문자열에서 문자를 선택할 수 있으므로 알파가 아닌 문자를 찾고 새 문자열을 저장하는 것이 쉽습니다.

string x = "hell5o"  // loop through until you find a non-alpha & mark that pos 
for(i = 0; i <= pos-1; i++) 
            // store the different parts of the string 
string tempLeft = ... // make loops up to and after the position of non-alpha character 
string tempRight = ... 
1

luser droog 답변이 효과적 일 수 있지만 제 생각에는 필요 이상으로 복잡합니다.

당신의 간단한 예를 FOI 당신이 시도 할 수 : fscanf` 하나의 큰 문제가

while (fscanf(inputFile, "%[A-Za-z]", x) == 1) { // read until find a non alpha character 
    fscanf(inputFile, "%*[^A-Za-z]")) // discard non alpha character and continue 
} 
+1

예. 그게 나아. +1 –

관련 문제