简体   繁体   中英

Difference between fgets and gets

What is the difference between fgets() and gets() ?

I am trying break my loop when the user hits just "enter". It's working well with gets() , but I don't want to use gets() . I tried with fgets() and scanf() but I don't have the same results as with gets() . fgets() breaks the loop whatever user enters in text! Here is my code :

void enter(void)
{
  int i,

  for(i=top; i<MAX; i++)
    {
      printf(".> Enter name (ENTER to quit): ");
      gets(cat[i].name);

      if(!*cat[i].name)
         break;

      printf(".> Enter Last Name: ");
      scanf("%s",cat[i].lastname);
      printf(".> Enter Phone Number: ");
      scanf("%s",cat[i].phonenum);
      printf(".> Enter e-Mail: ");
      scanf("%s",cat[i].info.mail);
      printf(".> Enter Address: ");
      scanf("%s",cat[i].info.address);
      printf("\n");
    }
  top = i;
}

A difference between gets() and fgets() is that fgets() leaves the newline in the buffer. So instead of checking whether the first element of the input is 0 , check whether it's '\\n' ;

fgets(cat[i].name, sizeof cat[i].name, stdin);
if (cat[i].name[0] == '\n' || cat[i].name[0] == 0) {
    // empty line or no input at all
    break;
} else {
    // remove the trailing newline
    int len = strlen(cat[i].name);
    cat[i].name[len-1] = 0;
}

Drop gets() and scanf() .
Create a helper function to handle and qualify user input.

// Helper function that strips off _potential_ \n
char *read1line(const char * prompt, char *dest, sizeof size) {
  fputs(prompt, stdout);
  char buf[100];
  *dest = '\0';
  if (fgets(buf, sizeof buf, stdin) == NULL) {
    return NULL;  // EOF or I/O error
  }
  // Remove potential \n
  size_t len = strlen(buf);
  if (len > 0 && buf[len-1] == '\n') {
    buf[--len] = `\0`;
  }
  // Line is empty or too long
  if (len == 0 || len >= size) return NULL;
  return memcpy(dest, buf, len+1);
}

void enter(void)
{
  int i;

  for(i=top; i<MAX; i++)
    {
      if (read1line(".> Enter name (ENTER to quit): ", 
          cat[i].name, sizeof cat[i].name) == NULL) break;
      if (read1line(".> Enter Last Name: ", 
          cat[i].lastname, sizeof cat[i].lastname) == NULL) break;
      if (read1line(".> Enter Phone Number: ", 
          cat[i].phonenum, sizeof cat[i].phonenum) == NULL) break;
      if (read1line(".> Enter e-Mail: ", 
          cat[i].info.mail, sizeof cat[i].info.mail) == NULL) break;
      if (read1line(".> Enter Address: ", 
          cat[i].info.address, sizeof cat[i].info.address) == NULL) break;
    }
  top = i;
}

Some attributes of fgets() and gets() :

fgets() reads input and saves to a buffer until:
1) The buffer is 1 shy of being full - or -
2) '\\n' is encountered - or -
3) The stream reaches an end-of-file condition - or -
4) An input error occurs.

gets() does #2 - #4 above except it scans, but does not save a '\\n' .
gets() is depreciated in C99 and no longer part of C11.

The problematic difference between gets and fgets is that gets removes the trailing '\\n' from an input line but fgets keeps it.

This means an 'empty' line returned by fgets will actually be the string "\\n".

The nasty difference, that means it's best to avoid gets altogether, is that if you give gets a line that's too long your program will crash in very bad ways.

you can use fgets() with STDIN instead. This function is secured and always insert a '\\0' at the string end.

An example:

char inputbuffer[10];
char *p;
p = fgets(inputbuffer, sizeof(inputbuffer), stdin);
printf(">%s<\n", p);    /* p is NULL on error, but printf is fair */

You'll get at most 9 characters + '\\0', in this example.

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