简体   繁体   English

C,读取多行文本文件

[英]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.\n放入 scanf 格式字符串与空格没有不同的效果。 You should use fgets to get the line, then sscanf on the string itself.您应该使用 fgets 获取该行,然后使用 sscanf 获取字符串本身。

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.如果只是匹配换行符,您可以在字符串末尾使用"%*[ \t]%*1[\n]"而不是" \n" You should probably use %*[ \t] in place of all your spaces in that case, and check the return value from fscanf.在这种情况下,您可能应该使用%*[ \t]代替所有空格,并检查 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.直接在输入上使用 fscanf 很难正确(如果一行中有四个单词会发生什么?如果只有两个会发生什么?)我会推荐 fgets/sscanf 解决方案。

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.此外,正如 Delan Azabani 所提到的......从这个片段中不清楚你是否还没有这样做,但你必须定义空间 [例如在一个大数组或一些带有 malloc 的动态结构中] 来存储整个数据集,或在循环内进行所有处理。

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. scanf 中的%s本身始终是一个错误,并且可能是一个安全漏洞。

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.首先,您不会像那样使用feof() ...它显示了可能的 Pascal 背景,无论是在您的过去还是在您的老师的过去。

For reading lines, you are best off using either POSIX 2008 (Linux) getline() or standard C fgets() .对于阅读行,您最好使用 POSIX 2008 (Linux) getline()或标准 C fgets() Either way, you try reading the line with the function, and stop when it indicates EOF:无论哪种方式,您都尝试使用 function 读取该行,并在它指示 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.每次调用fscanf时,它都会读取更多值。 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:这是从诗歌 Ozymandias 的 a.txt 文件中读取的示例:

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.这产生了诗 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".请注意,这首诗有 14 行长,打印出您不知道长度的文件更加困难,因为读取空行会产生 output “x�oA”。 Another issue is if you check if the next line is null by writing另一个问题是,如果您检查下一行是否为 null 通过写入

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快乐编码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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