Linguaggio C, warning utilizzando %s e struct di array

di Anonimizzato14377 il
17 risposte

#include <stdio.h>
#include <string.h>

#define M_MAX 5

struct studente
{
  	int matricola;
	char *nome;
	char *cognome;
};

int main()
{
	struct studente M[DIM_M];
	int n, i;
	
	printf("\n\tRegistro attivita' studenti \n\tInserimento dati matricole \n\tNumero studenti? ");
	scanf("%d", &n);	
	
	//Inserimento dati all'interno della struttura
	for(i = 0; i < n; i++)
	{
		printf("\n\n\tInserimento %d\n", i);
		printf("\tMatricola: "); scanf("%d\n", &M[i].matricola);
		printf("\tNome: "); scanf("%s \n", &M[i].nome);
		printf("\tCognome: "); scanf("%s \n", &M[i].cognome);
	}

}
Compilando mi dice:

main.c:18:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]
printf("\tNome: "); scanf("%s \n", &M.nome);
^
main.c:19:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]
printf("\tCognome: "); scanf("%s \n", &M.cognome);
^


Perché?

17 Risposte

  • M.nome è già di suo un char *
    di conseguenza &M.nome è un char **
    Comunque ti sconsiglio di utilizzare scanf(), molto meglio fgets() di cui trovi innumerevoli esempi e discussioni in questo stesso forum.
    p.s. dai una dimensione alle stringhe, non semplicemente char *, altrimenti da qualche parte le devi allocare!!!
  • struct studente
    {
    	int matricola;
    	char nome[40];
    	char cognome[50];
    };
    
    Così mi dice:

    main.c:18:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[40]’ [-Wformat=]
    printf("\tNome: "); scanf("%s \n", &M.nome);
    ^
    main.c:19:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[50]’ [-Wformat=]
    printf("\tCognome: "); scanf("%s \n", &M.cognome);
    ^

    E, sempre con questa struct, con printf("\tNome: "); fgets(M.nome); mi dice:

    main.c:18:3: error: too few arguments to function ‘fgets’
    printf("\tNome: "); fgets(M.nome);//scanf("%s \n", &M.nome);
    ^
    In file included from definizioni.h:17:0,
    from main.c:1:
    /usr/include/stdio.h:622:14: note: declared here
    extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
    ^
    make: *** [exe] Errore 1


    Come posso fare?
  • Come posso fare?
    Per quanto riguarda la fgets() cerca con google come richiamare questa funzione.
  • Ho letto tutto attentamente, e ho provato anche a fare quello che mi hai detto tu. Mi da sempre lo stesso problema!
  • Ho provato a fare come scritto su questo sito:

    http://www.daniweb.com/software-development/c/threads/112772/using-fgets-properly

    Ovvero:
    fflush(stdin);
    fgets(M[i].nome, sizeof M[i].nome, stdin);
    Compilando non mi da errori, però quando lo eseguo non me lo fa inserire. Si blocca subito dopo l'inserimento della matricola.

    Se lo volessi fare con scanf, altrimenti, come dovrei fare?
  • Devi eliminare tutti i \n dalle scanf
  • Oh, bene! Ora me li fa inserire. Grazie!! Però mi da sempre questo warning:

    main.c: In function ‘main’:
    main.c:22:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]
    printf("\tNome: "); scanf("%s", &M.nome);
    ^


    Non c'è un modo per toglierlo?
  • Più che cercare un modo per "toglierlo" dovresti capirlo ...

    M.nome è già un puntatore a carattere (un char *) che è quello che si aspetta la scanf.
    Se scrivi &M.nome allora diventa un puntatore a puntatore (un char **) e NON va bene.

    Questo significa che, dopo tantissimi post e tanto studio del C, ancora non hai capito molto dei puntatori ...
  • Evidentemente no, ma è per questo che faccio gli esercizi
  • La mia non era una critica "fine a sé stessa" ... non mi permetterei ... era per evidenziare il fatto che devi fare un numero maggiore di esercizi sui puntatori.

    Non devi fare "grandi esercizi" o "esercizi molto complessi" ...

    Devi esercitarti sui puntatori con esempi di poche linee, tanti esempi diversi da 3 o 4 linee che trattino tutti gli aspetti principali dei puntatori.

    Ad esempio, il fatto che tu abbia inizialmente inserito

    char *nome;
    char *cognome;

    nella struttura e li abbia usati direttamente - senza allocare lo spazio - vuol dire che devi soffermarti ancora sul significato di puntatore, insomma le basi.
  • Nemmeno io volevo criticare, tranquillo. Va bene seguirò il tuo consiglio, ti ringrazio.

    Solo ti sarei grato se mi dicessi il motivo dell'ultimo warning.

  • Solo ti sarei grato se mi dicessi il motivo dell'ultimo warning.
    Ti è già stato spiegato, sia da me che da oregon.
    M.nome è una stringa C, una puntatore a char ovvero char *.
    Il compilatore ti dice che "format ‘%s’ expects argument of type ‘char *", ovvero che se usi %s devi successivamente specificare un char *, una stringa C, nel tuo caso M.nome.
    Perchè hai aggiunto &? Se passi &M.nome stai passando un char **.
    Prova a rifletterci sopra; se invece ti interessa solo la soluzione semplicemente togli &.
  • davide.fruci ha scritto:


    Solo ti sarei grato se mi dicessi il motivo dell'ultimo warning.
    Ma non te l'ho già detto?
Devi accedere o registrarti per scrivere nel forum
17 risposte