Как указывают Тау и Тоби, ваш спецификатор преобразования %c
в вызове scanf()
читает первый пробельный символ между последним числом и оператором.
%c
является особым случаем средиоператоры преобразования: большинство других преобразований по умолчанию пропускают пробелы, пока не встретятся с символами, не являющимися пробелами.Это имеет смысл для ввода пользователем с разрывами строк или табличными текстовыми данными с различным количеством пробелов между столбцами: вы хотите прочитать следующее число или слово и не интересоваться пробелами.
%c
, в отличие отпросто читает следующий символ, включая пробелы и т.д .;это полезно для самостоятельного анализа.
Существует два простых способа исправить это.
Менее навязчивым является добавление некоторого пространства перед %c
: scanf("%d%d%d%d %c", &num1, &num2, &num3, &num4, &op);
.Один пробел - это «директива» в строке формата, указывающая scanf
пропускать все пробела, пока не будет найден непробельный символ.(См. Ниже аннотированную цитату из спецификации.) Ничего другого в программе не нужно менять.
Вы также можете прочитать строку с %s
и проверить ее первый символ.%s
предназначен для чтения следующего слова и поэтому пропускает пробелы самостоятельно.Но вам нужно позаботиться о вводе пользователем, который слишком длинный: он не может переполнять используемый вами буфер, не должен оставаться на входе и вводить в заблуждение позже scanf
s.Мы ограничиваем длину строки до 1, но оставляем пространство для 2 символов, потому что scanf
завершит строку нулевым символом.Мы игнорируем ввод, который не читается, потому что программа все равно завершается.Пример:
// ...
char op[2] = {'\0', '\0'}; // space for the `'\0'`
// Read a string of length 1 (just a single char, in effect)
int numScanned = scanf("%d%d%d%d%1s", &num1, &num2, &num3, &num4, op);
switch (op[0]) // switch on first char in the array
{
case'x':
// ...
}
Некоторые обзорные замечания:
num3 > num1&&num3 > num1&&num3 > num4)
и еще одно логическое выражение имеет два избыточных члена (num3 > num1
).
Это также улучшило бы удобочитаемость для вставки пробелов между операндами и операторами, которые имеют меньший приоритет, например:
num3 > num1 && num3 > num4)
.
Некоторые люди ставят скобки вокруг подвыражений дажеесли они избыточны, но я не дружу с этим.
Последнее, что не менее важно, ваше преобразование формата с плавающей запятой в последнем printf
неверно, потому что тип выражения аргумента - int
;Может быть, вы хотели бы бросить один int, чтобы плавать?Это приведет к тому, что все целые числа будут перемещаться с плавающей точкой и приводить к результату с плавающей точкой:
printf(" %f", ((float)num1 + num2 + num3 + num4) / 4);
Обратите внимание, что для получения полного результата будет недостаточно: вы все равно выполните целочисленное деление, округляя доменьшее целое число, а затем преобразовать это целое число в число с плавающей точкой, что бессмысленно.
Цитаты о
scanf
, из
последней версии стандарта ISO C, 7.21.6.2 (с некоторыми форматированием и примечаниями в квадратных скобках):
Формат составленили ноль или более директивы:
- один или несколько символов пробела;
- обычный многобайтовый символ (ни%, ни пробел)
- или спецификация преобразования [например,% d].
Итак, пробельные символы в строке формата (например, пробел перед %c
в предложенном мной scanf("%d%d%d%d %c", ...
) являются директивой , как %d
... и что? * Директива
Директива , состоящая из символов пробела, выполняетсячтение ввода до первого непробельного символа (который остается непрочитанным) [...].
Ах, хорошо: он пропускает пробел и оставляет следующий доступный символ, что нам и нужно.: -.)