Что не так с кодом?Что я делаю не так?
gets(s->name);
пытается прочитать пользовательский ввод в s->name
.s->name
- это char *
, который еще не был назначен.gets()
пытается сохранить данные, кто-где-знает?Результат: неопределенное поведение (UB).
Альтернативы?
Считывание в буфер и выделение памяти для копии.
Подсказка: как вы можете, избегайте scanf(), gets()
для пользовательского ввода и используйте fgets()
. C - scanf () vs gets () vs fgets () .
Некоторый код, чтобы дать идею.
#define NAME_N 100
// return 1 on success
// return EOF on end-of-file
// return 0 other errors
int getS(Student *s) {
*s = (Student) {NULL, NULL, {0}}; // pre-fill with default values.
char buffer[NAME_N];
printf("Enter name\n");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
return EOF;
}
trim(buffer);
if (!validate_name(buffer)) {
return 0;
}
s->name = strdup(buffer);
printf("Enter last name\n");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
return EOF;
}
trim(buffer);
if (!validate_name(buffer)) {
return 0;
}
s->lastname = strdup(buffer);
printf("Enter marks\n");
for (int i = 0; i < 5; i++) {
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
return EOF;
}
if (sscanf(buffer, "%d", &s->marks[i]) != 1) {
return 0;
}
}
return 1;
}
trim()
- ваша функция для обрезки начальных / конечных / чрезмерных пробелов.См. Также Как стандартным способом обрезать начальные / конечные пробелы? .
strdup()
не является стандартом C, но широко распространенной функцией дублирования строк, которая выделяет память и копии. Пример кода
validate_name()
- это код заполнителя для обеспечения некоторого здравого смысла в имени.Будьте щедры в том, что приемлемо.Обычно допустимые символы в имени включают [AZ, az, '-', '' ',' ','. '] И многие другие: Каковы все допустимые символы для имен людей? .
Пример:
// Fail a zero length name or one with controls characters in it.
bool validate_name(const char *name) {
if (*name == '\0') return false;
while (*name) {
if (iscntrl((unsigned char) *name)) return false;
name++;
}
return true;
}