Почему этот макрос assert не работает для целых чисел, меньших или равных 0, но работает для значений, превышающих INT_MAX? - PullRequest
1 голос
/ 19 апреля 2019

В алгоритме, который я должен разработать, я решил установить, являются ли входные данные <=0 или >INT_MAX и, если это так, будет отображаться сообщение об ошибке. Странно только значения больше INT_MAX. Что я могу сделать, чтобы улучшить реализацию?

int total_digits;
scanf("%d", & total_digits);
assert(total_digits <= 0 && "Whoops your input data cannot be less or equal to 0. Please rerun the program and enter another input data.");
assert(total_digits > INT_MAX && "Whoops your input data cannot be bigger than 2147483647. Please rerun the program and enter another input data.");
while (total_digits) {
    compute_no_of_pages(total_digits);
    scanf("%d", & total_digits);
    assert(total_digits <= 0 && "Whoops your input data cannot be less or equal to 0. Please re-run the program and enter another input data.");
    assert(total_digits > INT_MAX && "Whoops your input data cannot be bigger than 2147483647. Please rerun the program and enter another input data.");
}

Ответы [ 2 ]

2 голосов
/ 19 апреля 2019

Assert создаст ошибку и завершит программу, если аргумент окажется ложным.

assert (total_digits <= 0 && "К сожалению, ваши входные данные не могут быть меньше или равны 0. Пожалуйста, перезапустите программу и введите другие входные данные"); </p>

Это означает завершение программы, если total_digits больше 0, что полностью противоположно тому, что предлагает ваш комментарий

Также вы можете объединить оба оператора в одном выражении

assert(total_digits > 0 && total_digits < INT_MAX);
1 голос
/ 19 апреля 2019
  1. Ваши выражения утверждений выглядят обратными;Вы хотите проверить, что total_digits больше , чем ноль, и меньше , чем INT_MAX.

  2. assert должно бытьиспользуется для условий, которые, когда ложно, указывают ошибки в программе. Он не должен использоваться для сообщения об ошибках во входных данных.Вместо этого сделайте что-то вроде этого:

    if (total_digits < 0) {
        fputs("Whoops your input data cannot be less or equal to 0.\n"
              "Please re-run the program and enter another input data\n",
              stderr);
        exit(1);
    }
    

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

  3. Вы никогда не должны использовать scanf, по многим причинам, наиболее важной из которых сейчас является то, что scanf("%d") будет только читать число.Для такой программы вы хотите прочитать , что бы пользователь ни набрал , а затем попытаться проанализировать ее как число.Лучший способ сделать это в стандартном C - с fgets и strtol.Если у вас есть getline, которого нет в ISO C, но в POSIX, вы должны использовать его вместо fgets, чтобы вам не приходилось беспокоиться о том, как долго строка будет принята.

  4. Переменная int не может содержать значение больше MAX_INT.Если число, введенное пользователем, больше MAX_INT, scanf("%d") имеет неопределенное поведение, поэтому вы не можете проверить, слишком ли велико число, увидев, сделал ли scanf что-то особенное.(Это еще одна из причин, по которой вам никогда не следует использовать scanf.)

    Правильный способ проверки слишком большого числа - осторожное использование strtol, например:

    int total_digits = 0;
    while (total_digits == 0) {
        char input_line[BUFSIZ];
        fgets(input_line, BUFSIZ, stdin);
        // exercise: check for line being too long here
    
        long l_total_digits;
        char *endp;
        errno = 0;
        l_total_digits = strtol(input_line, &endp, 10);
        if (endp == input_line) {
            fputs("You must enter a number\n", stderr);
            continue;
        }
        if (*endp) {
            fputs("Don't enter anything after the number\n", stderr);
            continue;
        }
        if (errno) {
            fputs("Number is too large\n", stderr);
            continue;
        }
        // exercise: check for the number being < 0 or > INT_MAX here, but
        // only if necessary
    
        // If we get here, the number is good.
        total_digits = l_total_digits;
    }
    

    (l_total_digits - это long, потому что, к сожалению, strtoi.)

...