Seekg (ios :: beg) не возвращается к началу перенаправленного ввода

Я делаю кодировщик Хаффмана, и для этого мне нужно прочитать данные на входе (который ВСЕГДА будет перенаправленным файлом), чтобы записать частоты, затем создать кодовую книгу, а затем снова прочитать данные на входе, чтобы я мог их кодировать.

Моя проблема в том, что я сейчас пытаюсь проверить, как заставить файл считываться из 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 () на самом деле не сбрасывает ввод.

2

Решение

Есть несколько проблем с вашим кодом. Первое, что вы используете
результаты ввода (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,

1

Другие решения

Вот мои $ 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);
}
0

По вопросам рекламы [email protected]