Programmazione.it v6.4
Ciao, per farti riconoscere devi fare il login. Non ti sei ancora iscritto? Che aspetti, registrati adesso!
Info Pubblicità Collabora Autori Sottoscrizioni Preferiti Bozze Scheda personale Privacy Archivio Libri Corsi per principianti Forum
Forum :: Programmazione.it :: C :: Controllare lunghezza massima di un input
Scritto da Loris Stefano a.k.a. javoso89 il 13-08-2012 ore 09:29
Intel Parallel Studio XE
Salve.. sono sempre io u.u

Devo inserire dei dati in una struct, ma prima di farlo devo verificare che non siano più lunghi di 15 caratteri.

Ho scritto questo:
  1. #include 
  2. #include 
  3. #include 
  4. #include 
  5. #include 
  6. #include 
  7.  
  8. #define MAX_SIZE 1024
  9. #define SIZE 15
  10.  
  11. typedef struct ElencoTelefonico{
  12. 	char name[SIZE];
  13. 	char surname[SIZE];
  14. 	char numeroTelefono[SIZE];
  15. }ElencoTelefonico;
  16.  
  17. void verificaInput(ElencoTelefonico record, int flag);
  18.  
  19. int main(int argc, char**argv) {
  20.  
  21. 	ElencoTelefonico record;
  22.  
  23. 	verificaInput(record,1);
  24. 	verificaInput(record,2);
  25. 	verificaInput(record,3);
  26.  
  27. 	printf("Nome: %s",record.name);
  28. 	printf("Cognome: %s",record.surname);
  29. 	printf("Numero: %s", record.numeroTelefono);
  30.  
  31. 	return 1;
  32. }
  33.  
  34. void verificaInput(ElencoTelefonico record, int flag) {
  35.  
  36. 	char temp[MAX_SIZE];
  37. 	memset(temp,0,MAX_SIZE);
  38.  
  39. 	int testscanf;
  40.  
  41. 	if(flag == 1) {
  42. 		printf("nInserisci il nome: ");
  43. 	}
  44. 	if(flag == 2) {
  45. 		printf("nInserisci il cognome: ");
  46. 	}
  47. 	if(flag == 3) {
  48. 		printf("nInserisci il numero di telefono: ");
  49. 	}
  50.  
  51. 	do {
  52.  
  53. 		testscanf = scanf("%s", temp);
  54. 		while(testscanf == -1) {
  55. 			if(errno != EINTR) {
  56.                 printf("nErrore scanfn");
  57.                 exit(0);
  58.             }
  59.             else {
  60. 				memset(temp,0,MAX_SIZE);
  61.                 testscanf = scanf("%s", temp);
  62.             }
  63.         }
  64.         if(testscanf == 0 || strlen(temp) > 15){ 
  65.             while(scanf("%*[^n]") == -1){ 
  66.                 if(errno != EINTR){
  67.                     printf("nErrore scanfn");
  68.                     exit(0);
  69.                 }
  70.             }
  71.  
  72.             memset(temp,0,MAX_SIZE);
  73.             printf("nErrore, lunghezza massima pari a 15 caratteri!n");
  74.             if(flag == 1) {
  75. 				printf("nInserisci il nome: ");
  76. 			}
  77. 			if(flag == 2) {
  78. 				printf("nInserisci il cognome: ");
  79. 			}
  80. 			if(flag == 3) {
  81. 				printf("nInserisci il numero di telefono: ");
  82. 			}
  83.         }
  84.  
  85. 	}while(testscanf == 0 || strlen(temp) > 15);
  86.  
  87. 	if(flag == 1) {
  88. 		strcpy(record.name,temp);
  89. 	}
  90. 	if(flag == 2) {
  91. 		strcpy(record.surname,temp);
  92. 	}
  93. 	if(flag == 3) {
  94. 		strcpy(record.numeroTelefono,temp);
  95. 	}
  96.  
  97. 	return;
  98. }

Ma il comportamento non è quello voluto. Basta compilare ed avviare per rendersene facilmente conto :)
Precedente: Presentazione
Successiva: Leggere righe di un file
Intervento di Loris Stefano a.k.a. javoso89 del 13-08-2012 ore 10:51, Fossacesia (CH)
Plebeo
Plebeo
(38 interventi)
Iscritto il 21-04-2011
Ho quasi risolto con quest'altra versione.. solo che le stampe si comportano in modo strano.
  1. #include < unistd.h >
  2. #include < string.h >
  3. #include < stdio.h >
  4. #include < stdlib.h >
  5. #include < errno.h >
  6. #include < fcntl.h >
  7.  
  8. #define SIZE 15
  9.  
  10. typedef struct ElencoTelefonico{
  11. 	char name[SIZE+1];
  12. 	char surname[SIZE+1];
  13. 	char numeroTelefono[SIZE+1];
  14. }ElencoTelefonico;
  15.  
  16. void verificaInput(ElencoTelefonico record);
  17.  
  18. int main(int argc, char**argv) {
  19.  
  20. 	ElencoTelefonico record;
  21.  
  22. 	verificaInput(record);
  23.  
  24. 	printf("Nome: %s",record.name);
  25. 	printf("Cognome: %s",record.surname);
  26. 	printf("Numero: %s",record.numeroTelefono);
  27.  
  28. 	return 1;
  29. }
  30.  
  31. void verificaInput(ElencoTelefonico record) {
  32.  
  33. 	char name_temp[SIZE+1];
  34. 	char surname_temp[SIZE+1];
  35. 	char numero_temp[SIZE+1];
  36.  
  37. 	//int testscanf;
  38.  
  39. 	do {
  40. 		printf("nInserisci il nome: ");
  41. 		scanf("%s", name_temp);
  42. 		printf("nInserisci il cognome: ");
  43. 		scanf("%s",surname_temp);
  44. 		printf("nInserisci il numero di telefono: ");
  45. 		scanf("%s",numero_temp);
  46.  
  47. 		if(strlen(name_temp) > SIZE) {
  48. 			printf("nNome troppo lungo!n");
  49. 		}
  50. 		if(strlen(surname_temp) > SIZE) {
  51. 			printf("nCognome troppo lungo!n");
  52. 		}
  53. 		if(strlen(numero_temp) > SIZE) {
  54. 			printf("nNumero troppo lungo!n");
  55. 		}
  56. 	}while((strlen(name_temp) > SIZE) || (strlen(surname_temp) > SIZE) || (strlen(numero_temp) > SIZE));
  57.  
  58. 	strcpy(record.name,name_temp);
  59. 	strcpy(record.surname,surname_temp);
  60. 	strcpy(record.numeroTelefono,numero_temp);
  61.  
  62. 	return;
  63. }
Intervento di B_gin a.k.a. b_gin del 15-08-2012 ore 13:12, Padova (PD)
Nobile
Nobile

(62 interventi)
Iscritto il 14-11-2010
Concettualmente credo che sia più corretto passare a verificaInput le singole stringhe invece dell'intero ElencoTelefonico, così è anche più facile da implementare.
  1. #include <stdio.h>
  2. #include <string.h>
  3. #define SIZE 15
  4.  
  5. #define TRUE 1
  6. #define FALSE 0
  7.  
  8. typedef struct ElencoTelefonico {
  9. 	char name[SIZE+1];
  10. 	char surname[SIZE+1];
  11. 	char numeroTelefono[SIZE+1];
  12. } ElencoTelefonico;
  13.  
  14. int main()
  15. {
  16. 	ElencoTelefonico record;
  17. 	int inputAccettato = FALSE;
  18. 	do
  19. 	{
  20. 		printf("\nInserisci il nome: ");
  21. 		inputAccettato = verificaInput(record.name);
  22. 	} while (!inputAccettato);
  23. 	inputAccettato = FALSE;
  24. 	do
  25. 	{
  26. 		printf("\nInserisci il cognome: ");
  27. 		inputAccettato = verificaInput(record.surname);
  28. 	} while (!inputAccettato);
  29. 	inputAccettato = FALSE;
  30. 	do
  31. 	{
  32. 		printf("\nInserisci il numero di telefono: ");
  33. 		inputAccettato = verificaInput(record.numeroTelefono);
  34. 	} while (!inputAccettato);
  35.  
  36. 	printf("\nNome: %s", record.name);
  37. 	printf("\nCognome: %s",record.surname);
  38. 	printf("\nNumero: %s",record.numeroTelefono);
  39. }

Per verificaInput ti offro due versioni al prezzo di una teeth.gif

Versione (che secondo me è) più elegante, che legge un carattere alla volta e controlla di non averne letti più di SIZE:
  1. int verificaInput(char * input)
  2. {
  3. 	int i = 0;
  4. 	while (TRUE)
  5. 	{
  6. 		char c = getchar();
  7. 		if (c == '\n')
  8. 		{
  9. 			input[i++] = '\0';
  10. 			return TRUE;
  11. 		}
  12. 		if (i >= SIZE)
  13. 		{
  14. 			printf("\nErrore, lunghezza massima pari a %d caratteri!", SIZE);
  15. 			while (getchar() != '\n');   // consuma i rimanenti caratteri nello stdin ("flush")
  16. 			return FALSE;
  17. 		}
  18. 		input[i++] = c;
  19. 	}
  20. }


Versione più semplice, simile alla tua, che usa il "trucchetto" della stringa temporanea per controllare la lunghezza. La stringa temporanea basta che sia lunga SIZE + 2 caratteri (SIZE + 1 + il carattere terminatore), usare 1 kbyte solo per lei mi sembra un po' uno spreco di spazio :)
  1. int verificaInput(char * input)
  2. {
  3. 	char temp[SIZE+2];
  4. 	scanf("%16s", temp);
  5. 	if(strlen(temp) > SIZE)
  6. 	{
  7. 		printf("\nErrore, lunghezza massima pari a %d caratteri!", SIZE);
  8. 		scanf("%*[^\n]s");  // consuma i rimanenti caratteri nello stdin ("flush")
  9. 		return FALSE;
  10. 	}
  11. 	strcpy(input, temp);
  12. 	return TRUE;
  13. }

Ho usato anche due diverse versioni del "flush", una con scanf e una con getchar, che ovviamente sono equivalenti.
Intervento di B_gin a.k.a. b_gin del 15-08-2012 ore 14:10, Padova (PD)
Nobile
Nobile

(62 interventi)
Iscritto il 14-11-2010
PS: alla riga 4 della seconda versione ho usato la stringa di formato "%16s" con il numero magico 16 (SIZE + 1), per fare prima. È buona regola evitare di usare i numeri magici e quindi sarebbe meglio creare la stringa di formato concatenando "%", SIZE + 1 e "s", in qualche modo, per esempio
  1. char format[5];
  2. sprintf(format, "%%%ds", SIZE + 1);
  3. scanf(format, temp);

ma così ho usato un altro numero magico. D'oh!
Intervento di Loris Stefano a.k.a. javoso89 del 18-08-2012 ore 16:48, Fossacesia (CH)
Plebeo
Plebeo
(38 interventi)
Iscritto il 21-04-2011
b_gin ha scritto:
PS: alla riga 4 della seconda versione ho usato la stringa di formato "%16s" con il numero magico 16 (SIZE + 1), per fare prima. È buona regola evitare di usare i numeri magici e quindi sarebbe meglio creare la stringa di formato concatenando "%", SIZE + 1 e "s", in qualche modo, per esempio
  1. char format[5];
  2. sprintf(format, "%%%ds", SIZE + 1);
  3. scanf(format, temp);

ma così ho usato un altro numero magico. D'oh!

Ahaha ma grazie! Quanta roba! La vedrò tutta, è molto utile. Sinceramente ho risolto il problema che avevo prima di leggere la tua risposta; quando rientro in ubuntu la posto :)
Intervento di Loris Stefano a.k.a. javoso89 del 21-08-2012 ore 16:36, Fossacesia (CH)
Plebeo
Plebeo
(38 interventi)
Iscritto il 21-04-2011
javoso89 ha scritto:
b_gin ha scritto:
PS: alla riga 4 della seconda versione ho usato la stringa di formato "%16s" con il numero magico 16 (SIZE + 1), per fare prima. È buona regola evitare di usare i numeri magici e quindi sarebbe meglio creare la stringa di formato concatenando "%", SIZE + 1 e "s", in qualche modo, per esempio
  1. char format[5];
  2. sprintf(format, "%%%ds", SIZE + 1);
  3. scanf(format, temp);

ma così ho usato un altro numero magico. D'oh!

Ahaha ma grazie! Quanta roba! La vedrò tutta, è molto utile. Sinceramente ho risolto il problema che avevo prima di leggere la tua risposta; quando rientro in ubuntu la posto :)

Allora guarda, usando la prima versione di verificaInput accade questo:

Inserisci il nome:
Inserisci il cognome: bla bla bla...

In sostanza mi salta il primo inserimento, come mai?
Intervento di B_gin a.k.a. b_gin del 21-08-2012 ore 18:06, Padova (PD)
Nobile
Nobile

(62 interventi)
Iscritto il 14-11-2010
Ho provato sia su Windows che su Linux (e su Ideone), a me funziona in tutti i casi. Sei sicuro di aver scritto esattamente solo il codice che ho postato? La seconda versione ti funziona?
Intervento di Loris Stefano a.k.a. javoso89 del 21-08-2012 ore 18:39, Fossacesia (CH)
Plebeo
Plebeo
(38 interventi)
Iscritto il 21-04-2011
b_gin ha scritto:
Ho provato sia su Windows che su Linux (e su Ideone), a me funziona in tutti i casi. Sei sicuro di aver scritto esattamente solo il codice che ho postato? La seconda versione ti funziona?

Questo è il codice:
  1. ElencoTelefonico* record = (ElencoTelefonico*)malloc(sizeof(ElencoTelefonico));
  2.  
  3. 	int inputAccettato = FALSE;
  4.  
  5. 	do {
  6. 		printf("nInserisci il nome: ");
  7. 		inputAccettato = verificaInput(record->name);
  8. 	}while(!inputAccettato);
  9.  
  10. 	inputAccettato = FALSE;
  11.  
  12. 	do {
  13. 		printf("nInserisci il cognome: ");
  14. 		inputAccettato = verificaInput(record->surname);
  15. 	}while(!inputAccettato);
  16.  
  17. 	inputAccettato = FALSE;
  18.  
  19. 	do {
  20. 		printf("nInserisci il numero di telefono: ");
  21. 		inputAccettato = verificaInput(record->numeroTelefono);
  22. 	}while(!inputAccettato);

verificaInput
  1. int verificaInput(char* input) {
  2.  
  3. 	int i = 0;
  4. 	while(TRUE) {
  5. 		char c = getchar();
  6. 		if(c == 'n') {
  7. 			input[i++] = '';
  8. 			return TRUE;
  9. 		}
  10. 		if(i >= SIZE) {
  11. 			printf("nErrore, lunghezza massima pari a %d caratteri", SIZE);
  12. 			while(getchar() != 'n'); //consuma i rimanenti caratteri nello stdin ("flush")
  13. 			return FALSE;
  14. 		}
  15. 		input[i++] = c;
  16. 	}
  17. }

Ho copiato ed incollato. Come vedi ho utilizzato malloc per vedere se il problema veniva risolto. Provo la seconda versione..
Intervento di Loris Stefano a.k.a. javoso89 del 21-08-2012 ore 18:45, Fossacesia (CH)
Plebeo
Plebeo
(38 interventi)
Iscritto il 21-04-2011
javoso89 ha scritto:
b_gin ha scritto:
Ho provato sia su Windows che su Linux (e su Ideone), a me funziona in tutti i casi. Sei sicuro di aver scritto esattamente solo il codice che ho postato? La seconda versione ti funziona?

Questo è il codice:
  1. ElencoTelefonico* record = (ElencoTelefonico*)malloc(sizeof(ElencoTelefonico));
  2.  
  3. 	int inputAccettato = FALSE;
  4.  
  5. 	do {
  6. 		printf("nInserisci il nome: ");
  7. 		inputAccettato = verificaInput(record->name);
  8. 	}while(!inputAccettato);
  9.  
  10. 	inputAccettato = FALSE;
  11.  
  12. 	do {
  13. 		printf("nInserisci il cognome: ");
  14. 		inputAccettato = verificaInput(record->surname);
  15. 	}while(!inputAccettato);
  16.  
  17. 	inputAccettato = FALSE;
  18.  
  19. 	do {
  20. 		printf("nInserisci il numero di telefono: ");
  21. 		inputAccettato = verificaInput(record->numeroTelefono);
  22. 	}while(!inputAccettato);

verificaInput
  1. int verificaInput(char* input) {
  2.  
  3. 	int i = 0;
  4. 	while(TRUE) {
  5. 		char c = getchar();
  6. 		if(c == 'n') {
  7. 			input[i++] = '&#65533;';
  8. 			return TRUE;
  9. 		}
  10. 		if(i >= SIZE) {
  11. 			printf("nErrore, lunghezza massima pari a %d caratteri", SIZE);
  12. 			while(getchar() != 'n'); //consuma i rimanenti caratteri nello stdin ("flush")
  13. 			return FALSE;
  14. 		}
  15. 		input[i++] = c;
  16. 	}
  17. }

Ho copiato ed incollato. Come vedi ho utilizzato malloc per vedere se il problema veniva risolto. Provo la seconda versione..

Edit: la seconda versione funziona
Intervento di B_gin a.k.a. b_gin del 21-08-2012 ore 20:03, Padova (PD)
Nobile
Nobile

(62 interventi)
Iscritto il 14-11-2010
Noto che hai cambiato posto alle graffe, magari è per quello teeth.gif
Seriamente, se usi gcc e esegui il programma dalla linea di comando (cioè non in un IDE, anche se non dovrebbe cambiare niente), e non ti funziona, non so cosa dirti, usa la tua versione o la mia seconda e dimenticati della prima sweatdrop.gif
Copyright Programmazione.it™ 1999-2013. Alcuni diritti riservati. Testata giornalistica iscritta col n. 569 presso il Tribunale di Milano in data 14/10/2002. Pagina generata in 0.349 secondi.