【问题标题】:Counting alphanumeric characters in a text file in C++在 C++ 中计算文本文件中的字母数字字符
【发布时间】:2012-08-20 22:26:57
【问题描述】:

我编写了一个程序来计算文本文件中字母数字字符的数量。但是,它返回的数字总是大于在线字符计数器返回的数字。

例如,程序将计算此文本中字母数字字符的个数:

如果这些人有奇怪的时尚和最期望的服从 他们至少准备好为他们的非同寻常的事情付出代价 偏心

是162。再次运行程序,它会说文本中有164个字符。再次运行它,它会说有 156 个字符。使用this在线字符计数器,似乎字符数应该低于144(在线字符计数器也包括空格)。

代码如下:

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

int main() {
    char line[100];
    int charcount = 0;
    ifstream file("pg1661sample.txt");
    while (!file.eof()) {
        file.getline(line, 99);
        for (int i = 0; i < 100; i++) {
            if (isalnum(line[i])) {
                charcount++;
            }
        }
    }

    cout << endl << "Alphanumeric character count: " << charcount;
    cin.get();
    return 0;
}

我做错了什么?

【问题讨论】:

标签: c++ text-files alphanumeric


【解决方案1】:

试试:

#include <iterator>
#include <algorithm>
#include <iostream>
#include <cctype>
bool isAlphaNum(unsigned char x){return std::isalnum(x);}
int main()
{
    std::cout << "Alphanumeric character count: " <<
    std::count_if(std::istream_iterator<char>(std::cin),
                  std::istream_iterator<char>(),
                  isAlphaNum
                 ) ;
}

您的代码有问题:

在您阅读文件末尾之前,EOF 不正确:

 // this is true even if there is nothing left to read.
 // If fails the first time you read after there is nothing left.
 while (!file.eof()) {

 // thus this line may fail
     file.getline(line, 99);

最好总是这样做:

 while(file.getline(line, 99))

只有在 getline 实际工作时才进入循环。

您还使用了错误版本的 getline(因为行可能超过 100 个字符)。
尝试使用适用于 std::string 的版本,以便它自动扩展。

std::string  line;
while(std::getline(file, line))
{
     // stuff
}

接下来假设该行正好是 100 个字符。
如果一行只有 2 个字符,会发生什么?

for (int i = 0; i < 100; i++)

基本上,您将扫描数据,它会计算前一行剩余的字母(如果前一行比当前行长)或完全随机的垃圾。如果您仍在使用file.getline(),那么您可以使用file.gcount() 从一行中检索字符数。如果您使用 std::getline() 那么变量 line 将是读取的行的确切大小 (line.size())。

【讨论】:

  • 我明白了!感谢您的详尽回答!
  • 我通常喜欢这个答案,但是,它不是便携式的! &lt;cctype&gt; 中的函数只能使用正值调用,但您的代码会在 char 已签名的系统上创建负值。为避免这种情况,您应该将您的测试声明为bool isAlphaNum(unsigned char)。此声明保证所有char 值都转换为std::isalnum() 的适当int 参数。从性能的角度来看,我也会使用std::istreambuf_iterator&lt;char&gt; 而不是std::istream_iterator&lt;char&gt;(不是前者中的buf)。
【解决方案2】:
while (!file.eof()) {

不要这样做。 eof() 直到 尝试输入失败后才返回 true,因此像这样的循环会运行额外的时间。相反,请这样做:

while (!file.getline(line, 99)) {

当输入结束时循环将终止。

另一个问题是在计算字符的循环中。问问自己:每次通过输入循环时有多少字符被读入缓冲区?那么,为什么计数循环会查看 100 个字符?

【讨论】:

    【解决方案3】:

    您假设 getline() 用正好 100 个字符填充 line。检查getline()读入的字符串长度,例如使用strlen():

    for (int i = 0; i < strlen(line); i++) {
        if (isalnum(line[i])) {
            charcount++;
        }
    }
    

    编辑:另外,请确保您听取其他答案的建议,将getline() 的返回值用于循环条件,而不是调用eof()

    【讨论】:

    • 这似乎已经解决了这个问题。谢谢! :)
    猜你喜欢
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 2021-01-25
    • 2015-08-03
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多