names - это массив указателей на char, поэтому в
names = (char*)malloc(amount * sizeof(char));
вы выделяете недостаточно, и позже поведение будет неопределенным, когда вы назначит его из него
do (приведение не имеет смысла)
names = malloc(amount * sizeof(char*));
Выполнение
(*names)[i] = (char*)realloc((*names)[i], strlen(names[i]) * sizeof(char));
недопустимо, поскольку (*names)[i]
является символом, не забудьте также место для нулевого символа, заканчивающего строку, поэтому вы хотите:
names[i] = realloc(names[i], strlen(names[i]) + 1);
обратите внимание, что по определению sizeof(char)
равно 1
Без проверки результата из malloc
и realloc
вы предполагаете / надеетесь, что памяти достаточно, но это может быть ложным, и в этом случае эти функции возвращают NULL, более безопасно проверить этот случай. Это означает, что realloc
для первого сохранения во вспомогательном char*
, чтобы не потерять текущее значение names[i]
, вы можете продолжать использовать, если realloc
возвращает NULL
To
scanf("%d", &amount);
опасно, когда ввод недействителен, вы этого не знаете, и сумма не инициализируется с неопределенным поведением при его использовании, например,
if (scanf("%d", &amount) != 1)
{
puts("invalid value");
return -1;
}
Учитывая, как вы используете names[i]
, когда вы
names[i] = (char*)malloc((MAX_CHARS + 1) * sizeof(char));
выделяете 1 байт слишком много, вы можете сделать
names[i] = malloc(MAX_CHARS);
Предупреждение выполняя:
fgets(names[i], MAX_CHARS - 1, stdin);
вероятный символ новой строки, заканчивающий ввод, сохраняется в names[i]
, возможно, вам нужно удалить его. В этом случае вам придется адаптироваться, когда вы печатаете имена, чтобы ввести разделитель между именами, пробелом или новой строкой.
Другой способ чтения, но без перевода новой строки:
scanf(" 49%[^\n]", names[i]);
49 позволяет ограничить количество символов, записанных в массиве (я удалил 1, чтобы освободить место для нулевого символа), а пробелы перед позволяют пропустить пробелы в начале ввода (здесь пробелы означают '', но также и табуляцию, перевод строки и c). Используя этот способ, имя может содержать пробелы, что не имеет место в формате "%49s"
.
В любом случае, что бы вы ни использовали, вам нужно проверить, что ввод был выполнен, иначе вы не установите массив и когда вы будет использовать его позже, поведение будет неопределенным.
Когда вы сортируете свой массив, вы делаете:
strcpy(temp, names[j]);
strcpy(names[j], names[i]);
strcpy(names[i], temp);
, но вам не нужно копировать глубоко, просто поменяйте указатели так:
char * aux = names[j];
names[j] = names[i];
names[i] = aux;
В конце вы хотите освободить ресурсы, но вы делаете только free(names);
, поэтому вы не освобождаете другие массивы