RoadRunner RoadRunner - 3 months ago 8
C Question

Reading tab separated file using getchar()

I am trying to read a text file using input redirection,

./program < file.txt
, and the file I made looks like this:

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


Which just reads some random data, in according to the first row with 4 columns, headed
Country
,
Sport
,
Gender
and
Medal
.

I also inserted
\t
and
\n
to make the file more readable, but the file actually has tabs and newlines in it.

I am trying to read each line of that file, and store them in an array of strings, which I have declared as:

char *records[ROWS][COLUMNS];


I would like the array of strings,
records
to look something like:

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


So far I have just been using
scanf
to read the lines, like this:

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


I know this will not work as the country name
New Zealand
has a space between both strings, and my
scanf
wil only read the first four characters. My method of
scanf
will also not be effective because it only works for 4 columns.

Is there a way I can use
getchar()
instead to do this? I'm just not sure how to use
getchar
to analyse each character in the input stream, and convert the necessary characters to strings depending on the tabs and newlines.

Answer

The posted code contains several problems:

  1. unused stack variable records[][]
  2. unused parameter: argc
  3. unused parameter: argv
  4. places all input data into first entries in the arrays: country[], sport[], gender[], medal[] I.E. all the other entries are not used
  5. does not handle 'columns' that contain any white space
  6. includes a header file those contents are not used: string.h

The following code cleanly compiles and performs the desired function:

#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