scanf зависает после присвоения массива 0.o?

Я запускаю этот код, и он запрашивает ввод пользователя, а затем зависает, когда начинает вводить все эти числа в позицию массива. Я разместил здесь несколько тестов, чтобы помочь мне понять, что вызывает зависание. Я не могу понять это. Это либо что-то глупо простое, либо что-то с моим компилятором (Code::Blocks).

    // Chapter 9 Programming Project #1

    #include <stdio.h>

    #define N 10

    void selection_sort(int n, int a[]);

    int main(void)
    {
        int i, a[N];

        printf("Enter a series of integers: ");
        for (i = 0; i < N; i++) {
            scanf("%d", &a[i]);
            printf("Scanf Test #%d and %d\n", i, a[i]);
        }

        printf("Scanf Test\n");
        selection_sort(N - 1, a);

        // iterate through array
        for (i = 0; i < N; i++) {
            printf("%d ", a[i]);
        }
        printf("\n");

        return 0;
    }

    void selection_sort(int n, int a[n])
    {
        // Search for the highest value
        // Place that value at the end
        // Call the function with the end of the array removed
        // Create a way for it to break the cycle
        int i, temp, high = n;
        printf("Function Called\n");
        for (i = 0; i < n; i++) {
            printf("Test: %d", i);
            if (a[i] > a[high]) {
                temp = a[high];
                a[high] = a[i];
                a[i] = temp;
                printf("Test Pass: %d\n", i);
                if (n - 1 > 1)
                    selection_sort(n - 1, a);
            }
        }
    }

Примечание. Эта программа печатает Scanf Test #0 and 1 снова и снова, пока последнее число не будет присвоено его позиции в a[i]....где #0 and 1, 1 будет первым числом, введенным пользователем.

Редактировать: чтобы устранить путаницу, если пользователь ввел только 1 число, равное «1», тогда программа присвоит это значение и/или все другие введенные значения, и это можно проверить с помощью «Теста сканирования», который я ввел, который будет выведите позицию в массиве, за которой следует номер, который ей был присвоен. После того, как все значения были присвоены массиву, теоретически он должен запустить следующий тест, который находится прямо под циклом for. Проблема в том, что это не так, вместо этого программа зависает после распечатки последней позиции и номера, который был назначен....

Программа не делает ничего другого, а просто сидит там, один человек ниже заявил, что он запустил этот код, и он работал нормально... что заставляет меня поверить, что это проблема компиляции в моем IDU (Code::Blocks)


person John Conner    schedule 16.04.2014    source источник
comment
Тогда что происходит после #0 и 1 снова и снова?   -  person M.M    schedule 16.04.2014
comment
Скажу лишь, что этот код у меня работает (Apple LLVM 5.1). Он запросил у меня 10 целых чисел, напечатал кое-что и, в конце концов, напечатал 10 целых чисел в порядке возрастания.   -  person carlosdc    schedule 16.04.2014
comment
Разве if (n - 1 > 1) не следует заменить на if (n - 1 >= 1)?   -  person Mohit Jain    schedule 16.04.2014
comment
извините, я потерял сознание после публикации этого, он просто зависает, он никогда не доходит до теста после цикла for   -  person John Conner    schedule 17.04.2014
comment
спасибо, carlosdc, я думал, что это как-то связано с моим компилятором... учитывая, что один и тот же точный код работал во всех других программах, которые таким же образом назначали входные данные массиву.   -  person John Conner    schedule 17.04.2014
comment
Да, кстати, немного не по теме, но как изменить свое имя с user3404748? XD   -  person John Conner    schedule 17.04.2014
comment
О, и Мохит Джейн, это было редактирование, которое я сделал перед добавлением тестов, потому что изначально я думал, что моя функция вызывает бесконечный цикл, поэтому я добавил это, чтобы убедиться, что выборка не выполняется после того, как она дошла до точки, где остался только один персонаж. Я использовал подход, в котором он будет постоянно сужать итерацию, только через значения, которые еще не были отсортированы.   -  person John Conner    schedule 17.04.2014


Ответы (2)


Эта программа снова и снова печатает «Scanf Test # 0 и 1».

Это следствие отсутствия проверки результата scanf. Если scanf не может прочитать целое число, то он оставляет поток нетронутым и сообщает об ошибке. Вы не проверяете это, так что это сработало один раз и не удалось 9 раз.

Если вы введете 10 целых чисел, все будет работать нормально; однако очевидно, что вы вводите какие-то другие вещи, такие как буквы, что приводит к сбою извлечения целого числа.

Когда в строке формата есть одна спецификация преобразования ("%d"), scanf может возвращать:

  • 1 - успех
  • 0 - введены ненужные символы
  • EOF - ошибка потока

Вы должны проверить это значение и принять соответствующие меры. Вы можете просто прервать программу, если это не 1, хотя было бы полезно очистить мусор и снова спросить в случае 0.

Переходим к фактической сортировке. Ваш интерфейс странный, поскольку вы передаете N-1 функции, а затем функция получает доступ к 1 элементу за концом массива. Было бы понятнее сделать selection_sort(N, a), а потом внутри функции high = n-1 и for (i = 0; i < n-1; i++) и т.д.

Теперь есть тонкая проблема со строкой:

void selection_sort(int n, int a[n])

Эта строка не соответствует прототипу; вы можете решить свою проблему, заменив строку на:

void selection_sort(int n, int a[])

Первоначальная версия заставляла программу вести себя неожиданно для меня, но только если я вызываю gcc в режиме по умолчанию (т.е. несовместимом со стандартом C). Должно быть какое-то расширение GNU, вызывающее проблемы с int a[n].

В стандартном C исходный код должен работать (и работает, если gcc вызывается в стандартном режиме через -std=c99, что я настоятельно рекомендую делать в любом случае).

person M.M    schedule 16.04.2014
comment
Спасибо, я не мог вспомнить этот код std=c99 после сброса настроек компилятора по умолчанию (думая, что это проблема компилятора), я не совсем закончил свой код, и я ценю другие исправления. Я не подумал о том, чтобы добавить туда проверку, я думаю, я забыл, что я действительно помещал 10 позиций в массив и не добавляя предотвращение сбега.... Я не помню, чтобы у меня были проблемы с сток с использованием этого метода раньше, но в любом случае это хорошая практика, верно? - person John Conner; 17.04.2014
comment
На заметку о void selection_sort(int n, int a[n])... Я думал, что стандарт C99 позволяет вам определять размер массива таким образом, если вы объявили переменную размера перед ее использованием. Я действительно считаю, что это больше для внешнего вида, чем для чего-либо, но в основном используется только для помощи другим, которые просматривают или редактируют код. Я все еще новичок в C, так что поправьте меня, если я ошибаюсь. Спасибо всем за участие, это очень ценно :) - person John Conner; 17.04.2014
comment
Это позволяет это. Код работает в C99, но не работает в режиме GNU, отличном от C99. (Кстати, в данном случае это не VLA, массив просто передается, как и другие массивы). Определение функции должно соответствовать прототипу в любом случае. - person M.M; 17.04.2014
comment
Спасибо, Мэтт и Джонатан, это была моя проблема, в программе не было этой проверки, и она принимала только 10 значений за раз, единственное, что я не подумал проверить XD - person John Conner; 17.04.2014

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

Спасибо, что помогли мне с этим.

    // Chapter 9 Programming Project #1

    #include <stdio.h>
    #include <ctype.h>

    #define N count

    void selection_sort(int n, int a[]);

    int main(void)
    {
        int i, temp, temp2, a[20], count_dgts = 0, count = 0;
        char ch;

        printf("Enter a series of integers\n");
        printf("Enter only one or two digit numbers: ");
        ch = getchar();
        for (i = 0; ch != '\n';) {
            switch (ch) {
                case '0': temp = 0; count_dgts += 1; break;
                case '1': temp = 1; count_dgts += 1; break;
                case '2': temp = 2; count_dgts += 1; break;
                case '3': temp = 3; count_dgts += 1; break;
                case '4': temp = 4; count_dgts += 1; break;
                case '5': temp = 5; count_dgts += 1; break;
                case '6': temp = 6; count_dgts += 1; break;
                case '7': temp = 7; count_dgts += 1; break;
                case '8': temp = 8; count_dgts += 1; break;
                case '9': temp = 9; count_dgts += 1; break;
                default: count_dgts = 0; break;
            }
            ch = getchar();
            if (count_dgts == 2) {
                a[i++] = (temp2 * 10) + temp;
                count += 1;
            }
            if (ch != ' ' && count_dgts == 1) {
                temp2 = temp;
            }
            if ((ch == ' ' && count_dgts == 1) ||
                (ch == '\n' && count_dgts == 1)) {
                a[i++] = temp;
                count += 1;
            }
        }
        selection_sort(N, a);
        // iterate through array
        printf("\nYour numbers in ascending order are: \n");
        for (i = 0; i < N; i++) {
            printf("%d ", a[i]);
        }
        printf("\n");
        return 0;
    }

    void selection_sort(int n, int a[])
    {
        // Search for the highest value
        // Place that value at the end
        // Call the function with the end of the array removed
        // Create a way for it to break the cycle
        int i, temp, high = n - 1;
        for (i = 0; i < n; i++) {
            if (a[i] > a[high]) {
                temp = a[high];
                a[high] = a[i];
                a[i] = temp;
                if (n - 1 > 1)
                    selection_sort(n - 1, a);
            }
        }
    }
person Community    schedule 17.04.2014
comment
И да, я только что понял, что добавление ctypes.h было довольно бессмысленным... Я думал, что буду его использовать, но в итоге он мне не понадобился... Я работал с цифрами, а не с буквами, так что..... - person John Conner; 17.04.2014