JuMoGar
JuMoGar

Reputation: 1760

Best way of input in C console application: Differences between different types of inputting string in a console application C

Hi have been doing research and I have found three most common different types of input inside a C console application:

Having said this, I will show an example (MCVE) of the use of the three functions and what is picking up them:

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

int main(void)
{
    char hello[7]; //Will store word 'hello'; Length is 6 = 5+(1)+1 = strlen("hello")+(BreakLineChar)+NullTermination - BreakLineChar will appear (or not) depending input type
    int i;

    // SCANF()
    printf("Input HELLO: ");
    scanf("%[^\n]s",hello);
    fflush(stdin);
    printf("Length: %d\n", strlen(hello));
    for (i = 0; i < strlen(hello); i++)
    {
        printf("%i: %c\n", i, hello[i]);
    }
    printf("\n\n");

    // GETS()
    printf("Input HELLO: ");
    gets(hello);
    fflush(stdin);
    printf("Length: %d\n", strlen(hello));
    for (i = 0; i < strlen(hello); i++)
    {
        printf("%i: %c\n", i, hello[i]);
    }
    printf("\n\n");

    // FGETS()
    printf("Input HELLO: ");
    fgets(hello,sizeof(hello),stdin);
    fflush(stdin);
    printf("Length: %d\n", strlen(hello));
    for (i = 0; i < strlen(hello); i++)
    {
        printf("%i: %c\n", i, hello[i]);
    }
    printf("\n\n");

    return 0;
}


This code, have next output:

Input HELLO: hello
Length: 5
0: h
1: e
2: l
3: l
4: o


Input HELLO: hello
Length: 5
0: h
1: e
2: l
3: l
4: o


Input HELLO: hello
Length: 6
0: h
1: e
2: l
3: l
4: o
5:




Process returned 0 (0x0)   execution time : 5.757 s
Press any key to continue.


So, as we can see, three conclusions can be drawn from this:

       hello[0] = 'h'

       hello[1] = 'e'

       hello[2] = 'l'

       hello[3] = 'l'

       hello[4] = 'o'

       hello[5] = '\0'

       hello[0] = 'h'

       hello[1] = 'e'

       hello[2] = 'l'

       hello[3] = 'l'

       hello[4] = 'o'

       hello[5] = '\0'

       hello[0] = 'h'

       hello[1] = 'e'

       hello[2] = 'l'

       hello[3] = 'l'

       hello[4] = 'o'

       hello[5] = '\n'

       hello[6] = '\0'


Are my conclusions correct? Any information to add?

Thank you.

Upvotes: 1

Views: 524

Answers (2)

JuMoGar
JuMoGar

Reputation: 1760

In this answer I will make a compilation of all the answers obtained, and of the research work that I continue doing (I will update the answer as I get new information):

  • gets is insecure, one against it is buffer overflow
  • Most safe method for inputting by console is fgets, but it have a contra: This command reads '\n' character too. To solve this we can do the following:

    #include <stdio.h>
    #include <string.h>
    #define MAX_SIZE_STRING 5
    
    int main(void)
    {
        char string[MAX_SIZE_STRING+1]; // MAX_SIZE_STRING + 1 due to a string needs '\0' char at the end
        int i;
    
        printf("Input a string: ");
        fgets(string, MAX_SIZE_STRING, stdin);
    
        // Remove '\n' character inside the string:
        string[strcspn(string, "\n")] = '\0';
    }
    
  • scanf is a very powerful function, which is necessary to know it thoroughly to use it well. Speaking of scanf, I'm going to show an example of how to use scanf which controls everything you need (size, when stop reading, avoid bufferOverflow,...):

    #include <stdio.h>
    #include <string.h>
    #define MAX_SIZE_STRING 5
    #define STR_(X) #X
    #define STR(X) STR_(X)
    
    int main(void)
    {
        char string[MAX_SIZE_STRING+1]; // MAX_SIZE_STRING + 1 due to a string needs '\0' char at the end
        int i;
    
        printf("Input a string: ");
        scanf(" %" STR(MAX_SIZE_STRING) "[^\t\n]%*[^\n]", string);
        // EXPLANATION OF THE COMMNAD:
        // First blanck-space: It is used for empty string. If user entries only blank-spaces, it will no stored in the var until user input any char
        // STR(TAM_MAX): Use of preprocessor for adding a max length to the input
        // [^\t\n]: Pick up until find a '\t' or a '\n'
        // So, at the end, this command is equal to: scanf(" %5[^\t\n]s", string);
        // %*[^\n] remove end/break line (\n) so, by this way, buffer overflow is avoied 
    }
    

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

Your conclusions are correct. However, of the three input methods that you reference only fgets is safe:

  • scanf into a string without a limit can overflow an input buffer; see a fix below.
  • gets is deprecated, because it could not possibly be made safe of buffer overflow (why?).

To fix scanf specify the size of your buffer, and leave space for null terminator:

scanf("%6[^\n]", hello);

Note that s at the end is not necessary when you are using [^\n] format specifier.

Upvotes: 1

Related Questions