1

Изучаю Си, помогите решить проблему

Вот мой код:

#include <stdio.h>
#include <Windows.h>

int main(){
    int a, b, c;
    printf("Enter 1 value:");
    scanf("%d", &a);
    printf("\nEnter 2 value:");
    scanf("%d", &b);
    printf("\nEnter action you want to do with entered values[+,-,/,*]");
    scanf("%d", &c);

    switch(c) {
    case '+':
        printf("%d", a+b);
        break;
    case '-':
        printf("%d", a-b);
        break;
    case '*':
        printf("%d", a * b);
        break;
    case '/': 
        printf("%d", a/b);
        break;
    default:
        printf("\nEntered operator is not valid");
        return main();
    }

    system("PAUSE");
    return 0;
}
10
  • 1
    Могу поспорить, второе значение тоже вводится неправильно, потому что вы не выбираете \n из входного потока.
    – VladD
    23 янв 2014 в 10:45
  • @VladD, при правильных данных (числа) все OK. scanf() писали достаточно прагматичные люди, он (кроме формата %c) пропускает пробелы, табуляции, ньюлайны и т.п. Вот при ошибке форматного ввода он оставляет символ, на котором преобразование "сломалось" в потоке. И этот символ надо убирать. На практике надежней всего просто прочесть поток до конца строки (включительно).
    – avp
    23 янв 2014 в 12:07
  • @avp: Хм, в C++ не так :-) Тогда проблема в типа аргумента, да.
    – VladD
    23 янв 2014 в 12:42
  • 1
    @VladD, по поводу типа для c (нужно char, а не int с заменой %d на %c) ему уже @brightside90 написал. Но это будет работать только для ввода операции без пробелов между ней и вторым операндом. -- А что Вы имели в виду, когда написали, что в С++ не так? cin >> ? -- Вообще-то, если не заморачиваться с проверками, то ввод операции (в формате ТС) можно написать так char c, strop[10]; scanf ("%s", strop); c = strop[0];
    – avp
    23 янв 2014 в 12:55
  • 1
    @VladD, вот все три и даже с Enter-ом перед ними avp@avp-xub11:~/hashcode$ ./a.out Enter op1 op2 cop: 11 12 * 11*12 avp@avp-xub11:~/hashcode$ без проблем. -- По поводу переполнения буфера -- ну, понятно, я за надежное программирование. Тут самый простой вариант. В комментарии к ответу @brightside90, более правильный. -- @brightside90, Казалось бы, простой вопрос.. конечно, простой. Сложные тут так активно не обсуждают... (а жаль).
    – avp
    23 янв 2014 в 13:33

2 ответа 2

3

Сделайте переменную с типа char и поменяйте ваш scanf("%d", &c); на scanf("%c", &c);

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

fseek(stdin,0,SEEK_END);

Как я понял - это нужно добавить после первого и второго ввода, если я не прав, просветите, пожалуйста.

UPD2: странно, прогоняю код в 10 студии - всё работает. Прогоняю тут - не работает.

7
  • 2
    Чистить надо не всегда. Если scanf отработал нормально (вернул ожидаемое число, подробнее man scanf), то ничего чистить не надо. А ввод данных у ТС, я бы упростил: char inbuf[LINE_MAX], operation[LINE_MAX]; printf("Enter two integer values and operation [+,-,/,*]: "); fflush(stdout); if (fgets(inbuf, sizeof(inbuf), stdin)) { int op1, op2, c, rc = sscanf(inbuf, "%d %d %s", &op1, &op2, operation); if (rc == 3) { c = operation[0]; // это будет первый не пробел после операндов !!! ... } else puts("Invalid input); ......
    – avp
    23 янв 2014 в 11:35
  • @brightside90 только вот никакой код символа при scanf("%d", &c); не вводится.
    – alexlz
    23 янв 2014 в 11:47
  • @brightside90, а чего Вы удивляетесь. Вы читаете в c следующий символ (прямо скажем байт) после второго операнда. У Вас это '\n'. Для формата scanf("%c"...) все правильно. Если хотите пропустить пробелы между элементами ввода, то читайте "%s" (см. мой комментарий).
    – avp
    23 янв 2014 в 12:01
  • @alexlz согласен, с этим напорол 23 янв 2014 в 12:03
  • @VladD, там комментарии кончились. Посмотрел на пример ideone.com. Вы хотели продемонстрировать, что С++ is ugly (RMS) или terrible (Linus) язык? В принципе во многом с их оценкой крестов я согласен (по крайней мере с input/output) и сам предпочитаю чистый Си. В коде на ideone проблема в смешивании cin >> (оставляет '\n' в потоке) с getline() (читает все до '\n'). Наверное тот формат правильно читать так -- число через cin >>, а потом в цикле getline(), пока не прочтем что-то не только из пробелов. Далее повторяем.
    – avp
    23 янв 2014 в 14:15
0
#include <stdio.h>

int main(){
    int a, b;
    unsigned char c;
    printf("Enter 1 value:");
    scanf("%d", &a);

    printf("\nEnter 2 value:");
    scanf("%d", &b);

    while ( (c = getchar()) != '\n' && c != EOF ); //Очистка от мусора
    printf("\nEnter action you want to do with entered values[+,-,/,*]");
    c = getchar();

    printf("%c\n", c);

    switch(c) {
    case '+':
        printf("%d", a+b);
        break;
    case '-':
        printf("%d", a-b);
        break;
    case '*':
        printf("%d", a * b);
        break;
    case '/': 
        printf("%d", a/b);
        break;
    default:
        printf("\nEntered operator is not valid");
        return main();
    }

    system("PAUSE");
    return 0;
}
3
  • Просто и понятно. если scanf("%c",&c); "автозаполняется", значит нужно сделать так чтобы заполнилось только то что нам нужно. обычно остаются всякие '\n' поэтому добавляем while ( (c = getchar()) != '\n' && c != EOF ); и всё это дело очищаем. 23 янв 2014 в 15:18
  • @Антон Лакотко, тогда уж getche и не надо printf после него
    – paulgri
    23 янв 2014 в 15:48
  • 1
    Действительно, если не зацикливаться на чтении всей тройки одним scanf(), то для чтения символа операции после того, как прочли оба операнда, вот такой код: int c; // int это важно ... while(isspace(c = getchar())); // пропустит лишние пробелы, ньюлайны и т.п. switch (c) { case EOF: .... // м.б. стоит обработать специально IMHO выглядит вполне привлекательно
    – avp
    23 янв 2014 в 20:24

Ваш ответ

By clicking “Отправить ответ”, you agree to our terms of service and acknowledge you have read our privacy policy.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками или задайте свой вопрос.