Я делаю кодировщик Хаффмана, и для этого мне нужно прочитать данные на входе (который ВСЕГДА будет перенаправленным файлом), чтобы записать частоты, затем создать кодовую книгу, а затем снова прочитать данные на входе, чтобы я мог их кодировать.
Моя проблема в том, что я сейчас пытаюсь проверить, как заставить файл считываться из 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;
}
Отладка показывает, что он застревает в цикле while на строке 40 и, кажется, постоянно получает символ новой строки. Почему бы не выйти из этого цикла? Я предполагаю, что cin.seekg () на самом деле не сбрасывает ввод.
Есть несколько проблем с вашим кодом. Первое, что вы используете
результаты ввода (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 );
Третья проблема: ошибки во входном потоке являются липкими. Как только вы
достигнут конец файла, эта ошибка останется, а все остальные
операции будут запрещены, пока вы не очистите ошибку:
std::cin.clear();
,
Последний комментарий: тот факт, что вы используете std::cin
беспокоит меня
Это, вероятно, будет работать (хотя нет никаких гарантий, что вы можете искать
на std::cin
, даже если ввод перенаправлен из файла), но
знать, что есть нет как вы можете вывести результаты хаффмана
кодирование в std::cout
, Он будет работать под Unix, но, вероятно, не где
остальное. Кодирование Хаффмана требует, чтобы файлы были открыты в двоичном режиме,
что никогда не бывает std::cin
а также std::cout
,
Вот мои $ 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);
}