我正在制作一个霍夫曼编码器并且这样做我需要读取输入(它总是一个重定向的文件)来记录频率,然后创建码本然后再次读取输入以便我可以编码它
我的问题是我目前正在尝试测试如何从cin读取文件两次。
我在网上看到cin.seekg(0)或cin.seekg(ios :: beg)或cin.seekg(0,ios :: beg)都应该完全正常,只要文件被重定向而不是管道传输。但是,当我这样做时,似乎根本没有对cin的位置做任何事情。
以下是我目前使用的代码:
#include<iostream>
#include"huffmanNode.h"
using namespace std;
int main(){
//create array that stores each character and it's frequency
unsigned int frequencies[255];
//initialize to zero
for(int i=0; i<255; i++){
frequencies[i] = 0;
}
//get input and increment the frequency of corresponding character
char c;
while(!cin.eof()){
cin.get(c);
frequencies[c]++;
}
//create initial leafe nodes for all characters that have appeared at least once
for(int i=0; i<255; i++){
if(frequencies[i] != 0){
huffmanNode* tempNode = new huffmanNode(i, frequencies[i]);
}
}
// test readout of the frequency list
for(int i=0; i<255; i++){
cout << "Character: " << (char)i << " Frequency: " << frequencies[i] << endl;;
}
//go back to beginning of input
cin.seekg(ios::beg);
//read over input again, incrementing frequencies. Should result in double the amount of frequencies
**THIS IS WHERE IT LOOPS FOREVER**
while(!cin.eof()){
cin.get(c);
frequencies[c]++;
}
//another test readout of the frequency list
for(int i=0; i<255; i++){
cout << "Character: " << (char)i << " Double Frequency: " << frequencies[i] << endl;
}
return 0;
}
调试显示它在第40行的while循环中卡住,并且似乎不断获得换行符。为什么不退出这个循环呢?我假设cin.seekg()实际上并没有重置输入。
答案 0 :(得分:1)
您的代码存在一些问题。首先是你使用
输入结果(cin.get( c )
)没有检查
输入成功了。这总是一个错误;在你的情况下,它会
可能只会导致计算(以后输出)最后一个
字符两次,但它可能导致未定义的行为。你必须
在每次输入之后检查输入流是否处于良好状态
使用值输入。通常的做法是:
while ( cin.get( c ) ) // ...
,将输入直接置于循环条件中。
第二个是声明:
cin.seekg( std::ios::beg );
我甚至惊讶于这甚至编译:有两个
seekg
的重载:
std::istream::seekg( std::streampos );
和
std::istream::seekg( std::streamoff, std::ios_base::seekdir );
std::ios::beg
的类型为std::ios_base::seekdir
。这可能是一个
强制定义std::streampos
和std::ios_base::seekdir
一种方式,以便有一个隐含的转换
std::ios_base::seekdir
到std::streampos
,但在我看来,它
不应该,因为结果几乎肯定不是你想要的。
寻找文件的开头:
std::cin.seekg( 0, std::ios_base::beg );
第三个问题:输入流中的错误是粘滞的。一旦你
到达文件末尾,该错误将保留,所有其他错误
在您清除错误之前,操作将是no-ops:
std::cin.clear();
。
最后一条评论:你使用std::cin
的事实让我担心。
它可能会起作用(虽然不能保证你可以寻求
在std::cin
上,即使输入是从文件重定向的),但确实如此
意识到有没有方式可以输出霍夫曼的结果
编码为std::cout
。它可以在Unix下运行,但可能没有
其他。霍夫曼编码要求文件以二进制模式打开,
对于std::cin
和std::cout
,情况绝非如此。
答案 1 :(得分:0)
这是我的0.02美元,使这更多的C ++和解决你的寻求问题:
#include <sstream>
#include <iostream>
#include <iomanip>
//#include"huffmanNode.h"
std::string slurp()
{
std::stringstream ss;
ss << std::cin.rdbuf();
return ss.str();
}
void dump_freq(unsigned int (&frequencies)[255])
{
int i = 0;
for(auto freq : frequencies) {
if (freq) {
std::cout << "Character: " <<
std::ios::hex << std::setw(2) << "0x" << i++ <<
" Frequency: " << freq << std::endl;
}
}
}
int main() {
const auto data = slurp();
//create array that stores each character and it's frequency
unsigned int frequencies[255] = { 0 };
//get input and increment the frequency of corresponding character
for(auto ch : data) frequencies[ch]++;
//create initial leafe nodes for all characters that have appeared at least once
for(int i=0; i<255; i++) {
if(frequencies[i] != 0) {
//huffmanNode* tempNode = new huffmanNode(i, frequencies[i]);
}
}
// test readout of the frequency list
dump_freq(frequencies);
// read over input again, incrementing frequencies. Should result in double
// the amount of frequencies
for(auto ch : data) frequencies[ch]++;
//another test readout of the frequency list
dump_freq(frequencies);
}