2015-04-18 5 views
-2

im реализует программу, которая считывает идентификатор и имена учеников из stdin или файла и делает их упорядоченными по имени и упорядочивается по числу. Самое смешное, что я не могу понять, почему, но scanf не работает. Вот мой код, используя зсапЕ:scanf не работает

int n=0; 
while(n<SIZE){ 
    scanf("%d %s\n",&std_array[n].id, std_array[n].name); 
    n++; 
} 
for(int i=0; i<SIZE; i++) 
    printf("%d %s\n",std_array[i].id,std_array[i].name); 

и вот моя структура:

struct Student { 
char *name; 
int id;}; 

, когда я прочитал из файла и распечатать их из положить является:

> 12586546 (null) 0 (null) 0 (null) 0 (null) 0 (null) 0 (null) 0 (null) 
> 0 (null) 0 (null) 0 (null) 

хотя файл имеют некоторые номера и имена, такие как 21456764 john 45797654 fred и т. д., его не читают успешно.

Примечание: я знаю, как фиксируют структуру нравится вам, ребята, предложенные, но я должен узнать, как сделать это с указателем полукокса ...

+2

Это действительно работает – qrdl

+2

Вы всегда должны проверять количество элементов результата 'scanf' –

ответ

2

При этом:

struct Student { 
char *name; // This does not allocate memory 
int id;}; 

Здесь, имя - указатель, без выделенной памяти, ведет себя как неинициализированный литерал строка.

Попытка изменить его создает undefined поведение.

Заменить:

struct Student { 
char name[50]; 
int id;}; 

или

struct Student { 
char name[] = "Initial value gives maximum length. Do not write more!"; 
int id;}; 
+0

ok, я вижу разницу, но если я использую malloc, это тоже решит проблему? –

+1

@ yağızözbekevren Создавая изменяемую строку, вам нужно указать ограничение, указав размер или инициализируя его. – nestedloop

+0

'имя в основном неинициализированная буквальная строка.' ... это? ИМХО, это указатель, не так ли? –

-1

Это исправленный код

struct Student 
{ 
char name[20]; 
int id; 
}; 
struct Student std_array[SIZE]; 
int n=0; 
while(n<SIZE) 
{ 
    scanf("%d %s", &std_array[n].id, std_array[n].name); 
    n++; 
} 
n=0; 
while(n<SIZE) 
{ 
    printf("%d %s\n", std_array[n].id, std_array[n].name); 
    n++; 
} 

Надеется, что это помогает ...

+0

Уху, я понимаю, но это была моя домашняя работа. Лектор сказал, чтобы сделать эту структуру с «char * name» и «int id». Я должен научиться делать это так ... –

+0

Вам все равно нужно проверить возвращаемое значение 'scanf', чтобы оно было правильным * – chqrlie

2

Это выделяет память на указатель по мере необходимости. Промежуточная переменная используется для хранения строки, тогда в структуре выделяется только достаточное количество памяти плюс 1 для завершающего «\ 0».

int n=0; 
char name[100];//longest possible name 
while(n<SIZE && (scanf("%d%99s",&std_array[n].id, name) == 2)) {// successfully scanned two items 
    std_array[n].name = malloc (strlen (name) + 1)); 
    if (std_array[n].name == NULL) { 
     printf ("malloc failed\n"); 
     // break or return or exit(1) as appropriate 
    } 
    strcpy (std_array[n].name, name); 
    n++; 
} 
for(int i = 0; i < n; i++) 
    printf("%d %s\n",std_array[i].id,std_array[i].name); 

В конце концов, вы хотите, чтобы освободить память

for (i = 0; i < n; i++) { 
    free (std_array[i].name); 
} 
+0

, что помогло бы. попробуй сейчас. –

+1

1) Предложите ''% d% 99s "' вместо ''% d% s \ n "': введите значение до 99 и снимите '' \ n'' 2) Используйте 'for (int i = 0; i < n; i ++) '(' n', а не 'SIZE') – chux

1

пункт 1

Выделяют память name перед его использованием. В противном случае, если используется неинициализированный, он не указывает на действительный памяти для чтения или записи. Вы можете использовать malloc() для выделения памяти. Кроме того, как только вы закончите, не забудьте сделать free(), как только вы закончите использовать память.

Пункт 2

Удалить \n из scanf().

-1

как пользователь3121023 сказал мне, это сработало.фиксированный код выглядит следующим образом:

struct Student { 
char *name; 
int id; 
}; 

struct Student std_array[SIZE]; 
int cmpfunc (const void * a, const void * b); 
struct Student *order_by_number(struct Student *array); 

int main(int argc, char **argv){ 

int n=0; 
char name[100]; 
while(n<SIZE){ 
    scanf("%d %s\n",&std_array[n].id, name); 
    std_array[n].name = malloc(strlen(name)+1); 
    strcpy(std_array[n].name ,name); 
    n++; 
} 
for(int i=0; i<SIZE; i++) 
    printf("%d %s\n",std_array[i].id,std_array[i].name); 

order_by_number(std_array); 

for(int i=0; i<SIZE; i++) 
    printf("%d %s\n",std_array[i].id,std_array[i].name); 
} 

im done, ty ребята, помогающие мне. CASE ЗАКРЫТО :)

+2

' scanf ("% d% s \ n" 'является слабым. 1) возвращаемое значение не проверено. Отметьте «2». 2) размер строки не ограничен ''% 99s "' лучше, чем ''% s "' 3) '' '' не требуется в ''% d% s \ n "'. 4) '' \ n "' in '"% d% s \ n "', безусловно, является проблемой с консольным вводом-выводом, поскольку он обязывает 'scanf()' не возвращаться, пока не будет обнаружено дополнительное небелое пространство или EOF. Лучше всего отказаться от него. Он не просто сканирует 1 '' \ n''. – chux