Похоже, что в scanf_s проблема. Вот мой код.

#include <stdio.h>
#include "stack.h"
int main(){ 
    int disk;
    int hanoi[3][9];
    char input[3] = { 0,0,0 };
    int moveDisk;

    for (int i = 0; i < 9; i++) {
        hanoi[0][i] = i + 1;
        hanoi[1][i] = 0;
        hanoi[2][i] = 0;
    }

    printf("Insert the number of disks(1~9): ");
    scanf_s("%d", &disk);

    while (input[0] != 'q') {
        printf("%3c %3c %3c\n", 'A', 'B', 'C');
        for (int i = 0; i < disk; i++) {
            printf("%3d %3d %3d\n", hanoi[0][i], hanoi[1][i], hanoi[2][i]);
        }
        scanf_s("%s", &input); //getting moving disk -- LOCATION OF ERROR
    }
}

Я понятия не имею, как это решить

0
yoon-seul 4 Июл 2021 в 13:45

3 ответа

Лучший ответ

Несомненно, вы пытались использовать scanf() обычным способом, а Visual Studio сообщила об ошибке, предлагая вам использовать scanf_s()? Это не прямая замена. Для всех спецификаторов формата %c, %s и %[ вы должны предоставить два аргумента - цель, получающую ввод, и размер цели (или строго количество элементов).

В VS2019 даже на уровне предупреждения /W1 он дает четкое объяснение проблемы в этом случае:

warning C4473: 'scanf_s' : not enough arguments passed for format string
message : placeholders and their parameters expect 2 variadic arguments, but 1 were provided
message : the missing variadic argument 2 is required by format string '%s'
message : this argument is used as a buffer size

Не игнорируйте предупреждения и, конечно же, не отключайте их глобально (/W0).

Итак, в этом случае:

scanf_s("%s", input, sizeof(input) ) ;

Снова более строго:

scanf_s("%s", input, sizeof(input)/sizeof(*input) ) ;

Но последнее действительно необходимо только для wscanf_s (широкие символы). В обоих случаях вы можете использовать макрос _countof(), но он специфичен для Microsoft.

scanf_s("%s", input, _countof(input) ) ;

Обратите внимание на отсутствие символа & перед input. Он не нужен для аргумента, который уже является массивом или указателем. Это верно и для scanf().

Хотя есть аргументы в пользу использования scanf_s() вместо scanf() (что по своей сути более опасно), это может просто усложнить жизнь, если вы учитесь на стандартных примерах или используете другой набор инструментов. Более простое решение - просто отключить предупреждение и понять, что оно небезопасно:

enter image description here

1
AmigoJack 5 Июл 2021 в 11:19

Вы процитировали строку

scanf_s("%s", &input);

В этой строке есть несколько ошибок:

  1. Вы читаете строку в массив символов. Это исключение из обычного шаблона для scanf, поскольку вам не нужен &.

  2. Вы используете полустандартный scanf_s вместо обычного scanf. scanf_s должен быть "более безопасным", но для того, чтобы он обеспечивал гарантии безопасности, вы также должны называть его иначе, чем обычно scanf. Вы должны сообщить ему размер массива, в который вы читаете строку. В сочетании с №1 выше, я считаю, что более правильным вызовом будет scanf_s("%s", input, 3);.

  3. В большинстве случаев строка размера 3 была бы слишком маленькой для чтения строки ввода от пользователя. Поскольку в этом случае я предполагаю, что вы читаете только «строку», чтобы дать себе возможность нажать RETURN, прежде чем программа совершит еще один проход через свой цикл, я думаю, что это нормально.

  4. Как я уже упоминал, scanf_s не совсем стандартный, поэтому его использование неоднозначно. Плюсы: 1. Якобы безопаснее. 2. Некоторые люди (включая, возможно, вашего инструктора) рекомендуют всегда использовать его по этой причине. Минусы: 3. Он полностью стандартный (это необязательная часть стандарта), что означает, что не все компиляторы и библиотеки C его поддерживают. 4. Его шаблоны вызова обязательно сильно отличаются от обычных scanf; это не простая замена, поэтому возможна путаница. (Я не говорю «не используйте scanf_s», но вы должны знать о его несколько сомнительном статусе.)

  5. Если вы хотите прочитать строку ввода от пользователя, прежде чем продолжить, и если в строке может быть «q» или что-то еще, scanf (любой разновидности) может быть не лучшим выбором. В частности, %s хочет прочитать строку без пробелов, поэтому, если вы просто нажмете клавишу Return, он будет продолжать ждать. Это может быть для вас проблемой, а может и нет. (Или, возможно, вам не о чем беспокоиться прямо сейчас; возможно, вам нужно поджарить рыбу побольше.)

1
Steve Summit 4 Июл 2021 в 13:52

Как я могу решить эту проблему при отладке?

Пошагово запускайте вашу программу с помощью отладчика. Затем, когда вы получаете исключение, вы нашли строку, вызывающую его.

Перезапустите вашу программу и перейдите к строке, где произойдет исключение. То есть остановка на этой строке без ее выполнения.

Затем с помощью отладчика вы можете просмотреть все переменные и попытаться понять, соответствует ли их значение ожидаемому.

Это ответ на ваш вопрос?

Кстати: компилятор должен хотя бы выдавать некоторые предупреждения. Вам действительно следует сначала исправить эти предупреждения. Если у вас нет предупреждений, убедитесь, что вы включили все предупреждения в параметрах компилятора.

1
fpiette 4 Июл 2021 в 14:16