如何在C/C++中从文本文件中读取一行?

19

在大量的谷歌搜索和访问许多论坛后,我仍然没有找到一个好的全面答案来回答这个问题。很多论坛建议使用 istream& getline (char* s, streamsize n ) 函数。我的问题是如果我不知道每行的长度,也无法预测大小会是多少怎么办?在C中它的等效函数是什么?

是否有特定的C/C++函数可以从文本文件中每次读取一行?

请提供带代码片段的解释,这将对我非常有帮助。


3
这不是重复问题,因为它专门涉及 C 语言,而所谓的“重复”问题是关于 C++ 的。 - sje397
@sje 这个问题里也提到了 C++... - Danny Beckett
2
@DannyBeckett 是的,我注意到了。我认为这与我的观点无关,因为这个问题(与其他问题不同)是关于C语言的,这使它在质量上有所不同。 - sje397
5个回答

28
在C++中,您可以使用全局函数std::getline,它接受一个字符串和一个流以及一个可选的分隔符,并读取直到指定的分隔符的一行。例如:

In C++, 可以使用全局函数 std::getline, 它需要一个字符串和一个流作为参数,还可以选择性地指定分隔符,读取至指定分隔符出现的行。例如:

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

int main() {
    std::ifstream input("filename.txt");
    std::string line;

    while( std::getline( input, line ) ) {
        std::cout<<line<<'\n';
    }

    return 0;
}

这个程序从文件中读取每一行并将其输出到控制台。

对于C语言,你可能需要使用 fgets 函数。虽然我已经有一段时间没有用C了,有点生疏,但我相信你可以通过以下方式来模拟上面的C++程序的功能:

#include <stdio.h>

int main() {
    char line[1024];
    FILE *fp = fopen("filename.txt","r");

    //Checks if file is empty
    if( fp == NULL ) {                       
        return 1;
    }

    while( fgets(line,1024,fp) ) {
        printf("%s\n",line);
    }

    return 0;
}

在读取缓冲区的最大长度限制下,该行不能超过您正在读取的缓冲区的最大长度。


谢谢。我们如何在C语言中做同样的事情?有任何建议吗? - Eternal Learner
我更新了我的帖子,附上我记得如何做的内容,希望我所写的是正确的,否则一旦有人指出我的错误,我会更正帖子。 - Jacob
谢谢,我在想是否有比使用固定长度缓冲区更好的方法。我猜现在我知道我们需要硬编码缓冲区大小了。 - Eternal Learner
我猜你可以存储“行”的起始位置(文件开头或换行符后),然后扫描整个文件,直到达到该行的末尾或文件的末尾。然后取得这个位置,找出与第一个位置的字节差异,分配一个足够大以容纳这些字节的缓冲区,使用fseek将文件指针设置为该行的开头并将数据读入缓冲区。我希望这说得有点儿明白。 - Jacob
你可以搜索换行符 '\n' 的结束位置,然后分配一个缓冲区。 - anno
1
请关闭文件指针 fclose(fp); - karelv

19

c语言中,你可以使用fopen和getch。通常,如果你无法确定最长行的长度,你可以分配一个大缓冲区(例如8kb),几乎可以保证获取所有行。

如果有可能出现非常长的行并且必须逐行处理,则可以分配合理的缓冲区,并在接近填充时每次将其大小加倍使用realloc。

#include <stdio.h>
#include <stdlib.h>

void handle_line(char *line) {
  printf("%s", line);
}

int main(int argc, char *argv[]) {
    int size = 1024, pos;
    int c;
    char *buffer = (char *)malloc(size);

    FILE *f = fopen("myfile.txt", "r");
    if(f) {
      do { // read all lines in file
        pos = 0;
        do{ // read one line
          c = fgetc(f);
          if(c != EOF) buffer[pos++] = (char)c;
          if(pos >= size - 1) { // increase buffer length - leave room for 0
            size *=2;
            buffer = (char*)realloc(buffer, size);
          }
        }while(c != EOF && c != '\n');
        buffer[pos] = 0;
        // line is now in buffer
        handle_line(buffer);
      } while(c != EOF); 
      fclose(f);           
    }
    free(buffer);
    return 0;
}

1
字符 c;???!!!关闭(f)?? 和 malloc.h!!! 不是 stdlib.h。 - Nyan

7

在C语言中,使用fgets()函数读取输入时需要知道最大长度以防止截断。


这是C语言的最佳答案,应该有更多的赞。 (实际上getline更好,但不是标准的。) - Nate C-K

6

我并不是很擅长C语言,但我相信这段代码可以让你完成从该行的开头到末尾的单行内容。

 #include<stdio.h>

 int main()   
{      
  char line[1024];    
  FILE *f=fopen("filename.txt","r");    
  fscanf(*f,"%[^\n]",line);    
  printf("%s",line);    
 }    

1
你应该避免使用 fscanf,因为它会导致缓冲区溢出。它没有提供限制输入大小与写入缓冲区(这里是 line)大小的方法。 - Nate C-K

5

getline()是你需要的函数。在C++中使用字符串,你不需要提前知道字符串的大小。

假设使用std命名空间:

 ifstream file1("myfile.txt");
 string stuff;

 while (getline(file1, stuff, '\n')) {
      cout << stuff << endl;
 }

 file1.close();

注意:您需要使用std::getline(std::istream&, std::string&)而不是std::istream::getline - Billy ONeal
3
在C语言中,我们该怎么做? - Eternal Learner
@EternalLearner,我在这里发布了一些示例代码(以及屏幕录像):https://spectrum42.com/introduction-to-c-reading-a-line-of-text/ - mpontillo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接