Много проблем в этом коде.
Прежде всего, вы путаете количество аргументов в строке ввода для количества записей в каталоге. В одном контексте вы используете n
для подсчета количества аргументов, но в другом вы используете его для индексации массива catalog
.
Вы создаете головные боли при управлении памятью там, где вам это не нужно. Переменная args
совершенно не нужна, и вы все равно выделяете для нее память неправильно. Вы в основном говорите: «выделите указатель на символ для каждого символа в command
, что, вероятно, не то, что вы хотите.
Потерять args
полностью; тебе это не нужно.
Я понимаю, что это не вся ваша программа, но не ясно, почему вы создаете catalog
как массив указателей на struct catalog
, а не просто обычный массив.
Я не уверен, что вы думаете, что делаете на линии
*catalog[n]->short_name=*args[1];
Тип выражения catalog[n]->short_name
равен char[50]
. В этом контексте тип массива неявно преобразуется («распадается») в тип указателя, char *
. Таким образом, тип целого выражения *catalog[n]->short_name
равен * (char *)
или просто char
, который является целым типом. По сути, вы пытаетесь присвоить значение первого символа args[1]
первому символу catalog[n]->short_name
.
Всё равно это не имеет значения, потому что catalog[n]
не был инициализирован, чтобы указывать куда-либо значимое; segfault происходит от попытки доступа к элементу short_name
, который неявно разыменовывает catalog[n]
, который указывает куда-то случайно.
Далее, вы не можете использовать оператор присваивания =
для назначения строковых данных; Вы должны использовать strcpy()
или strncpy()
, чтобы сделать это.
Наконец, НИКОГДА НИКОГДА НЕ НИКОГДА НИКОГДА НИКОГДА использовать gets()
. Это будет вводить точку отказа в вашем коде. Он официально объявлен устаревшим в C99 и больше не должен использоваться. Используйте fgets()
вместо:
if (fgets(command, sizeof command, stdin) != NULL)
{
char *newline = strchr(command, '\n');
if (newline != NULL)
*newline = 0;
}
Вот как вам нужно разобрать командную строку и присвоить поля членам структуры:
curToken = strtok(command, '\t');
if (curToken)
strncpy(catalog[n]->short_name, curToken, sizeof catalog[n]->short_name);
curToken = strtok(NULL, '\t');
if (curToken)
strncpy(catalog[n]->surname, curToken, sizeof catalog[n]->surname);
curToken = strtok(NULL, '\t');
if (curToken)
{
char *chk;
catalog[n]->amount = (int) strtol(curToken, &chk, 10);
if (!isspace(*chk) && *chk != 0)
fprintf(stderr,
"Warning: expected integer value for amount, received %s instead\n",
curToken);
}
curToken = strtok(NULL, '\t');
if (curToken)
strncpy(catalog[n]->description, curToken, sizeof catalog[n]->description);
В этом коде предполагается, что catalog
все еще объявляется как массив указателей и , что каждый элемент был инициализирован, чтобы указывать куда-то значимое. В противном случае измените объявление с struct catalog {...} *catalog[MAX];
на struct catalog {...} catalog[MAX]
и измените ->
на .
.