Limit size of a String?

3

I declare

char pl1[10], pl2[10];

And I did the following:

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

Thinking he would read only the first 10 characters that the user types. So, when I type a name with more than 10 characters the program reads wrong, for example, it is typed "dynamically", it associates "dynamicame" with pl1 and "nte" with pl2 . I have tried it also without the 10 in the scanf it stores what exceeded the scope in pl1 , example (using "dynamically") it ignores the first name entered (if the second is longer than 10 characters), and assign the first 10 characters typed when you ask for Nome do Player 2 a pl2 and the rest on pl1 . If the typed in pl2 is less than 10 characters it stores it dynamically in pl1 and the name that was typed in pl2 .

    
asked by anonymous 12.06.2015 / 16:31

3 answers

-2

I thought about it a little bit, I tried it but it went wrong, but today, during the lesson, the idea came to me, I got to each one, 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 scanf , and if the vector has length greater than 10 then in a while it deletes the characters up to element 10 of the vector:

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.

    
13.06.2015 / 06:03
6

You need space for '&' and you can not by // ente<ENTER> operator

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

but the rest of the string is in the buffer scanf() and will be caught in fgets() 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 %code%

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 ideone

    
12.06.2015 / 16:46
3

The problem is precisely the fact that the scanf function does not check if the size of the read string "fits" within the reserved area. Therefore, when reading more than the allocated, the function continues writing in memory. Since you have 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 invade a memory area that is not reserved for your program, causing runtime errors.

If your compiler is from Microsoft *, there is the scanf_s function that lets you enter the maximum number of characters to be read (see in this other SOEN issue ). Otherwise, you need to take proper care. A good solution was 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 secure) size of your read buffer, and it uses the snprintf function to create the mask with the desired size for the buffer and ensure that errors do not occur.

* It's important to note comment of fellow @pmg on scanf_s is an optional function for C compilers, not just something unique to Microsoft compilers.

    
12.06.2015 / 16:47