2016-09-01 5 views
4

내가 입력 리디렉션, ./program < file.txt를 사용하여 텍스트 파일을 읽으려고하고, 파일이이 같은 모습했다 : 그냥 따라에, 어떤 임의의 데이터를 읽어읽기 탭 getchar가()를 사용하여 파일을 분리

Country\tSport\tGender\tMedal\n 
America\tCycling\tMens\tGold\n 
New Zealand\tSwimming\tWomens\tSilver\n 
India\tBadminton\tMens\tbronze\n 

을 첫 번째 행의 4 열로, Country, Sport, GenderMedal으로 향합니다.

\t\n을 삽입하여 파일을 읽기 쉽도록 만들었지 만 실제로 파일에 탭과 개행 문자가 있습니다.

내가 그 파일의 각 행을 읽으려고하고, 나는이 선언 한 문자열의 배열에 저장하고 : 같은 것을보고, 내가 문자열의 배열을 원하는

char *records[ROWS][COLUMNS]; 

records을 :

{{"Country", "Sport", "Gender", "Medal"}, {"America", "Cycling", "Mens", "Gold"}, 
{"New Zealand", "Swimming", "Womens", "Silver"}, {"India", "Badminton", "Mens", "Bronze"}} 

지금까지 난 그냥이 같은 라인, 읽기 scanf을 사용하고 있습니다 :

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

#define ROWS 1000 
#define COLS 30 
#define MAX_CH 50 

int 
main(int argc, char *argv[]) { 
    char *records[ROWS][COLS]; 

    char country[MAX_CH]; 
    char sport[MAX_CH]; 
    char gender[MAX_CH]; 
    char medal[MAX_CH]; 

    while (scanf("%s\t%s\t%s\t%s\n", country, sport, gender, medal) == 4) { 
     printf("%s %s %s %s\n", country, sport, gender, medal); 
    } 

    return 0; 
} 

국가 이름이 New Zealand 인 경우 두 문자열 사이에 공백이있는 것으로 인식되지 않으며 내 scanf은 처음 네 자만 읽습니다. scanf의 내 메서드는 4 열에서만 작동하기 때문에 효과가 없습니다.

내가 대신 getchar()을 사용할 수있는 방법이 있습니까? 난 단지 getchar을 사용하여 입력 스트림의 각 문자를 분석하고 탭과 개행 문자에 따라 필요한 문자를 문자열로 변환하는 방법을 모르겠습니다. getChar()

+3

'fgets'을 사용하고 직접 파스를 작성하십시오. –

+0

고마워요 @MichaelWalz,'getchar'도 사용할 수 있습니까? 나는'fgets'와 같은 것들로 넘어 가기 전에 이런 종류의 함수로 더 잘 해나 가고 있습니다. – RoadRunner

+0

@RoadRunner, 물론, 여기에'getchar()'을 사용할 수있는 방법이 있습니다. –

답변

1

행과 열을 읽을 수 있습니다.

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

#define ROWS 1000 
#define COLS 30 
#define MAX_CH 50 

void print_array(char str[][COLS][MAX_CH], int nrows, int ncols, int col[], int reorder); 
void sort_array(char str[][COLS][MAX_CH], int nrows, int ncols, int col[]); 


int main(int argc, char *argv[]) 
{ 
    char records[ROWS][COLS][MAX_CH] = { { { '\0'}}};//set each element 
    char item[MAX_CH] = { '\0'};//buffer for each item 
    //char yn[40]; 
    int row = 0; 
    int col = 0; 
    int usedcol = 0; 
    int sortby[COLS] = { 0}; 
    int ch = 0; 
    int each = 0; 
    int loop = 0; 
    int result = 0; 

    if (argc < 2 || argc > COLS + 1) { 
     fprintf (stderr, "syntax is\n%s column0 [column1]...[column%d] < inputfile\n", argv[0], COLS - 1); 
     exit(EXIT_FAILURE); 
    } 

    for (each = 1; each <= COLS + 1; each++) {// +1 to get to extra element 
     sortby[each - 1] = -1;//extra element will be -1 
     if (each < argc) { 
      if ((result = sscanf (argv[each], "%d", &sortby[each - 1])) != 1 || sortby[each - 1] < 0 || sortby[each - 1] >= COLS) { 
       fprintf (stderr, "syntax is\n%s column0 [column1]...[column%d] < inputfile\n", argv[0], COLS - 1); 
       fprintf (stderr, "column%d must be 0 to %d\n", each - 1, COLS - 1); 
       exit(EXIT_FAILURE); 
      } 
     } 
    } 

    for (each = 0; each < argc - 1; each++) { 
     for (loop = 0; loop < argc - 1; loop++) { 
      if (loop != each && sortby[each] == sortby[loop]) { 
       fprintf (stderr, "found duplicate columns in args\n"); 
       exit(EXIT_FAILURE); 
      } 
     } 
    } 
    //printf ("\n"); 

    if (isatty (fileno (stdin))) { 
     printf ("expected that a file would be redirected to this program\n"); 
     printf ("syntax is\n%s column0 [column1]...[column%d] < inputfile\n", argv[0], COLS - 1); 
     //printf ("enter y to continue WITHOUT the redirected file?\n"); 
     //if ((fgets (yn, sizeof (yn), stdin))) { 
      //if (strcmp (yn, "y\n") != 0) { 
       exit(EXIT_FAILURE); 
      //} 
     //} 
    } 

    row = 0; 
    col = 0; 
    each = 0; 
    while ((ch = getchar ()) != EOF) {//read each character 
     if (ch == '\r') {//skip carriage return 
      continue; 
     } 
     if (ch == '\t') { 
      strcpy (records[row][col], item); 
      each = 0;//back to first character 
      col++;//next column 
      if (col >= COLS) { 
       col = 0; 
       row++; 
       if (row >= ROWS) { 
        fprintf (stderr, "too many rows\n"); 
        break; 
       } 
      } 
      continue; 
     } 
     if (ch == '\n') { 
      strcpy (records[row][col], item); 
      col++; 
      if (col > usedcol) { 
       usedcol = col; 
      } 
      col = 0;//back to first column 
      each = 0;//back to first character 
      row++;//next row 
      if (row >= ROWS) { 
       fprintf (stderr, "too many rows\n"); 
       break; 
      } 
      continue; 
     } 
     item[each] = ch; 
     each++;//next character 
     item[each] = '\0';//terminate with '\0' 
     if (each >= MAX_CH - 1) { 
      fprintf (stderr, "too many characters in item\n"); 
      each = 0; 
      col++; 
      if (col >= COLS) { 
       col = 0; 
       row++; 
       if (row >= ROWS) { 
        fprintf (stderr, "too many rows\n"); 
        break; 
       } 
      } 
      continue; 
     } 
    } 

    print_array (records, row, usedcol, sortby, 0); 

    sort_array (records, row, usedcol, sortby); 

    print_array (records, row, usedcol, sortby, 1); 

    return 0; 
} 

void print_array(char str[][COLS][MAX_CH], int nrows, int ncols, int col[], int reorder) { 
    int i, j; 
    int order[COLS] = { 0}; 

    for (i = 0; i < COLS; i++) { 
     if (reorder) { 
      order[i] = col[i]; 
     } 
     else { 
      order[i] = i; 
     } 
    } 

    if (reorder) { 
     for (i = 0; i < COLS; i++) { 
      for (j = 0; j < COLS; j++) { 
       if (order[j] == i) { 
        break; 
       } 
       if (order[j] == -1) { 
        order[j] = i; 
        break; 
       } 
      } 
     } 
    } 

    for (i = 0; i < nrows; i++) { 
     for (j = 0; j < ncols; j++) { 
      printf("%-12s ", str[i][order[j]]); 
     } 
     printf("\n"); 
    } 
    printf("\n"); 
} 

void sort_array(char str[][COLS][MAX_CH], int nrows, int ncols, int col[]) { 
    int i = 0, j = 0, swap = 0, each = 0; 
    char temp[MAX_CH] = { '\0'}; 

    do { 
     swap = 0; 
     for (i = 1; i < nrows - 1; i++) {//iterate through rows. i=1 skip first row 

      for (each = 0; col[each] != -1; each++) {//col[] has last element of -1 

       if (strcmp(str[i][col[each]], str[i + 1][col[each]]) < 0) { 
        break; 
       } 
       if (strcmp(str[i][col[each]], str[i + 1][col[each]]) == 0) { 
        continue; 
       } 
       for (j = 0; j < ncols; j++) {//iterate through cols and swap rows 
        strcpy (temp, str[i][j]); 
        strcpy (str[i][j], str[i + 1][j]); 
        strcpy (str[i + 1][j], temp); 
       } 
       swap = 1; 
       break; 
      } 
     } 
    } while (swap);//loop until no swaps 
} 
+0

@ user3121023 답변 주셔서 감사합니다, 거기에'malloc'을 사용하지 않고 이것을 할 수있는 방법이 있습니까? – RoadRunner

+0

고맙습니다. user3121023, 첫 번째 열에 의해 2 차원 문자열 배열을 정렬 할 수있는 방법이 있습니까? 나는 이것을하기 위해 삽입 정렬을 사용하려고 생각했다. 'strcmp'를 사용하여 첫 번째 행의 각 단어를 비교하고 서로 바꾸는 것과 같습니다. – RoadRunner

+0

첫 번째 열의 각 단어를 유감스럽게 생각합니다. – RoadRunner

2

이 의사 코드 :

while (char = getChar()) is not 'EOF': // EOF = End of file 
    if char is not '\t' and char is not '\n' 
     save into current string 
    else if char is '\t' 
     terminate current string 
     increment column index 
    else if char is '\n' 
     terminate current string 
     increment row index 

편집 :

getChar()의 문제는 단지 당신이 다음 탭에 도달하면 문자열이 될 것입니다 얼마나 알고 있다는 것입니다.

문자열의 길이를 알기 위해 처음 반복을 수행 한 다음 적절한 양의 메모리를 할당하거나 항상 안전한 최대 메모리 (최대 문자열 길이)를 할당해야합니다.

char string[] = "MINE"; // string[0] -> 'M' 
string[0] = 'N'; // string -> "NINE" 

// with dynamic memory allocation 
char *string = (char*) malloc(5*sizeof(char)); 
string[0] = 'N'; // string -> "N" 
+0

답변 해 주셔서 감사합니다. 현재 문자열에 어떻게 저장 하시겠습니까? 'strcat'과 같은 것이 유용할까요? 이것이 나의 주요 혼란이있는 곳입니다. – RoadRunner

+0

@RoadRunner 내 편집을 참조하십시오 – Barthy

+0

고마워요 @ 바티,이 도움이됩니다 :) – RoadRunner

1

게시 된 코드는 여러 가지 문제를 포함

  1. 않는 스택 변수 records[][]
  2. 않는 파라미터 : argc
  3. 않는 파라미터 : 제 항목에 argv
  4. 대한 모든 입력 데이터 배열 : 국가 [], 스포츠 [], 성별 [], 메달 [] IE string.h

다음 코드는 정상적으로 컴파일하고 원하는 수행 다른 모든 항목은

  • 그 내용이 사용하지 않는 헤더 파일을 포함 공백을 포함하는 '열'을 처리하지 않습니다
  • 을 사용하지 않습니다 함수 :

    #include <stdio.h> 
    #include <stdlib.h> 
    //#include <string.h> 
    
    #define ROWS 1000 
    //#define COLS 30 
    #define MAX_CH 49 
    
    struct record 
    { 
        char country[ MAX_CH+1 ]; 
        char sport [ MAX_CH+1 ]; 
        char gender [ MAX_CH+1 ]; 
        char medal [ MAX_CH+1 ]; 
    }; 
    
    int main(void) 
    { 
        struct record records[ROWS]; 
    
        for(size_t i=0; i< ROWS; i++) 
        { 
         if(scanf(" %" MAX_CH "[^\t] %" MAX_CH "[^\t] %" MAX_CH "[^\t] %" MAX_CH "[^\n]", 
           records[i].country, 
           records[i].sport, 
           records[i].gender, 
           records[i].medal) == 4) 
         { 
          printf("%s %s %s %s\n", 
            records[i].country, 
            records[i].sport, 
            records[i].gender, 
            records[i].medal); 
         } 
    
         else 
         { 
          break; 
         } 
        } 
    
        return 0; 
    } // end function: main 
    
  • +0

    질문 OP는 코드가 원하는 수의 열을 처리 할 수 ​​있기를 바랍니다. 실제로 이것이 사실이라면'records []'의 정의와 컬럼을 읽는 방법을 수정해야 할 것입니다. 아마도 '\ n'이 나올 때까지 컬럼을 읽어야 할 것입니다. 아마도 읽기 위해 수정해야 할 것입니다 'getchar()'을 사용하려면 행 번호 열 – user3629249

    +0

    을 사용하기 위해 코드는 어떤 행 및 어떤 열의 현재 위치를 추적하고 각 문자 읽기에 대해 '\ t'가 다음 단계로 넘어갈 지 확인해야합니다 다음 행으로 이동하려면 '\ n'을 선택하십시오. EOF가 입력 루프를 종료하는지 확인하십시오. 이 세 가지 조건 중 하나라도 없다면 char read를 현재 열의 다음 사용 가능한 위치에 놓습니다. 또한 현재 열이 넘치지 않도록 확인하는 것이 좋습니다. – user3629249

    +0

    답변 해 주셔서 감사합니다 :) 나는'getchar '방법을 시도하고 있지만 작동하도록 고심하고 있습니다. 시간이 있다면 좀 봐 주시겠습니까? https://ideone.com/9LT32M 여기에 있습니다. 정확한 위치 근처가 아니라는 것을 알고 있지만 문제가 많이 있습니다. – RoadRunner

    관련 문제