?
Solved

getline function reading from a text file

Posted on 2006-06-04
11
Medium Priority
?
739 Views
Last Modified: 2010-04-15
Hi folks,

I`m doing a project with a few friends where we create a virtual pub quiz using C.

I have a few files which I read into the console, most of which I am fine with.  The file I am having trouble with is the actual question file.

This file contains 20 questions, each question is followed by 4 answers [ example below ]:

Where were the 1970 football World Cup finals held ?
Mexico,Spain,Brazil,England

What I am trying to do is obviously read this file into an array, then display each question and the answers on a seperate line [ as it is in the text file ] rather than all on one line like it currently is.

The code I am working with is below:


void readquiz() {
      
      int i;
      
      FILE *quiz_ptr;
      
      quiz_ptr = fopen("quiz.txt", "r");
      
      if(quiz_ptr != NULL) {
            
            i=0;
            
            while (fscanf(quiz_ptr, "%s", var[i]) != EOF) {
                  printf("%s ", var[i]);
                  i++;
            }
            
            printf("\n\n");
            fclose(quiz_ptr);
      }
}


Currently the data is printed as this :

Where were the 1970 football World Cup finals held ? Mexico,Spain,Brazil,England


I want it to look like this :

Where were the 1970 football World Cup finals held ?
Mexico,Spain,Brazil,England

Problem is I dont know how getline works and cant find much info on it, can anyone help ?

Thanks.
0
Comment
Question by:3nigmatic
  • 5
  • 4
  • 2
11 Comments
 
LVL 46

Expert Comment

by:Kent Olsen
ID: 16829624
Hi 3nigmatic,

How is the data file structured?  Are the questions and answers on 1 line or several?

My guess is that everything is on one line.  In that case, you'll have to split the line yourself.  Not too tough, though.


char *Question;
char *Answers;

          while (fscanf(quiz_ptr, "%s", var[i]) != EOF) {
               Question = var[i];
               Answer = strchr (Question, '?');
               if (Answer) {
                 ++Answer;
                 *Answer = 0;
               }
               printf("%s\n%s", Question, Answer);
               i++;



That will do for demonstration purposes, though I suggest that you rethink your array so that you can put the questions and answers in different locations.


Good Luck!
Kent
0
 
LVL 2

Author Comment

by:3nigmatic
ID: 16829638
Quiestions file data structure is like this:

Where were the 1970 football World Cup finals held ?
Mexico,Spain,Brazil,England
In books by JRR Tolkien, what kind of creatures are Bilbo and Frodo Baggins ?
Hobbits,Orcs,Elves,Humans
Which Italian city is home of the car manufacturer Fiat ?
Turin,Rome,Pisa,Ravena

For 20 questions plus four answers for each question.

The reason I want to use an array is because I will eventually randomise the answer output positions so that people can not just memorise the locations of the correct answer for each question.
0
 
LVL 23

Accepted Solution

by:
brettmjohnson earned 1200 total points
ID: 16829902
Don't use getline() - it is non-standard.  Use fgets() instead.  It also has the benefit of being better documented.


void readquiz() {
     int i;
     FILE *quiz_ptr;
     char *answs[4];
     char *sep = ",\r\n";
     char line[4096];

     quiz_ptr = fopen("quiz.txt", "r");
     
     if(quiz_ptr != NULL) {
          while (fgets(line, sizeof(line), quiz_ptr) {      /* read the next question */
               fputs(line, stdout);      /* display question */

               if (fgets(line, sizeof(line), quiz_ptr) {      /* read the answers */
                   /* parse the answers into an array */
                   for(i = 0, tok = strtok(line, sep); i < 4 && tok; i++, tok = strtok(NULL, sep))
                       answs[i] = tok;
                   /* display the answers */
                   printf("a) %s\tb) %s\tc) %s\td) %s\n\n", answs[0], answs[1], answs[2], answs[3]);
               }
          }
         
          printf("\n\n");
          fclose(quiz_ptr);
     }
}
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 46

Expert Comment

by:Kent Olsen
ID: 16831963
Hi 3nigmatic,

You can get past the single line effect with just a small change to the printf() statement.

          while (fscanf(quiz_ptr, "%s", var[i]) != EOF) {
               printf("%s\n", var[i]);    // Notice that \n has been added to the format.
               i++;
          }

That will put the question and answer on separate lines.

My suggestion is that you build two arrays.  

char Questions[MAX_QUESTIONS][MAX_LENGTH];
char Answers[MAX_QUESTIONS][MAXLENGTH];

Then in the while loop, read the question then the list of answers.  Answers[0] will apply to Question[0], Answer[6] will apply to Question[6], etc.  Just pick any random number and you have both the question and answer list for that number.


Kent
0
 
LVL 2

Author Comment

by:3nigmatic
ID: 16832037
brettmjohnson,

Thanks for your suggestion I`m looking into how it works etc now.


kdo,

Adding \n to my printf statement does produce a new line, but every new word is on a new line.  This is why I am looking to use getline, or as suggested by brettmjohnson fgets [ which I have also been reading up on ].
0
 
LVL 2

Author Comment

by:3nigmatic
ID: 16837758
With a little modification I went with brettmjohnson's code:

void readquiz() {

     FILE *quiz_ptr;
     char *answs[4];
     char *sep = ",\r\n";
     char line[4096];
       int i;
       int tok;
       int count = 1;

     quiz_ptr = fopen("quiz.txt", "r");
     
     if(quiz_ptr != NULL) {
          while (fgets(line, sizeof(line), quiz_ptr)) {     /* read the next question */
                    printf("%d) ", count);
               fputs(line, stdout);     /* display question */

               if (fgets(line, sizeof(line), quiz_ptr)) {     /* read the answers */
                   /* parse the answers into an array */
                   for(i = 0, tok = strtok(line, sep); i < 4 && tok; i++, tok = strtok(NULL, sep))
                       answs[i] = tok;
                   /* display the answers */
                   printf("\ta) %s\n\tb) %s\n\tc) %s\n\td) %s\n\n", answs[0], answs[1], answs[2], answs[3]);
                           count ++;
               }
          }
              fclose(quiz_ptr);
     }
}

I am a little stuck as to what the variables tok & sep do though, can anyone explain ?

Thanks.
0
 
LVL 23

Expert Comment

by:brettmjohnson
ID: 16838911
> I am a little stuck as to what the variables tok & sep do though, can anyone explain ?

strtok() tokenizes (breaks up) the string (line) based upon the separator characters (delimiters) in sep.  tok is a pointer to the returned string fragment strtok found.  BTW, strtok() tokenizes in place, so it overwrites the found delimiter (',' or newline) in line with a NUL byte, then returns a pointer to the beginning of that substring, so to will always be a pointer to somewhere in the line buffer (except when  its NULL).  

One caution: strtok() is not thread-safe - it maintains internal state (of its current position in the string) in static local storage (hence passing NULL on subsequent calls).  If you need thread-safety, consider strtok_r() or strsep() instead.

Not also that the code is not robust (for the sake of simplicity and demonstration).   It does not tolerate malformed answers - missing or less than 4 choices.

What is the variable 'count' for?  I appears to be the number of questions+1, but is otherwise unused.
0
 
LVL 2

Author Comment

by:3nigmatic
ID: 16838946
Thanks Brett for the explination, still a little confused but I will work it out ... always good fun.

Err, as for the var count, as you stated, it is basicaly there just to number the questions and thats it.

Why do you ask, is there something wrong with the way I have done it ?
0
 
LVL 23

Expert Comment

by:brettmjohnson
ID: 16839403
I only asked about 'count' because it is apparently used outside the chunk of code you posted, but as as count of the number of questions ,it is off by one.  To correct the issue, initialize count to 0, not 1.

0
 
LVL 2

Author Comment

by:3nigmatic
ID: 16841006
If I was to set the var count = 0; though, it would show that I had just 19 questions when in fact there are 20.

Or am I missing your point here  ?
0
 
LVL 23

Expert Comment

by:brettmjohnson
ID: 16843504
You aren't really missing the point, you are just wrong.  
Walk through the code with test files that contain 0, 1, 2,  and 3 questions.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

864 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question