Символьная переменная не печатается правильно при использовании cin и cout - PullRequest
0 голосов
/ 15 февраля 2019

Мне нужно написать программу, которая принимает входные данные, состоящие из следующих значений, разделенных пробелами: int, long, char, float и double, соответственно, а затем печатать каждое из этих значений в новой строке в выходных данных.

Когда я пишу программу с использованием printf и scanf, она отлично работает.

#include<stdio.h>
int main()
{
    int a;
    long b;
    char c;
    float d;
    double e;
    scanf("%d %ld %c %f %lf", &a, &b, &c, &d, &e);
    printf("%d\n%ld\n%c\n%f\n%lf", a, b, c, d, e);
    return 0;
}

Но когда я использую cin и cout, возникает некоторая проблема.Это происходит, когда вводимый номер long длиннее LONG_MAX.

#include<iostream>
using namespace std;
int main()
{
    int intNumber;
    long longNumber;
    char character;
    float floatNumber;
    double doubleNumber;
    cin>>intNumber>>longNumber>>character>>floatNumber>>doubleNumber;                
    cout<<intNumber<<"\n"<<longNumber<<"\n"<<character<<"\n"<<floatNumber<<"\n"<<doubleNumber;
   return 0;
}

Например, если ввод 211916801 97592151379235457 p 19856.992 -5279235.721231465, вывод первой программы будет

211916801
97592151379235457
p
19856.992
-5279235.721231465

Но вторая программа вышла

211916801
2147483647
╠
-1.07374e+08
-9.25596e+61

Что именно здесь происходит?

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

Вы ввели длинное число вне MAX_LONG = 2147483647. Так что в этом случае это проблема переполнения.

0 голосов
/ 15 февраля 2019

Функция istream::operator>> вызывает функцию std::num_get::get , которая вызывает функцию std::num_get::do_get.

Функция do_get выполняет синтаксический анализ в три этапаи для ступень 3 (преобразование и хранение) есть следующее примечание:

Если функция преобразования приводит к положительному значению, слишком большому, чтобы соответствовать типу vсамое положительное представимое значение хранится в v

[Примечание: v является целевой переменной]

Это объясняет, что происходит со значением, и почему выполучить 2147483647 для значения long.Из этого также можно сказать, что вы находитесь в системе, в которой размер long по-прежнему составляет 32 бита.

Список примечаний для этапа 3 затем продолжается:

В любом случае, в случае сбоя функции преобразования std::ios_base::failbit назначается err

И это объясняет, что происходит с остальными значениями.После установки failbit вы не сможете читать больше из входного потока, пока не очистите состояние.


Более того, если мы вернемся к operator>> эталону , мыобратите внимание, что для C ++ 98 и C ++ 03

Если извлечение не удается ... значение остается неизменным и устанавливается failbit.

И для C++ 11 и более поздние версии

Если извлечение завершается неудачно, в значение

записывается ноль, поскольку ваши переменные после failbit не равны нулю, то мы можем сделать вывод, чтоВы строите это с помощью компилятора до C ++ 11.Значения, которые вы печатаете, являются неинициализированным содержимым, которое не определено .И даже чтение неопределенного содержимого приводит к неопределенному поведению .

...