C - scanf() vs gets() vs fgets()

c fgets
scanf() vs fgets
c gets
fscanf
scanf vs gets vs fgets
gets vs scanf
fgets vs fscanf
gets and puts in c

I've been doing a fairly easy program of converting a string of Characters (assuming numbers are entered) to an Integer.

After I was done, I noticed some very peculiar "bugs" that I can't answer, mostly because of my limited knowledge of how the scanf(), gets() and fgets() functions work. (I did read a lot of literature though.)

So without writing too much text, here's the code of the program:

#include <stdio.h>

#define MAX 100

int CharToInt(const char *);

int main()
{
    char str[MAX];

    printf(" Enter some numbers (no spaces): ");
    gets(str);
//  fgets(str, sizeof(str), stdin);
//  scanf("%s", str);

    printf(" Entered number is: %d\n", CharToInt(str));

    return 0;
}

int CharToInt(const char *s)
{
    int i, result, temp;

    result = 0;
    i = 0;

    while(*(s+i) != '\0')
    {
        temp = *(s+i) & 15;
        result = (temp + result) * 10;
        i++;
    }

    return result / 10;
}

So here's the problem I've been having. First, when using gets() function, the program works perfectly.

Second, when using fgets(), the result is slightly wrong because apparently fgets() function reads newline (ASCII value 10) character last which screws up the result.

Third, when using scanf() function, the result is completely wrong because first character apparently has a -52 ASCII value. For this, I have no explanation.

Now I know that gets() is discouraged to use, so I would like to know if I can use fgets() here so it doesn't read (or ignores) newline character. Also, what's the deal with the scanf() function in this program?

C - scanf() vs gets() vs fgets(), scanf() reads input until it encounters whitespace, newline or End Of File(EOF) whereas gets() reads input until it encounters newline or End Of File(EOF), gets()​  fgets() over scanf(): fgets function is short for file-get-string . Remember that files can be pretty much anything on *nix systems (sockets, streams, or actual files), so we can use it to read from standard input, which again, is also technically a file.

Yes, you want to avoid gets. fgets will always read the new-line if the buffer was big enough to hold it (which lets you know when the buffer was too small and there's more of the line waiting to be read). If you want something like fgets that won't read the new-line (losing that indication of a too-small buffer) you can use fscanf with a scan-set conversion like: "%N[^\n]", where the 'N' is replaced by the buffer size - 1.

One easy (if strange) way to remove the trailing new-line from a buffer after reading with fgets is: strtok(buffer, "\n"); This isn't how strtok is intended to be used, but I've used it this way more often than in the intended fashion (which I generally avoid).

Difference between scanf() and gets() in C, What is the difference between scanf () and gets () function? First, when using gets() function, the program works perfectly. Second, when using fgets(), the result is slightly wrong because apparently fgets() function reads newline (ASCII value 10) character last which screws up the result. Third, when using scanf() function, the result is completely wrong because first character apparently has a -52 ASCII value. For this, I have no explanation.

What can I use for input conversion instead of scanf?, does not stop reading input when it encounters whitespace instead it takes whitespace as a string. Difference between gets() and fgets() in C programming language Learn: Difference between gets() and fgets() in C programming language with examples. To read a string value with spaces, we can use either gets() or fgets() in C programming language.

You're correct that you should never use gets. If you want to use fgets, you can simply overwrite the newline.

char *result = fgets(str, sizeof(str), stdin);
char len = strlen(str);
if(result != NULL && str[len - 1] == '\n')
{
  str[len - 1] = '\0';
}
else
{
  // handle error
}

This does assume there are no embedded NULLs. Another option is POSIX getline:

char *line = NULL;
size_t len = 0;
ssize_t count = getline(&line, &len, stdin);
if(count >= 1 && line[count - 1] == '\n')
{
  line[count - 1] = '\0';
}
else
{
  // Handle error
}

The advantage to getline is it does allocation and reallocation for you, it handles possible embedded NULLs, and it returns the count so you don't have to waste time with strlen. Note that you can't use an array with getline. The pointer must be NULL or free-able.

I'm not sure what issue you're having with scanf.

c Programming/stdio.h/scanf, " %n" , code can simply detect if all the format was successfully scanned and that no extra non-white-space junk was at the end. scanf () ends taking input upon encountering a whitespace, newline or EOF. gets () considers a whitespace as a part of the input string and ends the input upon encountering newline or EOF. However, to avoid buffer overflow errors and to avoid security risks, its safer to use fgets (). share. |.

never use gets(), it can lead to unprdictable overflows. If your string array is of size 1000 and i enter 1001 characters, i can buffer overflow your program.

C Programming/stdio.h/fgets, Difference between scanf() and gets() in C · Why "&" is not used for strings in scanf() function? Cin-Cout vs Scanf-Printf · scanf() and fscanf() in  For reading a string value with spaces, we can use either gets() or fgets() in C programming language. Here, we will see what is the difference between gets() and fgets(). fgets() It reads a line from the specified stream and stores it into the string pointed to by str.

Why to use fgets() over scanf() in C?, PIEAS (Pakistan Institute of Engineering and Applied Sciences) C Programming! scanf() VS Duration: 6:29 Posted: Jul 24, 2018 La biblioteca estándar de C provee de varias funciones para introducir datos a nuestros programas. Estas son parte del módulo stdio.h. Vamos a ver la diferencia que existe entre tres de ellas (scanf, gets y fgets). Las tres nos permiten leer cadenas de caracteres introducidas por el usuario pero con importantes diferencias.

C Programming! scanf() VS fgets() VS gets() Which ones better , gets() is used extensively. The C library function int puts(const char *str) writes a string to stdout up to but not including the null character. A newline character  If you use fgets()+ sscanf(), you must enter both values on the same line, whereas fscanf()on stdin(or equivalently, scanf()) will read them off different lines if it doesn't find the second value on the first line you entered.

jayprogramming - scanf vs gets vs puts vs fgets vs fputs, gets() & fgets() - Used for getting a String value with spaces unlike scanf() white space is not a Delimiter in gets() and fgets() in C Programming language. gets - It is  Using scanf or gets depends on the way to receive user input from the standard input which is the keyboard most of the time. scanf is more flexible than gets. Download the PDF Version of scanf vs gets. You can download PDF version of this article and use it for offline purposes as per citation note.

Comments
  • You may wan to replace your CharToInt() function with a call to atoi() (they do the same thing). Also, the char datatype is implicitly signed, which may explain the "-52 ASCII value" you were seeing. cplusplus.com/reference/clibrary/cstdlib/atoi
  • Yes, I could use atoi(), but the very point of this program was to use Bitwise Operators. Also, thank you very much for reminding me about signed value of char. Using unsigned char solved the problem, even though I'm still unsure how and why.
  • @sigint: In C, char can be signed char or unsigned char at the discretion of the compiler.
  • I figured you probably had to write-your-own. As for why unsigned char(s) are solving your problem; A normal (signed) char has a value range of –128 to 127, whereas an unsigned char has a range of 0 to 255. The bit-twiddling was probably doing weird things with the negative values.
  • By the way, *(s+i) is usually written in C as s[i] (it has exactly the same semantics).
  • As I said in my answer, getline is now standard.
  • @Matthew Flaschen: Which standard? When I say "non-standard", I mean "non-standard C", not non-POSIX.
  • The strlen() function doesn't check whether you passed a null pointer. The standard C library specification explicitly says (§7.1.4 Use of library functions): If an argument to a function has an invalid value (such as a value outside the domain of the function, or a pointer outside the address space of the program, or a null pointer, or a pointer to non-modifiable storage when the corresponding parameter is not const-qualified) or a type (after promotion) not expected by a function with variable number of arguments, the behavior is undefined. It is reasonable to require a non-null pointer.
  • It is better to add a one-line safety check and catch careless mistakes then to assume a caller won't make them, but thanks for the Chapter Verse of the spec!
  • If the input line was actually as long as sizeof(str) - 1 or longer, there will be no newline, so this code would discard a valid character.
  • @MattMcNabb, thanks. I think I fixed it (not tested).
  • Note that you should not use strlen(str) until you've checked that fgets() returned a non-null value.
  • Thank you all for your answers. They were very much helpful. But I'd also like to know why scanf() doesn't work in this program? Thank you.
  • To clean things up, consider replacing strchr() with isdigit(). Even better, replace the entire CharToInt() function with a call to atoi(). cplusplus.com/reference/clibrary/cctype/isdigit cplusplus.com/reference/clibrary/cstdlib/atoi