Почему я продолжаю получать 0 Мой код C не будет входить Switch - PullRequest
0 голосов
/ 18 октября 2018

Напишите программу на C, которая вычисляет максимум, минимум, сумму и среднее из 4 целых чисел.

Эта программа считывает 4 целых числа в десятичном, шестнадцатеричном или восьмеричном форматах и ​​символ, который задает математическую операцию (x для максимума, m для минимума, s для суммы, a для среднего) из командной строки (xterminal в Ubuntu) и печатает результат операции.

Подробности ввода / вывода приведены ниже.

Результат должен быть напечатан как целое число для операций x, m и s;но как число с плавающей запятой для средней (а) операции.

Целочисленные выходные данные будут напечатаны в шестнадцатеричном формате, а значения с плавающей запятой будут напечатаны в научном формате.Вход:

<number 1>[space] <number 2>[space] <number 3>[space] <number 4>[space] <operation>

Пример ввода1: 0xFF 99 077 0 с, Ожидаемый выход 1: 0x1a1

Пример ввода2: 0x10 10 10 010 a, Ожидаемый вывод 2: 1.100000e + 01

Пример ввода 3: 0770 0xFF 270 0xAB м, ожидаемый результат 3: 0xab

Пример ввода 4: 010 0x10 10 0x3 x, ожидаемый результат 4: 0x10

Вот код, который я написал

#include <stdio.h>

int main() {
  int num1, num2, num3, num4;
  char op;

  scanf("%d%d%d%d%c", &num1, &num2, &num3, &num4, &op);

  switch (op)
  {
  case'x':
    if (num1 > num2&&num1 > num3&&num1 > num4)
      printf("%d", num1);
    else if (num2 > num1&&num2 > num3&&num2 > num4)
      printf("%d", num2);
    else if (num3 > num1&&num3 > num1&&num3 > num4)
      printf("%d", num3);
    else
      printf("%d", num4);
    break;
  case'm':
    if (num1 < num2&&num1 < num3&&num1 < num4)
      printf("%d", num1);
    else if (num2 < num1&&num2 < num3&&num2 < num4)
      printf("%d", num2);
    else if (num3 < num1&&num3 < num1&&num3 < num4)
      printf("%d", num3);
    else
      printf("%d", num4);
    break;
  case's':
    printf("%d", num1 + num2 + num3 + num4);
    break;
  case'a':
    printf(" %f", (num1 + num2 + num3 + num4) / 4);
    break;
  }

  return 0;
}

Ответы [ 3 ]

0 голосов
/ 18 октября 2018

Добавление printf("0x%2x", op); после того, как scanf() приведет к распечатке 0x20.

0x20 - это шестнадцатеричное значение для пробела, что подтверждает наши подозрения, что символ пробелачитать вместо требуемого оператора.

Замена строки формата в scanf() (%d%d%d%d%c) на %d%d%d%d %c заставляет метод работать должным образом, поскольку символ пробела теперь игнорируется перед оператором.

Вход: 1 2 3 4 x

Выход: 4

0 голосов
/ 18 октября 2018

Как указывают Тау и Тоби, ваш спецификатор преобразования %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 ... и что? * Директива

Директива , состоящая из символов пробела, выполняетсячтение ввода до первого непробельного символа (который остается непрочитанным) [...].

Ах, хорошо: он пропускает пробел и оставляет следующий доступный символ, что нам и нужно.: -.)

0 голосов
/ 18 октября 2018

Вам нужно добавить пробел между% d s. Вот хорошее описание, почему вам нужно пробел .Таким образом, код станет

scanf("%d %d %d %d %c",&num1,&num2,&num3,&num4,&op);

Для печати в шестнадцатеричном формате вам необходимо использовать "% x", например,

printf("%x",num1);

Для печати в научный формат , используйте "% .10e"

printf("%.10e",num1);

Еще одна вещь, чтобы получить число с плавающей запятой в делении, а каждое число является целым числом, необходимо сделать хотя бы числительили знаменатель с плавающей точкой.В вашем случае

printf("%.10e"(num1+num2+num3+num4)/4.0);
...