Limit the size of a String?

Asked

Viewed 3,929 times

3

I declared

char pl1[10], pl2[10];

And I did this:

printf("Nome do Player1: ");
scanf("%10s", &pl1);
printf("Nome do Player2: ");
scanf("%10s", &pl2);

Thinking he was only going to read the first 10 characters the user typed. However, when I type a name with more than 10 characters the program reads wrong, example, is typed "dynamically", it associates "dynamicam" to pl1 and "nte" to pl2. I tried too without the 10 on scanf then it stores what exceeded the scope in the pl1, example (using "dynamically") it ignores the first name typed (if the second is more than 10 characters), and assigns the first 10 characters typed when asking for the Nome do Player 2 á pl2 and the rest in pl1. Case the typed in pl2 is less than 10 characters it stores dynamically in pl1 and the name that was entered in pl2.

3 answers

6

You need room for the '\0' and you can’t put the & operator

scanf("%9s", pl1); // p1 = "dinamicam\x00"

but the rest of the string stays in the buffer // ente<ENTER> and will be caught in the scanf() next

scanf("%9s", pl2); // pl2 = "ente\x00" e fica o <ENTER> pendurado no buffer

EDIT

If you want to cut the input in the first 9 characters and ignore the rest, use fgets()

fgets(p1, sizeof p1, stdin);
lenp1 = strlen(p1);
if (p1[lenp1 - 1] == '\n') {
    /* nome completo, com ENTER incluido */
    p1[--lenp1] = 0; // apagar o ENTER
} else {
    /* ENTER e possivelmente outros caracteres ficaram no buffer */
    int ch;
    do ch = getchar(); while (ch != '\n'); // limpa caracteres extra
}

fgets running on the ideone

  • I think it would be better to change the vector size to 11 instead of decreasing the number of characters read

  • I couldn’t reproduce here, it was the same

  • The situation I described is: https://ideone.com/OlzRmU

  • Yes, this is the error that has been occurring with me, P1 has "dynamicam" P2 has the same "entity" in its example

  • But if p1 has space for 9 characters plus the terminator ... can not put there "dinamicamente"!

  • Yes I know, but he should not assign the rest in the other vector, but just ignore the rest, because it is not possible to inform the P2 name, understand the problem now? Type, is to limit the heat the user can type

  • To limit what the user can type while the program runs you will have to use functions specified to your Operating System. Or you use a library that makes it kind of easy, for example ncurses or pdcurses (in English).

  • It’s working when I put it directly as the first thing in the program, when I put it inside the menu case or if it doesn’t work, it skips the P1 part

  • Mingle fgets() with scanf() is a bad idea. Apparently the menu uses scanf() and leaves things hanging in the buffer. Change these scanf() for fgets() followed by sscanf().

  • It disturbs the fgets() even being integer? I did not know rs I will try here

Show 5 more comments

3

The problem is precisely the fact that the function scanf does not check whether the size of the string read "fits" within the reserved area. Therefore, when reading more than allocated, the function continues to write in memory. As you declared the two variables one after the other, it happens that it ends up recording in the area of the next variable. It could be much worse, it could hack into an area of memory that is not reserved for your program, causing execution errors.

If your compiler is from Microsoft*, there is the function scanf_s which allows you to enter the maximum number of characters to be read (more details on this other issue of SOEN). Otherwise, you need to take due care. A good solution has been proposed in this SOEN response:

int scanner(const char *data, char *buffer, size_t buflen)
{
    char format[32];
    if (buflen == 0)
        return 0;
    snprintf(format, sizeof(format), "%%%ds", (int)(buflen-1));
    return sscanf(data, format, buffer);
}

Basically, you create a function of your own (scanner) that receives a parameter (buflen) with the maximum (and safe) size of your read buffer, and it uses the function snprintf to create the mask with the desired size for the buffer and ensure that errors do not occur.

* It is important to note the comment @pmg on the scanf_s be an optional function for C compilers, not just something exclusive to Microsoft compilers.

  • 1

    the scanf_s() is described in C Latest Standard but is part of Annex K which is optional for compilers.

  • @pmg Thanks, I didn’t know. I always thought it was something specific to Microsoft compilers.

-2


I thought a little, I tried, but it was wrong, but today I came up with the idea, I got there, I tried, and it worked. First we must change the value of the vectors to a number that the user will probably never put as 100. After that we gave the scanf, and if the vector has length greater than 10 it then in a while that erases the characters up to vector element 10:

int i;
char p1[100], p2[100];
printf("\nNome do Player1: ");
scanf("%s", &p1);
printf("Nome do Player2: ");
scanf("%s", &p2);

//Redefine tamanho do Nome do player1
i = strlen(p1);
if (i > 10){
    while(i != 9){
         p1[i] = 0;
         i --;
    }
}

//Redefine tamanho do Nome do player2
i = strlen(p2);
if (i > 10){
    while(i != 9){
         p2[i] = 0;
         i --;
    }
}

This was the simplest way I found without having to change the rest of the program.

  • 1

    "First we must change the value of the vectors to a number that the user will probably never put as 100." Uhoh! That’s how they’re born buffer overflow.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.