#arrays #c #bubble-sort
#массивы #c #пузырьковая сортировка
Вопрос:
Я новичок в C. Я сделал свою собственную сортировку, чтобы отсортировать кучу строк в алфавитном порядке, и это то, что у меня есть, но strcmp, похоже, не работает? Программа просто вылетает.
int main(void) {
char **a = malloc(sizeof(char*));
a[0] = "Cam";
a[1] = "Bam";
a[3] = "Dam";
a[4] = "Aam";
for (int i = 0; a[i] != ''; i ) {
for (int j = i 1; a[j] != ''; j )
if (strcmp(a[i], a[j]) > 0) {
char* temp = a[i];
a[i] = a[j];
a[j] = temp;
}
printf("%s ", a[i]);
}
return 0;
}
// output should be Aam Baam Caam Daam
Комментарии:
1. C имеет
qsort
, который, даже если вы не можете его использовать, служит примером того, как вы должны организовать свой код: создайте функцию сортировки, а не просто делайте всеmain()
.2. Вы выделили место только для 1 указателя, но полагаетесь на то, что их 5 (один из которых,
a[2]
, не используется). Поэтому, конечно, он выходит из строя.3. Подсказка:
a[i]
это achar*
и не сопоставимо с нулевым байтом.4. Вместо того, чтобы перебирать
malloc
, почему бы не простоchar* a[] = { "X", "Y", ... }
? Это намного сложнее исправить, потому что вы не пропустите записи, как вы это сделали, или выделите неправильный размер, что является распространенной ошибкой. Одним из распространенных соглашений C является объявление его так{ "X", ..., NULL }
, чтобы вы знали, когда прекратить итерацию, и вам не нужно вычислять размер.5. Правильный способ избежать перехода к концу массива — это иметь переменную
length
orsize
и тестироватьi < size
.
Ответ №1:
Три проблемы:
-
Вы выделили место только для массива длиной 1, но использовали 5 слотов. Чтобы выделить массив размером 5, используйте
char **a = malloc(5 * sizeof(char *));
-
Вы никогда не инициализировались
a[2]
. -
a[i] != ''
не имеет особого смысла, поскольку вы сравниваете указатель с символом.
Комментарии:
1. На самом деле код требует дополнительного
NULL
указателя в конце (как только тест исправлен для использованияNULL
вместо''
). Таким образом, даже приmalloc
фиксированном вызове он все равно будет удаляться с конца массива (если только тест не будет изменен на использование длины массива).
Ответ №2:
В этом коде много путаницы в том, как работает C, и много простых ошибок, которых можно избежать, если уделять самое пристальное внимание мельчайшим деталям. В программировании один символ может иметь огромное значение, крошечная ошибка может кардинально изменить поведение вашего кода: от рабочего до сломанного или от безошибочного до полностью уничтоженного.
Вот более идиоматическая версия вашего кода на C:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void) {
// Create a local variable to represent the strings to be sorted
char *a[] = {
"E",
"B",
"C",
"A",
"D",
NULL // Use NULL as a terminator
};
// Iterate over each entry and stop at the NULL terminator...
for (int i = 0; a[i]; i ) {
for (int j = i 1; a[j]; j ) {
if (strcmp(a[i], a[j]) > 0) {
char* temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
// Once the sort has wrapped, print the sorted array
for (int i = 0; a[i]; i ) {
// This was erroneously inside the sorting routine before
printf("%s ", a[i]);
}
printf("n");
return 0;
}
Обратите внимание, что при компиляции может быть обнаружено много простых ошибок -Wall
, или эквивалент, когда компилятор предупреждает ( -W
) обо всем ( all
), что он считает неправильным.
В clang
вы получите предупреждения типа:
sort.c:10:28: предупреждение: сравнение указателя с нулевой символьной константой; вы имели в виду сравнение с NULL? [-Wpointer-compare]
Это помогает выявлять ошибки на ранней стадии. Помните, что в C «compiles» и «correct» часто отличаются друг от друга. Компилятор мало что проверяет в C, кроме синтаксиса. Остальное на вас, и как программист на C, вы несете большую ответственность.
Отдельные ошибки, переход от конца массива и невозможность выделения или освобождения памяти — это лишь некоторые из многих вещей, которые вам нужно иметь в виду при написании C. Этот язык разработан для быстрого, а не безопасного использования. Это похоже на гоночный автомобиль в том смысле, что если вы не знаете, как им управлять, вы сразу же развернетесь и врежетесь в стену.
Не торопитесь, найдите хорошие ссылки и учитесь на хороших примерах. Вы можете довольно быстро освоиться с C, как только поймете, что он будет и абсолютно не будет делать для вас.
Ответ №3:
Вы выделили достаточный размер только для одного указателя, и все же вы выделяете пространство на пять указателей.
Попробуйте это:
char **a = malloc(sizeof(char*)*5);