简体   繁体   中英

C, reading a multiline text file

I know this is a dumb question, but how would I load data from a multiline text file?

while (!feof(in)) {
    fscanf(in,"%s %s %s \n",string1,string2,string3);
}

^^This is how I load data from a single line, and it works fine. I just have no clue how to load the same data from the second and third lines.

Again, I realize this is probably a dumb question.

Edit: Problem not solved. I have no idea how to read text from a file that's not on the first line. How would I do this? Sorry for the stupid question.

Try something like:

/edited/

char line[512]; // or however large you think these lines will be

in = fopen ("multilinefile.txt", "rt");  /* open the file for reading */
/* "rt" means open the file for reading text */
int cur_line = 0;
while(fgets(line, 512, in) != NULL) {
     if (cur_line == 2) { // 3rd line
     /* get a line, up to 512 chars from in.  done if NULL */
     sscanf (line, "%s %s %s \n",string1,string2,string3);
     // now you should store or manipulate those strings

     break;
     }
     cur_line++;
} 
fclose(in);  /* close the file */

or maybe even...

char line[512];
in = fopen ("multilinefile.txt", "rt");  /* open the file for reading */
fgets(line, 512, in); // throw out line one

fgets(line, 512, in); // on line 2
sscanf (line, "%s %s %s \n",string1,string2,string3); // line 2 is loaded into 'line'
// do stuff with line 2

fgets(line, 512, in); // on line 3
sscanf (line, "%s %s %s \n",string1,string2,string3); // line 3 is loaded into 'line'
// do stuff with line 3

fclose(in); // close file

Putting \n in a scanf format string has no different effect from a space. You should use fgets to get the line, then sscanf on the string itself.

This also allows for easier error recovery. If it were just a matter of matching the newline, you could use "%*[ \t]%*1[\n]" instead of " \n" at the end of the string. You should probably use %*[ \t] in place of all your spaces in that case, and check the return value from fscanf. Using fscanf directly on input is very difficult to get right (what happens if there are four words on a line? what happens if there are only two?) and I would recommend the fgets/sscanf solution.

Also, as Delan Azabani mentioned... it's not clear from this fragment whether you're not already doing so, but you have to either define space [eg in a large array or some dynamic structure with malloc] to store the entire dataset, or do all your processing inside the loop.

You should also be specifying how much space is available for each string in the format specifier. %s by itself in scanf is always a bug and may be a security vulnerability.

First off, you don't use feof() like that...it shows a probable Pascal background, either in your past or in your teacher's past.

For reading lines, you are best off using either POSIX 2008 (Linux) getline() or standard C fgets() . Either way, you try reading the line with the function, and stop when it indicates EOF:

while (fgets(buffer, sizeof(buffer), fp) != 0)
{
     ...use the line of data in buffer...
}

char *bufptr = 0;
size_t buflen = 0;
while (getline(&bufptr, &buflen, fp) != -1)
{
    ...use the line of data in bufptr...
}
free(bufptr);

To read multiple lines, you need to decide whether you need previous lines available as well. If not, a single string (character array) will do. If you need the previous lines, then you need to read into an array, possibly an array of dynamically allocated pointers.

Every time you call fscanf , it reads more values. The problem you have right now is that you're re-reading each line into the same variables, so in the end, the three variables have the last line's values. Try creating an array or other structure that can hold all the values you need.

The best way to do this is to use a two dimensional array and and just write each line into each element of the array. Here is an example reading from a.txt file of the poem Ozymandias:

int main() {

char line[15][255];
FILE * fpointer = fopen("ozymandias.txt", "rt");
for (int a = 0; a < 15; a++) {
    fgets(line[a], 255, fpointer);
}
for (int b = 0; b < 15; b++) {
    printf("%s", line[b]);
}

return 0;

This produces the poem output. Notice that the poem is 14 lines long, it is more difficult to print out a file whose length you do not know because reading a blank line will produce the output "x�oA". Another issue is if you check if the next line is null by writing

while (fgets(....) != NULL)) {

each line will be skipped. You could try going back a line each time to solve this but i think this solution is fine for all intents.

I have an even EASIER solution with no confusing snippets of puzzling methods (no offense to the above stated) here it is:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;
int main()
{
    string line;//read the line
    ifstream myfile ("MainMenu.txt"); // make sure to put this inside the project folder with all your .h and .cpp files

    if (myfile.is_open())
    {
        while ( myfile.good() )
        {
            getline (myfile,line);
            cout << line << endl;
        }
        myfile.close();
           }
    else cout << "Unable to open file";
   return 0;

}

Happy coding

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM