Linguaggio C
Salve a tutti sono nuovo del forum e avrei in problema in C sto facendo un esercizio sulle liste concatenate e sono incappato in un problema
ho dei problemi in questa parte
purtroppo quando provo ad usare degli scanf nella parte dove chiedo di inserirlo in testa o in coda viene saltato tutto quello che c'è sotto ho provato a usare getch() o anche getchar() ma niente, come potrei fare per risolvere il problema? Grazie.
#include <stdio.h> #include <stdlib.h> typedef struct node* link; struct node { int key; char* item; link next; }; link insert_end(link head, link n) { if(head == NULL) return n; link current = head; while(current->next != NULL) current = current->next; current->next = n; return head; } link insert_head(link head, link n) { if(head == NULL) return n; n->next = head; return n; } void printlist(link head) { link current = head; while(current != NULL) { printf("Chiave elemento %d: %s\n", current->key, current->item); current = current->next; } } int main() { link head = NULL; char scelta; char decisione; while(scelta != 27) { printf("Inserire in quale modalita' accedere:\n i = inserisci elemento\n s = stampa\n c = cerca\n e = elimina\n esc = termina\n"); scanf("%c", &scelta); if(scelta == 'i') { link n = malloc(sizeof *n); n->next = NULL; printf("inserisci codice dell' elemento\n"); scanf("%d", &n->key); printf("Inserisci il nome dell'elemento\n"); scanf("%s", n->item); printf("Inserisci dove vuoi mettere l'elemento t = TESTA, c = CODA\n"); scelta = getch(); if(scelta == 'c'){head = insert_end(head, n); printf("elemento aggiunto\n");} else if(scelta == 't'){head = insert_head(head, n); printf("Elemento aggiunto\n");} } else if(scelta == 's')printlist(head); /*else if(scelta == 'c')find_elem(); else if(scelta == 'e')del_elem();*/ } return 0; }
ho dei problemi in questa parte
printf("Inserire in quale modalita' accedere:\n i = inserisci elemento\n s = stampa\n c = cerca\n e = elimina\n esc = termina\n"); scanf("%c", &scelta); if(scelta == 'i') { link n = malloc(sizeof *n); n->next = NULL; printf("inserisci codice dell' elemento\n"); scanf("%d", &n->key); printf("Inserisci il nome dell'elemento\n"); scanf("%s", n->item); printf("Inserisci dove vuoi mettere l'elemento t = TESTA, c = CODA\n"); scelta = getch();
purtroppo quando provo ad usare degli scanf nella parte dove chiedo di inserirlo in testa o in coda viene saltato tutto quello che c'è sotto ho provato a usare getch() o anche getchar() ma niente, come potrei fare per risolvere il problema? Grazie.
Risposte
Il problema credo sia stato discusso più volte nel forum. Non ha nulla a che fare con le liste ovviamente, piuttosto con l'uso di scanf per leggere un singolo carattere. Al contrario di altri formati, %c non elimina gli spazi e i caratteri di a capo prima del carattere letto e quindi con ogni probabilità va a leggere il carattere di a capo della riga precedente. Una possibile soluzione è usare:
Ma usare qualcosa di diverso da scanf è normalmente preferibile.
scanf(" %c", &scelta);
Ma usare qualcosa di diverso da scanf è normalmente preferibile.
grazie mille la situazione è migliorata, ho provato ad usare getch() e getchar() ma mi dava problemi di crash e a dire il vero ora che ho applicato la tua soluzione mi dà sempre problemi di crash quando ripeto il ciclo while una seconda volta, cioè quando vado a re-inserire "i" crasha.
Non è un errore ma noto leggendo che
Non sono sicuro che
link insert_head(link head, link n) { if(head == NULL) return n; n->next = head; return n; }contiene codice inutile. Non hai bisogno di fare un test che head sia uguale NULL, al limite assegni NULL a n->next.
Non sono sicuro che
sizeof *nfaccia quello che vuoi. Immagino tu voglia fare
sizeof(struct node)quindi è meglio se usi questa notazione oppure usa un typedef su node.
per l'head == NULL hai ragione è ridondante, però sizeof * n non mi dà problemi e va bene, la usano i miei professori regolarmente, in effetti anche io inizialmente ero rimasto perplesso da quella scrittura ma mi hanno assicurato che è una scrittura valida, comunque grazie mille a tutti ho risolto anche col problema di crash.
Solo per curiosità, che problema era?
Mi ero dimenticato di allocare la stringa dinamica char* item

Sei sicuro che valga la pena usare una stringa dinamica? Insomma, più o meno dovresti sapere la dimensione del codice prodotto, quindi tanto vale usare fgets e definire item come una stringa di dimensione fissa. Inoltre penso che, in una ambiente meno scolastico, le performance ne gioverebbero (ogni volta che hai un puntatore hai un cache missing assicurato). Senza considerare che fgets è più sicuro e performante di scanf se usato su stringhe.
Penso si possa fare, ma quindi se usassi la scrittura scanf("%30s", item) sarebbe meno performante rispetto ad una fgets?
In via del tutto teorica si perché scanf deve prima di tutto interpretare la stringa e quindi leggere. Mentre fgets sa già cosa deve andare a cercare. Dopo di che in fase di compilazione è possibile la differenza venga ridotta.
Non lo sapevo grazie mille ancora.
In pratica la differenza principale tra usare fgets e qualcosa come scanf("%30s", stringa) risiede comunque nella diversa gestione degli spazi. fgets legge una riga intera, scanf ignora gli spazi prima della stringa e la termina al primo carattere che non sia uno spazio.
Sì in effetti pensavo che la differenza fosse solo quella, non pensavo ci fosse anche una differenza dal punto di vista delle prestazioni