简体   繁体   English

如何在C中从文件读取特定行?

[英]How can I read a specific line from a file, in C?

All right: So I have a file, and I must do things with it. 好吧:所以我有一个文件,我必须使用它来做。 Oversimplifying, the file has this format: 过度简化,文件具有以下格式:

n
first name
second name
...
nth name
random name
do x⁽¹⁾, y⁽¹⁾ and z⁽¹⁾
random name
do x⁽²⁾, y⁽²⁾, z⁽²⁾
...
random name
do x⁽ⁿ⁾, y⁽ⁿ⁾, z⁽ⁿ⁾

So, the actual details are not important. 因此,实际细节并不重要。 The problem is: I'll have to declare a variable n, I have an array name[MAX], and I'll fill this array with the names, from name[0] to name[n-1]. 问题是:我必须声明一个变量n,我有一个数组名[MAX],然后用名称(从name [0]到name [n-1])填充此数组。

Alright, the problem is: How can I get this input, if I don't know previously how many names do I have? 好的,问题是:如果以前不知道我有多少个名字,如何获得此输入?

For example, I could do it just fine if that was an user input, from the keyboard: I would do it like this: 例如,如果这是用户通过键盘输入的内容,我可以做到这一点:我可以这样做:

int n; char name[MAX];
scanf( "%d", &n);
int i; for (i = 0; i < n; i++)
    scanf( "%s", &N[i]);

And I could go on, do the whole code, but you get the point. 我可以继续进行全部代码,但是您明白了。 But, my input now comes from a file. 但是,我的输入现在来自文件。 I don't know how can I get the input, all I can do is to fscanf() the whole file, but since I don't know its size (the first number will determine it), I can't do it. 我不知道如何获取输入,我只能做fscanf()整个文件,但是由于我不知道它的大小(第一个数字会确定它的大小),所以我不能这样做。 As far as I know (please correct me if that's not true, I am very new to this), we can't use the command "for" and get the numbers gradually as if that was coming from the keyboard, right? 据我所知(如果不正确,请更正我,我对此很陌生),我们不能使用命令“ for”来逐渐获取数字,就好像是从键盘来的一样,对吗?

So, the only exit I see is to find a way to read a particular line from the file. 因此,我看到的唯一出口是找到一种从文件中读取特定行的方法。 If I can do this, the rest is easy. 如果我可以做到,剩下的就很容易了。 The thing is, how can I do that? 问题是,我该怎么办? I google'd it, I even found some questions in there, though it didn't make any sense at all. 我用谷歌搜索,甚至没有发现任何问题。 Apparently, reading a particular line from a file is really complicated. 显然,从文件中读取特定行确实很复杂。

This is from a beginner problem set, so I doubt it is something that complicated. 这是来自初学者的问题集,因此我怀疑它是否太复杂了。 I must be missing something very simple, though I just don't know what it is. 我一定会错过一些非常简单的东西,尽管我只是不知道它是什么。

So, the question is: How would you do it, for instance? 因此,问题是:例如,您将如何做?

How to scan the first number n from the file, and then, scan the others 'n' names, assigning each one to an element in an array (first name = name[0], last name = name[n - 1])? 如何扫描文件中的第一个数字n,然后扫描其他“ n”个名称,将每个名称分配给数组中的一个元素(名字= name [0],姓= name [n-1]) ?

I would suggest looking into End Of File. 我建议调查文件结尾。

while(!eof(fd))
{
...code...
}

Mind you my C knowledge is rusty, but this should get you started. 请注意,我的C语言知识很生锈,但这应该可以帮助您入门。

IIRC eof returns a value (-1) so that's why you need to compare it to something. IIRC eof返回值(-1),这就是为什么您需要将其与某些值进行比较的原因。 Here fd being file descriptor of the file you are reading. 这里fd是您正在读取的文件的文件描述符。 Then after parse of text or count of lines you have your 'n'. 然后,在解析文本或行数之后,您将得到“ n”。

EDIT: Since I'm obviously more tired then I thought(didn't notice your 'n' at the top). 编辑:既然我显然更累了,那么我想(没注意到您的'n'在顶部)。
Read first line malloc for 'n' size array for loop to iterate names. 读取第一行malloc中的'n'大小数组,以循环访问名称。

Since the given format seems to imply that the number of names n is given as the first entry in the file, it would be possible to use the style of reading that the OP describes when reading from stdin. 由于给定的格式似乎暗示名称的数量n作为文件中的第一个条目给出,因此从stdin读取时可以使用OP描述的读取方式。 Use fscanf to read the first integer from the file ( n ), then use malloc to allocate the array(s) for the names, then use a for loop up to n to read the names. 使用fscanf从文件( n )中读取第一个整数,然后使用malloc为名称分配数组,然后使用直到nfor循环读取名称。

However, I am unsure of the meaning of the example data following that with the do x⁽¹⁾, y⁽¹⁾ and z⁽¹⁾ format. 但是,我不确定示例数据的含义是否遵循do x⁽¹⁾, y⁽¹⁾ and z⁽¹⁾格式。 Perhaps I am not understanding part of the question. 也许我不理解问题的一部分。 If it means there are potentially more than n names, then you can use realloc to grow the size of the array. 如果这意味着可能有n名称,则可以使用realloc增加数组的大小。 One way of growing the array that is not uncommon is to double the length each time. 增长阵列的一种常见方法是每次将长度加倍。

Here you go.. I leve compiling and debugging as an exercise for the student. 在这里,您可以开始学习。我将编译和调试作为学生的练习。

The idea is to slurp the whole file into a single array if you files are always small. 想法是如果文件总是很小,则将整个文件包含到单个数组中。 This is so much more efficient than scanf(). 这比scanf()更有效。

char buf[100000], *bp, *N[1000];   // plenty big

memset( buf, '\0', sizeof buf );
if ( fgets( buf, sizeof(buf), fd ) )
{
    int   n  = 0;
    char *bp;
    if ( buf[(sizeof buf)-2)] != '\0' )
    {   // file too long for buffer
        printf( stderr, "trouble: file too large: %d\n", (int)(sizeof buf));
        exit(EXIT_FAILURE);
    }
    // now replace each \n with a \0, remembering where each line is.
    for ( bp = buf, bp = strchr( bp, '\n' ); bp++ )
        N[n++] = bp;
}

If you want to read any size files you need to read the file in chunks, calloc()ing each chunk before a read, and carefully handling of the line fragments left at the end of the current buffer to move them to the next buffer and then properly continuing you reads. 如果要读取任何大小的文件,则需要以块的形式读取文件,在读取之前对每个块进行calloc(),并仔细处理当前缓冲区末尾的行片段,以将它们移至下一个缓冲区,然后正确继续阅读。 Unless you have a limit on how many lines you can read the N may need to also be set up in chunks, but this time remalloc() might be your friend. 除非您对可以读取的行数有限制,否则可能还需要以块的形式设置N,但是这次remalloc()可能是您的朋友。

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

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