Ошибка переполнения при использовании C std::cin, имеет странное значение внутри переменной (C 11)

#c #cin

#c #cin

Вопрос:

Для программы на C я реализовал 2 функции:

  1. Make1DArray, который принимает размер массива в качестве входных данных и создает одномерный массив такого размера
  2. 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 в неопределенном состоянии. Если вы инициализируете эти переменные, вы заметите, что они не изменятся.

Решение

  1. Не используйте int для удержания размера, а size_t вместо этого. Это должно работать с вашими примерами в большинстве компиляторов.
  2. Если вы хотите, чтобы ваш код был пуленепробиваемым, проверьте состояние on cin , чтобы убедиться, что ввод был действительным, и при необходимости обработайте любые ошибки (в том числе cin.clear() для очистки состояния сбоя перед возобновлением чтения).
  3. Не связано: в коде ваших функций (которые, кстати, пропускают память) size_t также выполните итерацию a . И избегайте malloc() : в C предпочитают new динамически создавать объекты.