简体   繁体   中英

Why fgets() works wrong?

Here's my code

if(passwordCorretta(ds_sock)){
   printf("CLIENT: password aggiungi corretta\n");

   do{
      printf("Cognome >> ");
      fgets(cognome,sizeof(cognome),stdin);
      //scanf("%s", cognome);
      printf("Nome >> ");
      fgets(nome,sizeof(nome),stdin);
      //scanf("%s", nome);
      printf("Telefono >> ");
      fgets(telefono,sizeof(telefono),stdin);
      //scanf("%s", telefono);

in output print first the two printf,skipping first fgets(), why is that?

here's my output

CLIENT: password aggiungi corretta
Cognome >> Nome >> **my input
Telefono >> **my input

any ideas why? thanks

Here's my entire function

void main(){
int ds_sock, length, res;
struct sockaddr_in client;
struct hostent *hp;
char oper[2];

int risPwd;
int op;

char cognome[30];
char nome[20];
char telefono[12];

char continua[3];
char ris[2];
int trovato;
int aggiunto;

ds_sock = socket(AF_INET, SOCK_STREAM, 0);

client.sin_family = AF_INET;
client.sin_port = 1999;

hp = gethostbyname("localhost");  //indirizzo del server
memcpy(&client.sin_addr, hp->h_addr, 4);

res = connect(ds_sock, &client, sizeof(client));
if(res==-1) {
    perror("Errore nella connessione");
}

signal(SIGPIPE, gest_broken_pipe);
signal(SIGINT, gest_interruzione);

do{
    op=scelta();
    sprintf(oper,"%d",op);
    if(write(ds_sock, oper, sizeof(oper))<0){
        if(errno!=EINTR) perror("Errore di scrittura");
    }

    switch(op){
            case 1:
                printf("INSERIMENTO NUOVO CONTATTO\n");

                if(passwordCorretta(ds_sock)){
                    printf("CLIENT: password aggiungi corretta\n");

                    do{
                        printf("Cognome >> ");
                        fgets(cognome,sizeof(cognome),stdin);
                        //scanf("%s", cognome);
                        printf("Nome >> ");
                        fgets(nome,sizeof(nome),stdin);
                        //scanf("%s", nome);
                        printf("Telefono >> ");
                        fgets(telefono,sizeof(telefono),stdin);
                        //scanf("%s", telefono);
                        if(write(ds_sock, cognome, sizeof(cognome))<0){
                            if(errno!=EINTR) perror("Errore di scrittura");
                        }
                        if(write(ds_sock, nome, sizeof(nome))<0){
                            if(errno!=EINTR) perror("Errore di scrittura");
                        }
                        if(write(ds_sock, telefono, sizeof(telefono))<0){
                            if(errno!=EINTR) perror("Errore di scrittura");
                        }

                        if(read(ds_sock, ris, sizeof(ris))<0){
                            if(errno!=EINTR) perror("Errore di lettura");
                        }
                        trovato=atoi(ris);

                        switch(trovato){
                            case 0:
                                printf("Errore di lettura nel Server\n");
                                break;
                            case 1:
                                printf("Il contatto è già presente nell'elenco\n");
                                break;
                            case 2:
                                if(read(ds_sock, ris, sizeof(ris))<0){
                                    if(errno!=EINTR) perror("Errore di lettura");
                                }
                                aggiunto=atoi(ris);
                                if(aggiunto==0) printf("Errore di scrittura nel Server\n");
                                else printf("Il contatto è stato correttamente inserito nell'elenco\n");
                                break;
                        }

                        printf("Vuoi aggiungere un altro contatto? [SI/NO]\n");
                        scanf("%s", continua);
                        if(write(ds_sock, continua, sizeof(continua))<0){
                            if(errno!=EINTR) perror("Errore di scrittura");
                        }
                    }while(strcmp(continua, "SI")==0);

                }
                break;

            case 2:
                printf("RICERCA DI UN NUMERO TELEFONICO\n");

                if(passwordCorretta(ds_sock)){
                    printf("CLIENT: password cerca corretta\n");

                    do{
                        printf("Cognome >> ");
                        scanf("%s", cognome);
                        printf("Nome >> ");
                        scanf("%s", nome);
                        if(write(ds_sock, cognome, sizeof(cognome))<0){
                            if(errno!=EINTR) perror("Errore di scrittura");
                        }
                        if(write(ds_sock, nome, sizeof(nome))<0){
                            if(errno!=EINTR) perror("Errore di scrittura");
                        }

                        if(read(ds_sock, ris, sizeof(ris))<0){
                            if(errno!=EINTR) perror("Errore di lettura");
                        }
                        trovato=atoi(ris);

                        switch(trovato){
                            case 0:
                                printf("Errore di lettura nel Server\n");
                                break;
                            case 1:
                                if(read(ds_sock, telefono, sizeof(telefono))<0){
                                    if(errno!=EINTR) perror("Errore di lettura");
                                }
                                if(strcmp(telefono, "errore")==0) printf("Errore di lettura nel Server\n");
                                else printf("Il telefono del contatto richiesto è: %s\n", telefono);
                                break;
                            case 2:
                                printf("Il contatto non è presente nell'elenco\n");
                                break;
                        }

                        printf("Vuoi cercare un altro numero di telefono? [SI/NO]\n");
                        scanf("%s", continua);
                        if(write(ds_sock, continua, sizeof(continua))<0){
                            if(errno!=EINTR) perror("Errore di scrittura");
                        }
                    }while(strcmp(continua, "SI")==0);

                }
                break;

            case 3:
                printf("USCITA\n");
                break;

            case 0:
                printf("Eseguito lo SHUTDOWN del Server\n");
                break;
    }

}while(op!=3 && op!=0);

close(ds_sock);

}

i use 3 buffer named cognome,nome,telefono. ideas?

The problem is in your scelta() function. Both versions of it (with scanf() or fgets() ) are wrong.

First I will explain why your fgets() version is wrong.

You declared comando as int , while fgets() expects a char * . This is undefined behavior, and you're lucky (or unlucky) it didn't crash.

As for your scanf() version: This is exactly what I predicted in the comments. scanf() only reads the integer input, and leaves the new line (ENTER key) in the input buffer. This means that your first fgets() call in main() is reading this left-over ENTER key.

One way of doing this correctly is as follows:

long int scelta() {
    char input[20];
    fgets(input, sizeof input, stdin); // this reads input
    while(strchr(input, '\n') == NULL) {
        // the input has not ended
        // it is probably not a long int anyway but you still need to consume it
        // choose your appropriate action, e.g.
        while(getchar() != '\n'); // read everything in input buffer up to (and including) the ENTER key
        puts("error");
        fgets(input, sizeof input, stdin); // read input again
    }
    char *endptr;
    long int comando = strtol(input, &endptr, 10);
    // then check range and check for errors with endptr
    return comando;
}

For a detailed description and example code (with error-checking) of strtol() , please refer to the Linux Programmer's Manual .

If it is supported by your system, the function fpurge cleans input streams and could be used in that case :

if(passwordCorretta(ds_sock)){
   fpurge(stdin);
   printf("CLIENT: password aggiungi corretta\n");

   do{

and do not try to use fflush because it only acts on output streams.

But anyway, you should try to understand where the unwanted input comes from. This is not far from a quick and dirty hack but at least is harmless is nothing was left in buffer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM