【问题标题】:Writing a C++ file to read lines of a text file containing white spaces编写 C++ 文件以读取包含空格的文本文件的行
【发布时间】:2021-10-16 18:39:24
【问题描述】:

我打算编写一个 C++ 程序,它读取文本文件的每一行,并检查每行写入的数据是否代表有效数据。只有介于 0 和 15 之间的整数被视为有效数据。文本文件名作为命令行参数 (argv[1]) 写入程序中。

文本文件的内容是:

1 2  
-3  
5  
0  
d  
15  
16  
3.1  
v7  
4  
8y  
2  
7  

我编写了以下代码,其中while (f.getline(buf, 10)) 用作while 循环条件,因为while(f >> buf) 在遇到空格时停止读取一行。

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

/* A function that checks whether a line of data is valid.
The function returns 1 if a line of data is valid, and 0 if it is invalid. */

int ValidityCheck(char* str)
{
    int i = 0;
    for (i = 0; str[i]; i++)
    {
        if ((str[i] < '0') || (str[i] > '9')) break;
    }

    if (str[i])
    {
        cout << "Invalid data" << endl; 
        return 0; 
    }
    else if (atoi(str) > 15)
    {
        cout << "Invalid data" << endl; 
        return 0; 
    }
    else return 1; 
}


int main(int argc, char* argv[])
{
    char buf[10];
    
    if (argc == 2)
    {
        ifstream f(argv[1], ios::in | ios::binary);
        if (!f) 
        {
            cout << "Error: cannot open file." << endl; 
            return 0;
        }
        while (f.getline(buf, 10))
        {
            if (ValidityCheck(buf) == 1)
            {
                cout << buf << endl;
            }
        }
        f.close();
    }
    return 0;
}

但是,当我运行这段代码时,程序只正确打印出最后一行为 7,并在所有其他行上打印出错误消息,如下所示:

Invalid data
Invalid data
Invalid data
Invalid data
Invalid data
Invalid data
Invalid data
Invalid data
Invalid data
Invalid data
Invalid data
Invalid data
7

如何解决此问题并让程序按预期工作?

【问题讨论】:

  • 示例输入文件的最后一行是8 9。我认为 应该 打印 Invalid data 并且不明白打印 7 怎么可能是正确的。另外你为什么要以二进制模式打开文件?
  • @NathanPierson 我复制了错误的文件。应该是7。错误已更正。

标签: c++ file-io fstream ifstream


【解决方案1】:

问题是文件中的每一行都包含尾随空格。因此,您需要先修剪每条线。我用 rtrim 函数做到了。这是正确的代码:

#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
using namespace std;

/* A function that checks whether a line of data is valid.
The function returns 1 if a line of data is valid, and 0 if it is invalid. */

void rtrim(char *s)
{
    char* back = s + strlen(s);
    while(isspace(*--back));
    *(back+1) = '\0';
}

int ValidityCheck(char* str)
{
    rtrim(str);
    int i = 0;
    for (i = 0; str[i]; i++)
    {
        if ((str[i] < '0') || (str[i] > '9')) break;
    }

    if (str[i])
    {
        cout << "Invalid data" << endl; 
        return 0; 
    }
    else if (atoi(str) > 15)
    {
        cout << "Invalid data" << endl; 
        return 0; 
    }
    else return 1; 
}


int main(int argc, char* argv[])
{
    char buf[10];
    
    if (argc == 2)
    {
        ifstream f(argv[1], ios::in | ios::binary);
        if (!f) 
        {
            cout << "Error: cannot open file." << endl; 
            return 0;
        }
        while (f.getline(buf, 10))
        {
            if (ValidityCheck(buf) == 1)
            {
                cout << buf << endl;
            }
        }
        f.close();
    }
    return 0;
}

输出:

Invalid data
Invalid data
5
0
Invalid data
15
Invalid data
Invalid data
Invalid data
4
Invalid data
2
7

【讨论】:

  • 嗨@YuanLinTech,如果这个或任何答案解决了您的问题,请点击复选标记考虑accepting it。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。
【解决方案2】:

while(f &gt;&gt; buf) 在遇到空格时停止读取一行

不,它没有。 operator&gt;&gt; 跳过前导空格(默认情况下,可以用std::noskipws 关闭),换行符被视为空格。 while(f &gt;&gt; buf) 将愉快地继续读取值,即使超过换行符,只要输入流具有与 buf 数据类型匹配的数据。如果您尝试读取不匹配的内容,则流将进入错误状态,您需要 clear() 才能再次读取。

由于您使用的是 C++ 而不是 C,因此如果您使用 std::stringstd::istringstream 而不是 char[]atoi(),则此任务会更容易处理,例如:

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;

/* A function that checks whether a line of data is valid.
The function returns true if a line of data is valid, and false if it is invalid. */

bool ValidityCheck(const string &str)
{
    std::istringstream iss(str);
    int number;

    while (iss >> number) {
        if (number < 0 || number > 15) {
            return false; 
        }
    }

    return iss.eof();
}

int main(int argc, char* argv[])
{
    if (argc == 2)
    {
        ifstream f(argv[1]);
        if (!f) 
        {
            cout << "Error: cannot open file." << endl; 
            return 0;
        }

        string buf;
        while (getline(f, buf))
        {
            if (ValidityCheck(buf))
                cout << buf << endl;
            else
                cout << "Invalid data" << endl;
        }
    }

    return 0;
}

Online Demo

【讨论】:

    猜你喜欢
    • 2014-10-08
    • 1970-01-01
    • 2013-02-22
    • 2013-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    • 1970-01-01
    相关资源
    最近更新 更多