1
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <string>
#include <iomanip>
#include <fstream>
#include <stdio.h>
using namespace std;

int main()
{
    ifstream file;
    string filename;
    char character;
    int letters[153] = {};

    cout << "Enter text file name: ";
    cin >> filename;    
    file.open(filename.c_str());
    if (! file.is_open())
    {
        cout << "Error opening file. Check file name. Exiting program." << endl;
        exit(0);
    }

    while (file.peek() != EOF)
    {
        file >> character;
        if(!file.fail())
        {
            letters[static_cast<int>(character)]++;
        }
    }

    for (int i = 0; i <= 153; i++)
    {
        if (letters[i] > 0)
        {
            cout << static_cast<char>(i) << " " << letters[i] << endl;
        }
    }

    exit(0);
}

#endif

大家好,我当前的代码计算文本文件中每个字母的频率。但是,它不计算空格的数量。有没有一种简单的方法可以打印出 .txt 文件中的空格数?

另外,当我尝试访问矢量项目时,为什么会遇到段错误?例如,如果我使用:

cout << " " + letters[i] << endl;,它显示一个段错误。有任何想法吗?

太感谢了。

4

2 回答 2

2

默认情况下,iostreams 格式化输入提取操作(使用 的操作>>)跳过所有空白字符以到达第一个非空白字符。也许令人惊讶的是,这包括提取运算符 for char。为了将空白字符视为要照常处理的字符,您应该在处理之前更改使用noskipws操纵器

file << std::noskipws;

不要忘记稍后将其重新设置:

file << std::skipws;

如果您是那些想要创建一个函数以使流状态的这一方面(甚至在所有方面)保持在它退出之前的状态的那些疯狂的人之一,该怎么办?自然地,C++ 提供了一种令人沮丧的丑陋方式来实现这一点:

std::ios_base::fmtflags old_fmt = file.flags();
file << std::noskipws;

...  // Do your thang

file.flags(old_fmt);
于 2013-10-24T03:40:41.660 回答
1

我只是将其发布为您显然正在尝试的另一种方法。这使用您在代码中使用的相同查找表方法,但使用istreambuf_iteratorslurp 直接从流缓冲区中提取未格式化(和未过滤)的原始字符。

#include <iostream>
#include <fstream>
#include <iterator>
#include <climits>

int main(int argc, char *argv[])
{
    if (argc < 2)
        return EXIT_FAILURE;

    std::ifstream inf(argv[1]);
    std::istreambuf_iterator<char> it_inf(inf), it_eof;

    unsigned int arr[1 << CHAR_BIT] = {};
    std::for_each(it_inf, it_eof,
         [&arr](char c){ ++arr[static_cast<unsigned int>(c)];});

    for (int i=0;i<sizeof(arr)/sizeof(arr[0]);++i)
    {
        if (std::isprint(i) && arr[i])
            std::cout << static_cast<char>(i) << ':' << arr[i] << std::endl;
    }

    return 0;
}

在源代码文件本身(即上面的代码)上执行此操作会生成以下内容:

 :124
#:4
&:3
':2
(:13
):13
*:1
+:4
,:4
/:1
0:3
1:2
2:1
::13
;:10
<:19
=:2
>:7
A:2
B:1
C:1
E:2
F:1
H:1
I:3
L:1
R:2
T:2
U:1
X:1
[:8
]:8
_:10
a:27
b:1
c:19
d:13
e:20
f:15
g:6
h:5
i:42
l:6
m:6
n:22
o:10
p:1
r:37
s:20
t:34
u:10
v:2
z:2
{:4
}:4

只是一种不同的方法,但希望很明显,如果您深入挖掘以找到其中的内容,通常 C++ 标准库会提供优雅的方法来做您想做的事情。祝你好运。

于 2013-10-24T04:56:08.783 回答