2012-03-01 3 views
0

Я работаю над автоматической системой суммирования в своем классе C++ и задаю вопрос относительно одного из сопоставлений ASCII, которые я делаю. Вот код:Что означает -1 в ASCII?

char ch; 
    string sentence; 
    pair<char, char> sentenceCheck; 
    int counter = 0; 
    while (!ifs2.eof()) 
    { 
     ch = ifs2.get(); 
     ch = tolower(ch); 

     if (ch == 13) 
      ch = ifs2.get(); 

     if (ch != 10 && ch != '?' && ch != '!' && ch != '.') 
      sentence += ch; 

     sentenceCheck.first = sentenceCheck.second; 
     sentenceCheck.second = ch; 

     cout << sentenceCheck.first << "-" << (int)sentenceCheck.first << " ---- " << sentenceCheck.second << "-" << (int)sentenceCheck.second << endl; 

     if(sentenceCheck.second == ' ' || sentenceCheck.second == 10 || sentenceCheck.second == -1) 
     { 
      if(sentenceCheck.first == '?' || sentenceCheck.first == '!' || sentenceCheck.first == '.') 
      { 
       istringstream s(sentence); 
       while(s >> wordInSentence) 
       { 
        sentenceWordMap.insert(pair<string, int>(wordInSentence, 0)); 
       } 
       //sentenceList.push_back(pair<string, int>(sentence, 0)); 
       sentence.clear(); 
      } 
     } 
    } 

Что делается здесь (с два, если заявления) проверяет, был ли новое предложение начато в тексте, который должен быть проанализирован и рассмотрен позднее. Условные работы работают, но только потому, что мы обнаружили, что мы должны также проверить это на -1. Любые идеи, что это представляет?

+0

ASCII, не распространяются это только 7 бит http://www.asciitable.com/ – kenny

+3

You должен использовать if (! ifs2), который проверяет режимы сбоя _and_ EOF. –

+0

Кроме того, в будущем большинство калькуляторов имеют режим программистов (по крайней мере, Windows, Mac, GNOME и KDE). Я думаю, что все они имеют какую-то кнопку «Показать в ASCII». – Linuxios

ответ

1

В качестве символа ASCII -1 не представляет ничего (что означает, что -1 не является допустимым значением ASCII). В качестве возвращаемого значения из get() это означает, что операция чтения не удалась - скорее всего, из-за окончания файла.

Обратите внимание, что функция eof() не возвращает true, если следующий вызов get завершится с ошибкой из-за того, что конец файла достигнут - он возвращает true, если предыдущий вызов для получения отказа из-за конца файл достигнут.

6

-1 не представляет ничего в ASCII. Все коды ASCII находятся в диапазоне [0, 127]. Это даже не гарантировано C++, что -1 является допустимым значением для char.

Проблема заключается в том, что вы не проверять возвращаемое значение из ifs2.get(), который возвращает int (не char!), Которые могут быть -1 в конце файла. Правильный способ проверить это

int ch = ifs2.get(); 
if (!ifs2) 
    // break the loop 

, так как значение EOF не гарантированно -1 (на самом деле это std::char_traits<char>::eof()).

(. Кстати, вы не должны писать ASCII-коды в качестве магических чисел, использование \n для перевода строки, \r для возврата каретки.)

+0

Общим сокращением для этого является 'while (ifs2 >> ch) {/ * process char * /}' –

1

Это не ASCII, это ошибка, возвращаемый istream::get

ch = ifs2.get(); 

Это, вероятно, EOF, т. Е. У вас закончились входные данные.

+1

+1, действительно. И OP должен собирать возвращаемое значение в 'int', а не' char. –

2

while неправильно структурированы: вам нужно проверить eof() сразу после get():

for (;;) 
{ 
    ch = ifs2.get(); 
    if (ifs2.eof()) break; 
    ch = tolower(ch); 

    if (ch == 13) 
    { 
     ch = ifs2.get(); 
     if (ifs2.eof()) break; 
    } 

    ... 
} 

-1, вероятно, индикатор EOF.

Примечание (как уже указывалось) get() возвращает int, а не char.

0

Дело в том, что проверка на наличие работ -1 является несчастным случаем и не имеет значения с значениями ASCII (которые используют только 0 до 127). Ваш код не сработает , если либо простой символ без знака (скомпилируйте с /J с VC++, я думаю), или EOF не является -1 (редко, но все, что это гарантирует, это отрицательный). Вы тоже код, если вход Latin-1, и он содержит 'ÿ'.

Основная проблема в вашем коде заключается в том, что вы не проверяете правильность завершения файла . Проведение теста в верхней части цикла не работает; вам необходимо проверить на предмет отказа (не eof()) после ввод, перед использованием значение считано. Есть несколько способов сделать это; в вашем случае, проще всего возможно использовать:

if (!ifs2.get(ch)) { 
    // Input failed... 
} 

В качестве альтернативы, вы можете сделать chint, и сделать:

ch = ifs2.get(); 
if (ch == EOF) { 
    // Input failed... 
} 

Это имеет то преимущество, что следующий вызов tolower НИКАКОГО более длинный неопределенное поведение (tolower принимает значение int, которое должно быть в диапазоне [0...UCHAR_MAX] или EOF — если простая char подписанный, вы не , гарантирующий это). С другой стороны, это не позволяет цепочки, т.е. вы не можете писать эквивалент:

while (ifs2.get(sentenceCheck.first) 
     && ifs2.get(sentenceCheck.second)) { 
    // ... 
} 

(что может быть полезно в некоторых случаях).

FWIW: метод вы используете нечто, называемое скользящее окно в поток, и это стоит толкая его в отдельный класс для обрабатывать логику сохранения окна заполнены и до настоящего времени. Кроме того, для вашей проблемы может использоваться простой конечный автомат.

И я бы определенно избегал использования магических констант: если вы хотите проверить возврат каретки, сравните с '\r'. Аналогично, новая строка - '\n', и внешняя if, похоже, вы хотите проверить пробелы (isspace(static_cast<unsigned char>(sentenceCheck.second))), , а не сравнивать их.

Я также могу добавить, что ваш код не может правильно обрабатывать предложения, которые заканчиваются цитатой, например This is the "text in your input."; он также не подходит для сокращений, таких как Mr. Jones is here.. Но эти проблемы могут выходить за рамки вашего задания. (Аббревиатуры один является , вероятно, не вполне разрешимы:. Иногда "etc." является концом предложений, а иногда это не так)

Смежные вопросы