почему этот код C ++ печатает после каждой строки? - PullRequest
0 голосов
/ 01 июля 2011
#include <iostream>
using namespace std;



int main() {

  for (;;) {
    char ch ;
    if (cin.fail()) break;
    cin.read((char*)&ch, sizeof(unsigned char));
    cout<<hex<<(unsigned int)(unsigned char)ch<<endl;
    cin.clear();
  }   
}

Почему этот код всегда печатает a после каждой строки? Я просто использовал любой char в качестве стандартного ввода. Добавлено : я пытаюсь прочитать неформатированный ввод с помощью read.

Ответы [ 4 ]

3 голосов
/ 01 июля 2011

Этот код читает символ за раз и записывает значение символа в шестнадцатеричном формате.

Чего вы не ожидаете, так это того, что нажатие клавиши Enter также отправляет символ, который читается вашим звонком на cin.read.

a - это шестнадцатеричное значение этого символа. Поэтому, если вы наберете hello и нажмете Enter, из операторов cout будет получено следующее:

68
65
6c
6c
6f
a

Если вы перестанете отображать значение в шестнадцатеричном формате, вы заметите, что оно печатает 10 после каждой записи.

2 голосов
/ 01 июля 2011

a, который вы видите, является просто шестнадцатеричным значением символа '\n' в конце строки ввода.

Если вы не хотите видеть этот символ, просто оберните строку вывода в оператор if, который проверяет наличие этого символа и не беспокоится о выводе, когда он виден:

if (ch != '\n') {
    cout<<hex<<(unsigned int)(unsigned char)ch<<endl;
}
1 голос
/ 01 июля 2011

GargantuChet правильно объяснил, почему вы получаете 'a's.

В общем, есть много других проблем

1 for (;;)
2 {
3     char ch;
4     if (cin.fail()) break;
5     cin.read((char*)&ch, sizeof(unsigned char));
6     cout << hex << (unsigned int)(unsigned char)ch < <endl;
7     cin.clear();
8 }

В строке 4 вы видите, установлена ​​ли cin.fail(), нос потоками они никогда не запустятся в состоянии сбоя - вы должны попытаться сделать что-то, чтобы это не удалось.Другими словами, вы должны сделать read() , а затем взглянуть на cin.fail().В общем, вы также должны использовать gcount(), чтобы проверить, сколько байтов действительно может быть прочитано (например, несмотря на запрос, скажем, 4, вы можете получить только 2, что не будет считаться ошибкой), но здесь вы запрашиваете только 1символ, так что это может быть проще.

Очистить его немного, но придерживаясь того же основного подхода:

1 for (char ch; cin.read(&ch, sizeof ch); )
2     cout << hex << (unsigned)(unsigned char)ch < <endl;

Это работает, потому что read() возвращает ссылку на cin и оценку«истина» cin является сокращением для запроса о том, был ли введенный до сих пор ввод без ошибок (более строго, по крайней мере, с момента последнего clear(), если вы его используете).

Тем не менее, std::istream, из которых std::cin является экземпляром, также имеет функцию, предназначенную для получения символов, позволяющую упростить цикл до:

for (char ch; std::cin.get(ch); )
    ...

В стороне

Помните, что for( ; ; ) оператор управления состоит из трех частей:

  • код инициализации слева, который также может создавать новые переменные
  • тест: это происходит до 1-го и каждогопоследующее выполнение оператора (ов) цикла
  • кода, который будет выполняться только после каждого выполнения оператора (ов) и перед повторением теста.

Из-за этого такие тесты, как std::cin.get(ch), вызываются и оцениваются на предмет успеха как условие для каждой итерации.Последнее решение, указанное выше, эквивалентно:

{
    char ch;
    while (std::cin.get(ch))
        ...
}
1 голос
/ 01 июля 2011

Я даже не знаю, что вы пытаетесь достичь с этим.Не используйте cin.read для чтения одного символа.Этот цикл должен выглядеть примерно так:

char ch;
while (std::cin.get(ch)) {
    std::cout << std::hex << static_cast<unsigned>(ch) << std::endl;
}

Что касается того, почему он печатает что-то, вы уверены, что это не тот символ, который вы фактически вводите?

...