从文件中读取未知长度的字符串

时间:2016-02-27 16:20:51

标签: c++ file scanf

我需要阅读这种格式的文本文件:

n k
S1
S2
S3
.
.
.
Sn

N是和整数,S是字符串。现在,据我所见,用fscanf函数无法读取字符串,而是必须使用char数组。 问题是我需要设置字符数组的长度,即使我无法知道单词的长度:

in = fopen("01.in", "r");

int N, k;

fscanf(in, "%d %d", &N, &k);

for (int i=0; i<N; i++){
    char temp[100];
    fscanf(in, "%s", temp);
}

那么有没有办法可以使用矢量或什么? 或者在关闭此问题无法解决的情况下,我可以将字符串转换为字符串,然后创建字符串向量吗?

2 个答案:

答案 0 :(得分:4)

为什么不使用std::ifstreamstd::getline这样的内容:

std::ifstream in("01.in");

int N, k;

if(!(in >> N >> k))
{
    std::cerr << "Error reading file!" << '\n';
    return EXIT_FAILURE;
}

std::string line; // read lines into this

int i = 0;
while(i < N && std::getline(in, line))
{
    // deal with line here

    ++i; // keep track
}

答案 1 :(得分:1)

这里迈向代码健全性的第一步是停止使用char数组并开始使用std::string。两者之间的最大区别在于阵列的大小在编译时是一成不变的,而std::string的初始大小可以在运行时选择,它也可以增长程序运行时缩小。

  

现在,据我所知,使用string函数无法读取fscanf,   但必须使用char的数组。

从C ++ 11开始,这并不完全正确。 std::string在许多方面与C函数兼容。例如,您可以使用&s[0]安全地获取指向底层缓冲区的指针。因此,您可以从技术上做到这一点:

std::string temp(100, '\0');
fscanf(in, "%s", &temp[0]);

但这并没有让我们走得太远。除了关于这个&#34;解决方案的其他一些不好的事情&#34; (如果读取的字符太多,则会出现单一的,未定义的行为,如果读取的字符太少则会造成浪费),正如您所看到的,原始问题仍然存在;数字100在程序中是硬编码的。这是真正的问题,正如您在评论中所说:

  

如果我的字符串超过100个字符,我的意思是什么?

答案是:不再使用fscanf了。使用std::ifstreamstd::getline功能。 std::getline读取整行,即直到下一个换行符的所有内容,并将结果存储在std::string中。大小和内存管理都是自动处理的:

std::ifstream is("01.in");
std::string temp;
std::getline(is, temp);