从文件中读取会产生意想不到的输出

Reading in from file gives unexpected output

本文关键字:意想不到 输出 文件 读取      更新时间:2023-10-16

我正在从文件中读取,并通过命令行参数的数据解析作业。我在墙上跑,我不知道是什么问题,我希望我能得到一些建议,我错过了什么。

数据文件是这样组成的;在第一行,它有总行数。对于之后的每一行,它都是由|字符分隔的一行字符串。我需要'|'字符,因为我想把字符串分割成子字符串。

这是一个输入文件的例子。

3
league of legends|Teemo|Master Yi|Vayne
apple|samsung|smart phone|smart watch
overwatch|d.va|junkrat|Reinhart

这是我的代码。

int main( int argc, char* const argv[] )
{
 //change string to char* so I can check through each char to see if the 
 //thing I read in is '|' character.
 String Data = (argv[1]);
 ifstream fin (Data.c_str());
 //check whether the file is open.
 if ( !fin.is_open() )
 {
    cout << "Could not open file" << endl;
 }
 else
 {
     int dataLines;
     char dataBuffer[100];
     //The first integer I read in will be how many lines I will loop through
     fin >> dataLines;
     //ignore the new line character and do not include it in the count of
     //dataLines.
     fin.ignore();
     //use noskipws so I can recognize whitespaces.
     fin >> noskipws >> dataBuffer;
     //TEST CODE: COMMENTED OUT FOR NOW.
     //cout<<dataBuffer<<endl;
     //loop for the number of lines
     for(int i = 0; i < dataLines; i++)
     {
         fin.getline(dataBuffer, 100);
         //print the buffer for checking
         cout<<dataBuffer<<endl;
     }
 }
 //close the file.
 fin.close();
 return 0;

}

结果应该是这样的:

league of legends|Teemo|Master Yi|Vayne
apple|samsung|smart phone|smart watch
overwatch|d.va|junkrat|Reinhart

实际结果如下所示

of legends|Teemo|Master Yi|Vayne
apple|samsung|smart phone|smart watch
overwatch|d.va|junkrat|Reinhart

从缓冲区中读取的第一个字已经消失。"league"是缺失的,我试图通过在代码中指定的位置插入测试代码来查看问题所在。对于给定的测试代码,我的输出是

league
of legends|Teemo|Master Yi|Vayne
apple|samsung|smart phone|smart watch
overwatch|d.va|junkrat|Reinhart

所以问题是在用noskipws读取文件和在dataLine上循环的forloop之间。在forloop之前,我的缓冲区是league。然而,一旦我进入循环,它就被传递到的

我在这里错过了什么?可能的解决方案是什么?

主要问题:

fin >> noskipws >> dataBuffer;

做两件事。1. >> noskipws关闭自动跳过空白,由于OP读取流的方式,这是不必要的。2. >> dataBuffer从流中读取第一个单词,在本例中使用单词"league"

解决方法:不要这样做。

其他问题:

fin.ignore();

将只忽略一个字符。但如果有人在计数后留下了一个几乎看不见的空间呢?请使用

fin.ignore(std::numeric_limits<std::streamsize>::max(), 'n');

以确保该行的其余部分被完整地使用。

char dataBuffer[100];

为什么要让自己受苦?而不是使用

std::string dataBuffer;

推荐:

使用std::stringstream和std::getline对'|'上的行进行标记

std::stringstream stream(databuffer);
std::string token;
while (std::getline(stream, token, '|')
{
    std::cout << token << ',';
}

您不需要以下行:

fin >> noskipws >> dataBuffer;

感谢用户4581301它正确读取数据并使用'|'字符进行分割。现在我可以将数据存储到类中。

对于任何可能有相同问题的人,这是修复版本的代码。

int main( int argc, char* const argv[] )
{
String Data = (argv[1]);
ifstream fin (Data.c_str());
if ( !fin.is_open() )
{
   cout << "Could not open file" << endl;
}
else
{
    int dataLines;
    char dataBuffer[100];
    fin >> dataLines;
    fin.ignore();
    for(int i = 0; i < dataLines; i++)
    {
        while(fin.getline(dataBuffer, 100, '|'))
        {
            cout<<dataBuffer<<endl;// check to see if it reads in correctly.
        }
    }
}
fin.close();
return 0;
}