Почему этот вызов isspace () никогда не возвращает true? [Дубликат]

0

Вероятно, это спрашивается 100 раз раньше, но я не могу найти или создать решение. Все (насколько я проверял) распознается, только нажатие пробела не работает. Я набираю пробел + hit enter, курсор просто переходит к следующей строке, и ничего не происходит. Как я могу сделать эту работу?

#include <cstdlib>
#include <iostream>
#include <cctype>

using namespace std;


int main(int argc, char** argv) {
    cout << "Press a key please:  " << endl;
    char key;
    cin >> key;

    if (isalpha(key))
        cout << key << " is a letter." << endl;
    else if (isdigit(key))
        cout << key << " is a number." << endl;
    else if (isspace(key))
        cout << key << " is a space." << endl;
    else if (ispunct(key))
        cout << key << " is a punctuation" << endl;
    return 0;
}
  • 0
    Сделайте некоторую отладку. Что находится в key когда вы нажимаете пробел?
  • 0
    «Вероятно, это спрашивают 100 раз раньше», да простой поиск показал бы это !
Показать ещё 7 комментариев
Теги:

4 ответа

4
Лучший ответ

Проблема в том, что cin использует пробел как разделитель (также tab, newline). Поэтому вы должны прочитать свой вход, игнорируя разделитель:

cin >> noskipws >> x;

В качестве альтернативы используйте get для одиночных символов:

cin.get(x);

Также посмотрите, как cin Space в c++?

  • 0
    Это работает. Почти все, cin.get(key) >> key; но это не вычислило.
  • 0
    Потому что это не имеет смысла ...
Показать ещё 4 комментария
5

Когда вы используете форматированные функции ввода (т.е. operator>>()), вход по умолчанию пропускает ведущие пробелы. Если вы хотите прочитать char который может быть пробелом, вам нужно будет использовать манипулятор std::noskipws чтобы отключить это пропущение:

if (std::cin >> std::noskipws >> c) {
    // ...
}

В качестве альтернативы вы можете использовать неформатированные функции ввода, например, get() для чтения отдельных символов без изменения настройки потока: неформатированные функции ввода не пропускают ведущие пробелы (что часто вызывает горе при изменении между форматированным вводом, например, для int и неформатированный ввод, например, чтение строки с использованием std::getline()):

if (std::cin.get(c)) {
    // ...
}

Также обратите внимание, что вы можете передавать только положительные значения (и EOF) в любую из функций is....() но char подписан на многих платформах. Сначала вам необходимо превратить свой char в подходящее значение, используя, например, один из

isspace(static_cast<unsigned char>(c))
isspace(std::char_traits<char>::to_int_type(c))
  • 2
    Вы также можете передавать EOF в функции is*() , но это не умаляет вашей точки зрения, что аргумент должен быть значением int для представления unsigned char (или EOF).
  • 0
    @JonathanLeffler: Спасибо! Я исправил ответ.
Показать ещё 2 комментария
3

cin пропускает все пробелы (пробелы, вкладки, новые строки и т.д.) по умолчанию. Вы можете либо изменить свое поведение, либо использовать несколько иной механизм. Чтобы изменить свое поведение, используйте манипулятор noskipws следующим образом:

char key;
cin >> noskipws >> key;

Подробнее об этом вы можете прочитать здесь " Как cin Space в c++? ".

  • 1
    Спасибо за улучшение вашего ответа!
  • 2
    Спасибо за руководство, всегда учусь!
1

Как читать символ пробела.

Замените это:

cin >> key;

который пропускает пробелы и оставляет текст во входном буфере, при этом:

auto const max_streamsize = numeric_limits<streamsize>::max();

key = char( cin.get() );
cin.ignore( max_streamsize, '\n' );

который не пропускает пробелы и потребляет всю входную строку.

Проблема, заключающаяся в том, что вы не потребляете всю строку ввода, такую как завершающий символ '\n', заключается в том, что этот оставшийся текст будет затем прочитан следующей операцией ввода без предварительного ожидания ввода физического пользователя.


Как использовать функции классификатора символов C.

Функции C, такие как isalpha требуют неотрицательного символьного кода или специального значения EOF качестве аргумента.

Однако с большинством C++ компиляторов char по умолчанию подписан. В общем, это означает формальное неопределенное поведение, если оно передается непосредственно, например, isalpha. Например, проверяя, является ли значение char "ø" (норвежский нижний регистр Ø) алфавитным, передавая его прямо на isalpha, является Undefined Behavior с большинством C++ компиляторов и может выходить из строя в режиме отладки с помощью Visual C++ и некоторых других компиляторы.

Простое решение - передать его unsigned char (примечание: не может пройти EOF таким образом):

typedef unsigned char UChar;

... isalpha( UChar( ch ) ) ...

Полный пример, как и исходный код:

#include <iostream>
#include <limits>       // std::numeric_limits
#include <ctype.h>      // isalpha etc.
using namespace std;

auto main()
    -> int
{
    typedef unsigned char UChar;
    auto const max_streamsize = numeric_limits<streamsize>::max();

    for( ;; )
    {
        cout << "Type a character please (x to exit):  ";
        char const key = char( cin.get() );
        cin.ignore( max_streamsize, '\n' );

        if( key == 'x' ) { break; }

        if( isalpha( UChar( key ) ) )
            cout << key << " is a letter." << endl;
        else if( isdigit( UChar( key ) ) )
            cout << key << " is a number." << endl;
        else if( isspace( UChar( key ) ) )
            cout << key << " is a space." << endl;
        else if( ispunct( UChar( key ) ) )
            cout << key << " is a punctuation" << endl;
        else
            cout << key << " is some unknown kind of character" << endl;
    }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню