Зачем беспокоиться о сложных форматных строках, если вам это не нужно? Используйте fgets
.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void err(const char * msg) {
fprintf(stderr, msg);
exit(1);
}
int main()
{
int x,i;
char ch[50];
printf("How many names you want to sort:\n");
if(!fgets(ch, 50, stdin)) err("Error reading line");
if(sscanf(ch, "%d",&x) != 1) err("Could not read integer");
// Better than using VLA
char **names = malloc(x*sizeof(*names));
if(!names) err("Error allocating names");
printf("Enter the names:\n");
for(i=0;i<x;i++) {
if(!fgets(ch, 50, stdin)) err("Error reading line");
ch[strcspn(ch, "\n")] = 0; // Remove newline
if(!(names[i] = strdup(ch))) err("Error duplicating string");
}
for(int i=0; i<x; i++)
printf("name %d: %s\n", i, names[i]);
}
Всякий раз, когда функция имеет возвращаемое значение, которое может указывать на ошибку, вы должны ВСЕГДА проверять ее, и здесь это относится к malloc
, fgets
, strdup
и sscanf
и. Прочтите документацию, чтобы узнать, что она на самом деле возвращает, и узнать, как проверять ошибки. sscanf
возвращает количество успешных назначений, а остальные три возвращают указатель, который при ошибке равен NULL.
Вы написали в комментариях, что вы учитесь из книги «Позвольте нам C». Лучше всего подойдет заголовок «Как не кодировать С». Я быстро взглянул на это, и это действительно очень плохо. Помимо преподавания очень устаревшего языка С, он также учит очень вредным привычкам в целом. На самом деле, большинство вопросов о C можно отнести к этой книге, или, по крайней мере, могли бы иметь. Два основных примера - это то, что он последовательно избегает очень важных вещей, таких как функции проверки ошибок, такие как scanf
и malloc
. Я не читал каждую строку, но думаю, что в ней даже не упоминается, как проверять ошибки scanf
даже один раз. Он также использует функцию gets
, которая не только устарела, но и полностью удалена из новых стандартов C, поскольку она очень опасна.