#c #cin
#c #cin
Вопрос:
Для программы на C я реализовал 2 функции:
- Make1DArray, который принимает размер массива в качестве входных данных и создает одномерный массив такого размера
- Make2DArray, который принимает размер строки и столбца и создает 2D массив заданных размеров строк и столбцов
Основная функция выглядит следующим образом:
int main()
{
cout << "enter 1d array length: ";
int x;
cin >> x;
Make1DArray(x);
cout << "enter 2d array row size: ";
int nrows, ncols;
cin >> nrows;
cout << "enter 2d array col size: ";
cin >> ncols;
Make2DArray(nrows, ncols);
return 0;
}
Когда я ввожу x = 10000000000 (10 ^ 10), программа выводит не запускает вторую функцию и запрашивает ввод. Выходные данные сообщения выглядят следующим образом:
enter 1d array length: 100000000000
enter 2d array row size: enter 2d array col size:
Итак, я проверил значения для x, nrow и ncol, и значения были такими:
- x = 2147483647
- nrows = 0
- ncols = 32767
Я немного погуглил и обнаружил, что при возникновении ошибки переполнения cin присваивает x ближайшему значению. Я понимаю, что для nrows может быть 0, поскольку произошла ошибка.
Чего я не понимаю, так это почему третьей переменной ncols присваивается значение 32767. Я узнал, что 32767 является максимальным значением короткого int, но я не знаю, почему переменная ncols получит это значение.
Кто-нибудь может мне это объяснить? Спасибо!
ETA: я не был уверен, стоит ли добавлять две функции, потому что они действительно простые, но на всякий случай они выглядят так:
void Make1DArray(int arrSize) {
int *arr;
arr = (int *)malloc(arrSize * sizeof(int));
for (int i = 0; i < arrSize; i )
{
arr[i] = i;
}
}
void Make2DArray(int nrows, int ncols) {
int **arr = (int **)malloc(nrows * sizeof(int *));
for (int i = 0; i < nrows; i )
arr[i] = (int *)malloc(ncols * sizeof(int));
int count;
for (int i = 0; i < nrows; i )
for (int j = 0; j < ncols; j )
{
arr[i][j] = count;
}
}
Комментарии:
1. В старые добрые времена, когда
cin >> ncols;
не удалось прочитать, это не изменило бы значениеncols
и, посколькуncols
оно не было инициализировано, вы получаете то, что получаете, и не можете рассчитывать на рифму или причину. Теперь почему произошелncols
сбой …?2. Какая версия C ? Как указывает пользователь4581301, правила для этого изменились с C 11 (я думаю).
3. Когда в C резерв
malloc
для действительно странных крайних случаев и когда вы создаете низкоуровневые строительные блоки для других программ. Предпочитаю использоватьnew
, потому что он делает намного больше для вас и его сложнее испортить. Тем не менее, предпочитайте библиотечный контейнер, подобныйstd::vector
new
.4. Общее предложение: каждый раз, когда вы выполняете транзакцию ввода-вывода, проверяйте поток, прежде чем делать что-либо, что предполагает, что транзакция сработала. Что-то вроде
if (cin >> x) { use x } else { clean up stream }
.5. Поток cin перейдет в состояние сбоя после первого неудачного чтения и его необходимо сбросить перед чтением дальнейших значений
Ответ №1:
Проблема
Проблема в том, что первое переполнение устанавливает сбой из-за переполнения значения. Последующие чтения не выполняются, оставляя nrows
и ncols
в неопределенном состоянии. Если вы инициализируете эти переменные, вы заметите, что они не изменятся.
Решение
- Не используйте
int
для удержания размера, аsize_t
вместо этого. Это должно работать с вашими примерами в большинстве компиляторов. - Если вы хотите, чтобы ваш код был пуленепробиваемым, проверьте состояние on
cin
, чтобы убедиться, что ввод был действительным, и при необходимости обработайте любые ошибки (в том числеcin.clear()
для очистки состояния сбоя перед возобновлением чтения). - Не связано: в коде ваших функций (которые, кстати, пропускают память)
size_t
также выполните итерацию a . И избегайтеmalloc()
: в C предпочитаютnew
динамически создавать объекты.