Что-то я не понял. Когда определяется массив в инструкции char str[21];, то в ячейку str[21] автоматически попадает завершающий нуль-символ.
Это откуда вы такое взяли? Ничего подобного. Весь массив изначально содержит мусор (подразумевая автоматический массив). Кроме того, последняя ячейка такого массива - это `str[20]`. Не существует никакого `str[21]`.
Кроме этого у нас есть 21 свободная ячейка с номерами в диапазоне от нуля до 20. Зачем надо дополнительно записывать ещё один завершающий нуль-символ вызовом scanf ?
Но функция `scanf_s` не обязательно использует все 21 ячейки. Функция `scanf_s` запишет в этот массив
строку, которая запросто может быть намного короче. Вот для того, чтобы пометить конец строки функция `scanf_s` и поместит в ее конце завершающий \0. Это само
определение "строки" в языке С: строка по определению завершается нулевым символом.
Зачем так делать ?
Не совсем понимаю, о чем именно вопрос.
Как делать?
-- 28.10.2021, 09:25 --[quote="zykov в [url=http://dxdy.ru/post1535700.html#p1535700]
А какие критерии используются для оценки "правильности" кода?
Критерий должен быть ясен из контекста. Формальных устоявшихся определений нет.
Для языка С обычно "корректным" называют код, который соответствует синтаксису и ограничениям (cosntrаints), описанным в стандарте языка. (Это фактически требование выдачи диагностики, взятое из стандарта языка.) То есть "корректный" код - это формально
компилируемый код. При этом "корректный" код может иметь неопределенное поведение. В языке С++ дела обстоят аналогично.
"Правильным" же обычно называют код, который не только "корректен", но еще и не страдает от неопределенного поведения. "Правильность" запросто может зависеть от платформы, но этот обычно ясно из контекста.
Например, программа Qlin из сообщения выше
#include <iostream>
int main() {
char str[2];
str[0] = 'a';
str[1] = 'b';
std::cout << str;
}
является "корректной", но не "правильной". Ее поведение не определено.