HiveBrain v1.2.0
Get Started
← Back to all entries
debugcMinor

C gets_s() implementation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
implementationgets_sstackoverflow

Problem

I'm in a class that is using C, and my instructor has unfortunately used gets() in sample code.

As this is obviously a heinous oversight, likely to cause undefined behavior and other various issues (only a little sarcasm), I decided to implement gets_s(), because it was a fun exercise and sometimes it's just not worth it to do full error checking with fgets() and you just want to truncate unexpectedly long lines.

I'm not concerned whether this fully implements gets_s() as specified in the C11 standard -- this is just supposed to be a drop-in replacement for gets() that doesn't overrun your buffer.

However, what is very important is that this function actually does what it advertises: it's safe and doesn't overrun the buffer.

This is my first time working in C (I usually use java or kotlin), and I appreciate all tips, though I'd like at least some mention of the safety of this code, and am also interested in portability (to current compilers).

gets_s.h

#include 
#include 

#define GETS_S_OK 0
#define GETS_S_ERROR 1
#define GETS_S_OVERRUN 2

static inline int gets_s( char str[], int n )
{
  char *str_end, *fgets_return;
  int temp;

  fgets_return = fgets( str, n, stdin );

  /* If fgets fails, it returns NULL.
  This includes the case where stdin is exhausted. */
  if ( fgets_return == NULL )
  {
    str[0] = '\0';
    return GETS_S_ERROR;
  }

  str_end = str + strlen(str) - 1;

  if ( str_end == '\n' )
  {
    *str_end = '\0';
    return GETS_S_OK;
  }

  temp = fgetc( stdin );
  if (temp == EOF || temp = '\n')
    return GETS_S_OK;

  do temp = fgetc( stdin );
  while ( temp != EOF && temp != '\n' );

  return GETS_S_OVERRUN;
}


and a small test file:

gets_s.c

```
#include "gets_s.h"
#include

int main()
{
char buffer[10];
int gets_s_return;

printf("Enter up to %d characters safely.\n", sizeof(buffer) - 1);

gets_s_return = gets_s( buffer, sizeof(buffer) );

printf("buffer = %s", buffer);
printf("gets_s return = %d", get

Solution

First, don't call it gets_s as the signature and behavior differs in some subtle and not-so-subtle ways, that just leads to confusion and frustration. Anyway, you really wouldn't want the gets_s-contract.

Call it something descriptive like getline_truncated.

Do you know that n =0 depending on what you decide is "success", respectively !=0 or <0 for "failure".

Code Snippets

if (temp == EOF || temp = '\n')
                        ^
#define GETS_S_TRUNCATED 1
// Because truncation is not neccessarily an error
#define GETS_S_OK 0
#define GETS_S_ERROR EOF
// Because we already have an appropriate negative constant

Context

StackExchange Code Review Q#163133, answer score: 3

Revisions (0)

No revisions yet.