2017-03-24 10 views
-1

나는 이것이 매우 사소한 질문이지만 빠른 도움말이 필요하다는 것을 알고 있습니다. 나는 이것을 잠시 동안 알아 내려고 노력해왔다. 내가 할 노력하고 모든 형태 내가 궁극적으로 번호 만 가지고 배열에 저장하고, BST에 그 숫자를 넣을C에서 문자열, 공백, 줄 바꿈 및 정수가있는 파일의 정수만 읽는 방법

8 blah blah 
10 blah blah 
2 blah blah 
3 blah blah 

이있는 텍스트 파일 만 정수를 읽습니다. 번호가있는 파일은 있지만 지정된 파일 형식이 아닌 파일은 BST가 올바르게 작동합니다.

무엇이 문제가되지 않습니다. blah은 숫자를 가져 와서 배열에 저장하기 만하면됩니다. blah's을 꺼내면이 작업을 수행 할 수 있습니다. fscanf을 사용하면 코드 번호가 8 인 첫 번째 번호를 저장했지만 거기서 멈 춥니 다. 또한이 예제에는 네 줄이 있지만 파일에 몇 줄이 있는지는 중요하지 않습니다. 12 또는 6 일 수 있습니다. 어떻게 제대로 할 수 있습니다. 아래는이 문제를 해결하려는 나의 가난한 시도입니다.

fscanf(instructionFile, "%d", &num); 

는 또한 모든 것을 저장 만 정수를 사용하려면

while(!feof(instructionFile)){ 
    fscanf("%d %s %s", &num, string1, string2); 
} 

같은 일을했지만, 내가 그런 일을 할 때 내 BST가 작동하지 않습니다.

+0

정지 없습니다. 'fgets'를 사용하고'strtol'을 사용하여 구문 분석하십시오. –

+0

또한 http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong을 참조하십시오. –

+0

숫자는 항상 시작 부분에 있습니까? 선? 항상 전화 번호가 있습니까? 한 줄에 많은 숫자가있을 수 있습니까? 번호를 글자 나 구두점으로 둘러 쌀 수 있습니까? 신호에 대해 걱정해야합니까? –

답변

1

입력 줄을 가져 오려면 fgets()을 사용하고 정수를 가져 오려면 sscanf()을 사용하십시오. 예를 들어 fscanf()을 사용하는 경우 첫 번째 호출은 int이고 다음 호출은 입력 스트림의 다음 항목이 int이 아니므로 실패합니다. 각 실패 후에 입력 스트림에 잘못된 입력이 남아 있습니다. 한 번에 줄을 가져 와서 다른 줄의 줄을 가져 오기 전에 여가 시간에 줄을 검사 할 수 있습니다.

다음은이 작업을 수행하는 방법의 예입니다. 읽기 루프를 제어하려면 feof()을 사용하지 않아야합니다. 대신 fgets()의 반환 값을 사용하십시오. 이 코드는 행의 첫 번째 항목이 원하는 공백 인 공백이있는 데이터라고 가정합니다. 약간 더 복잡한 상황에서 형식 문자열을 수정할 수 있습니다. 또한 선의 구문 분석을보다 세부적으로 제어해야하는 경우 strtok()을 사용할 수 있습니다.

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

#define MAX_LINES 100 

int main(void) 
{ 
    FILE *fp = fopen("data.txt", "r"); 
    if (fp == NULL) { 
     fprintf(stderr, "Unable to open file\n"); 
     exit(EXIT_FAILURE); 
    } 

    char buffer[1000]; 
    int arr[MAX_LINES]; 
    size_t line = 0; 

    while ((fgets(buffer, sizeof buffer, fp) != NULL)) { 
     if (sscanf(buffer, "%d", &arr[line]) != 1) { 
      fprintf(stderr, "Line formatting error\n"); 
      exit(EXIT_FAILURE); 
     } 
     ++line; 
    } 

    for (size_t i = 0; i < line; i++) { 
     printf("%5d\n", arr[i]); 
    } 

    fclose(fp); 

    return 0; 
} 

sscanf() 호출하기 전에 빈 줄에 대한 검사를 추가하는 것이 좋을 것입니다; 지금 빈 줄은 잘못된 형식의 데이터로 간주됩니다. 귀하의 예제 파일

출력 :

8 
    10 
    2 
    3 
1

당신이 파일의 혼란에서 정수만을 골라 싶은 경우에, 당신은 실제로 당신이 각각의 시작 숫자를 식별 할 수있는 포인터를 읽을 각 라인을 통해 작업 필요 (또는 처음에는 - 부호가 음수로 표시됨) 각 정수를 한 번에 하나씩 변환합니다. 포인터 sscanf을 사용하여 수행하거나 strtol 매개 변수를 사용하여 endptr 매개 변수를 사용하여 성공적인 변환 후 다음 문자로 이동할 수 있습니다. 원할 경우 문자 기반 입력 (예 : getchar 또는 fgetc)을 수동으로 숫자 식별 및 변환을 수행 할 수도 있습니다.

fgetssscanf 접근 방식으로 시작했다고 가정하면 다음과 같이 계속됩니다.sscanf 또는 strtol을 사용하든간에 전체 키는 발견 된 각 정수 뒤에 오는 문자로 다음 읽기 시작을 앞당기는 것입니다.

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

#define MAXC 256 

int main (int argc, char **argv) { 

    char buf[MAXC] = ""; /* buffer to hold MAXC chars at a time */ 
    int nval = 0;   /* total number of integers found */ 
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin; 

    if (!fp) { /* validate file open for reading */ 
     fprintf (stderr, "error: file open failed '%s'.\n", argv[1]); 
     return 1; 
    } 

    while (fgets (buf, MAXC, fp)) { 

     char *p = buf;  /* pointer to line */ 
     int val,   /* int val parsed */ 
      nchars = 0;  /* number of chars read */ 

     /* while chars remain in buf and a valid conversion to int takes place 
     * output the integer found and update p to point to the start of the 
     * next digit. 
     */ 
     while (*p) { 
      if (sscanf (p, "%d%n", &val, &nchars) == 1) { 
       printf (" %d", val); 
       if (++nval % 10 == 0)  /* output 10 int per line */ 
        putchar ('\n'); 
      } 
      p += nchars;  /* move p nchars forward in buf */ 

      /* find next number in buf */ 
      for (; *p; p++) { 
       if (*p >= '0' && *p <= '9') /* positive value */ 
        break; 
       if (*p == '-' && *(p+1) >= '0' && *(p+1) <= '9') /* negative */ 
        break; 
      } 
     } 
    } 
    printf ("\n %d integers found.\n", nval); 

    if (fp != stdin) fclose (fp);  /* close file if not stdin */ 

    return 0; 
} 

입력

다음 두 입력 파일 혼합 입력 중 정수만 따기 나타낸다. 파일 :

$ cat dat/blah.txt 
8 blah blah 
10 blah blah 
2 blah blah 
3 blah blah 

정말 지저분 파일

$ cat ../dat/10intmess.txt 
8572,;a -2213,;--a 6434,; 
a- 16330,;a 

- The Quick 
Brown%3034 Fox 
12346Jumps Over 
A 
4855,;*;Lazy 16985/,;a 
Dog. 
11250 
1495 

사용 예/출력

귀하의 경우 : 정말 지저분한 파일로

$ ./bin/fgets_sscanf_int_any_ex < dat/blah.txt 
8 10 2 3 
4 integers found. 

:

$ ./bin/fgets_sscanf_int_any_ex <dat/10intmess.txt 
8572 -2213 6434 16330 3034 12346 4855 16985 11250 1495 

10 integers found. 

궁금한 점이 있으면 살펴보고 알려주세요.

1

"정수만을 읽기"하기위한 간단한 방법, 즉

int x; 
int count; 
while ((count = fscanf(file_pointer, "%d", &x)) != EOF) { 
    if (count == 1) { 
    // Use the `int` in some fashion (store them in an array) 
    printf("Success, an int was read %d\n", x); 
    } else { 
    fgetc(file_pointer); // Quietly consume 1 non-numeric character 
    } 
} 

내가 8 첫 번째 번호를 저장하려면 코드를 가지고

을 실패 할 때 fscanf(file_pointer, "%d", ...)fgetc()을 사용하는 것입니다하지만, 거기서 멈 춥니 다.

이는 잘못된 숫자가 아닌 입력이 FILE 스트림에 남아 있기 때문입니다. 그 텍스트는 일부 다른 방법으로 소비되어야합니다. fscanf(instructionFile, "%d", &num);을 다시 호출하면 동일한 문제가 발생합니다. fscanf()은 초기 입력이 숫자가 아니므로 실패합니다.


주 : 영업 이익의 코드가 fscanf를 사용하여 파일 포인터를

// fscanf(????, "%d %s %s", &num, string1, string2);