在fstream期间忽略空行

Ignoring empty line during fstream

本文关键字:fstream      更新时间:2023-10-16

编写程序读取文本文件并将其存储在结构中。文本文件示例:

chicken
dog
car

765

当行中有一些文本时,它将被存储到结构中。我尝试过以下几种:

getline(file, aLine);
Info.animalchicken = aLine;
getline(file, aLine);
Info.animaldog = aLine;
getline(file, aLine);
Info.car = aLine;
getline(file, aLine);
Info.number = aLine;

我意识到getline实际上是在获取每一行。当我在程序中运行这个时,chicken将存储在结构Info.animalcicken中。下一行为空,将存储在Info.animaldog中。Dog将存储在Info.car中,依此类推。

我认为这里需要一个控制回路,但我想不出一个好的。如何忽略空行,以便我的文本能够正确地进入结构?

这是我的结构

struct Info {
string animalchicken;
string animaldog;
string car;
int number;
}

循环的想法虽然很原始,但应该能做到;最简单的方法是将逻辑封装在一个单独的函数中:

std::string getlineFilterEmpty(std::istream& s) {
std::string line;
do {
if (!s) {
throw std::runtime_error("End of stream");
}
getline(s, line);
} while(line.size() == 0);
return line;
}

那么获取您的价值就简单到:

Info.animalchicken = getlineFilterEmpty(file);
Info.animaldog = getlineFilterEmpty(file);
Info.car = getlineFilterEmpty(file);

number成员将需要将字符串解析为一个整数,您可以在SO的其他地方找到该整数的代码

逻辑需要类似

读一行。如果读取成功如果行不为空提供线路其他的请重试其他的处理错误

将其转换为代码并捆绑到一个函数中以便于重用,我们得到

std::string getNotEmptyLine(std::istream & in)
{
while (true) // repeat forever!
{
std::string temp;
std::getline(in, temp); // get a line
if (in) // test the line
{
if (line.size() != 0) // line not empty
{
return temp; //give it to caller
}
}
else
{
// handle error. We'll throw an exception, but this isn't the best solution
throw std::runtime_error("Couldn't read a line!"); 
}
}
}

与所有的直译一样,它需要一些工作。让这个函数像getline一样工作也会很有帮助,这样调用者就可以把它作为一个替代品。

std::istream & getNotEmptyLine(std::istream & in, // stream to read
std::string & line, // somewhere to put the string 
char  delim = 'n') // allow different delimiters
{
while (true) // repeat forever!
{
if (std::getline(in, line, delim)) // get a line right in line and test that we got it.
{
if (line.size() != 0) // line not empty
{
break; // success. exit.
}
}
else
{
// line will contain whatever this implementation of `getline` puts or 
// leaves in the string on failure.
break; // fail. Let the caller decide what to do
}
}
return in;
}

用法:

Info info;
std::string aLine;
if (getNotEmptyLine(in, info.animalchicken) &&
getNotEmptyLine(in, info.animaldog) &&
getNotEmptyLine(in, info.car) &&
getNotEmptyLine(in, aLine))
{
info.number = std::stoi(aLine);
}
else
{
// handle error
}

注意:即使这样也可能过于简单化。它无法处理只包含空白的行。一个错位的、几乎看不见的空间将造成严重破坏。如果这是一个问题,请为if (line.size() != 0)添加更多逻辑

这里有一个选项,添加流运算符和一个帮助函数来跳过空行。

#include <iostream>
#include <limits>
#include <sstream>
#include <string>
struct Info {
std::string animalchicken;
std::string animaldog;
std::string car;
int number;
};
// a helper function to do getline but skip empty lines
std::istream& getline_with_content(std::istream& is, std::string& s) {
while(std::getline(is, s)) if(not s.empty()) break;
return is;
}
// an istream operator to read one Info
std::istream& operator>>(std::istream& is, Info& i) {
getline_with_content(
getline_with_content(
getline_with_content(is,
i.animalchicken),
i.animaldog),
i.car);
is >> i.number;
// ignore everything after the number until a newline appears:
is.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
return is;
}
// an ostream operator to print one Info
std::ostream& operator<<(std::ostream& os, const Info& i) {
return os << i.animalchicken << 'n'
<< i.animaldog << 'n'
<< i.car << 'n'
<< i.number << 'n';
}
int main() {
// an example istream with a lot of blank lines:
std::istringstream file(
"chickennn"
"dognn"
"carnnn"
"765n");
Info i;
file >> i;      // read one Info from the stream
std::cout << i; // print one Info
}

演示