String of characters inside the scanf. Why and how does it work scanf("Day %d",&dia);?

Asked

Viewed 768 times

3

Problem

I was making a code that would read a string and then an entire value:

int dia, h, m, s;
char dp;            //Dois pontos.
scanf("Dia %d",&dia);   //Inicio do evento.
...

I thought of creating a string for the user to type the word "Dia" and then the value. But I saw a code with this example above, the word Dia follows inside the scanf without storing in a string. In that case, if we type exactly as it is inside the scanf (if it were "day" or "day" it would not work, it has to be exactly the same as what is inside the scanf), ie "Dia xx" (where xx can be any integer value) it works, and without having to read characters and store in a variable, ie, I did not point my information to any address to be stored.

I was curious to know why and how this happens.

Doubts

Why, without storing in a variable and without pointing to some address, without informing almost anything pro compiler who would type a string, the scanf executed normally?

How did that happen? This one string has to go somewhere, and since I didn’t specify, where did it go? What is the process that the compiler does with this string?

  • 1

    Have you never heard of the scanf in a C book? Then it shouldn’t be C book... Out of jokes, there’s lots of information on the web about it, a little research would solve your question

  • Yeah, I looked it up. But so far no one can explain how this works, why it accepts that I type a set of characters without storing them anywhere. Where these characters go, and what are the risks of using this in a code.

  • 1

    Maybe people can’t explain why you’re not explaining well what your doubt is. You can improve this. I might even be able to answer if I understand a little better where you’re going. But I’m telling you, you’re storing it somewhere yes.

  • To convey a thought already formulated to another person is really complicated, I will try to be clearer. Using scanf("Day %d",&dia); allows you to type the string "Day" without storing it in a variable. My question is to understand why the scanf accept that I do this and know where this string went. And also understand HOW this process happens, like, how does the compiler do it? eg: "ah, it takes the characters and does so and baked with them". Of course this should have its risk margin and I would also like to know about it, ie, what risks I have in using it. Got better?

  • 1

    The question is interesting and within the scope of the site, but @Filipimaciel if you manage to clear the question and make it clearer, I’m sure that future generations will be able to learn from it.

  • I’ll do it. Thank you for the touch!

  • Always check the amount returned by scanf(). This value indicates whether the reading went well or badly.

Show 2 more comments

2 answers

4

What happens in this case is that the scanf(...) a format string. This format string indicates to scanf(...) how to process the read input, ie is a formatting directive. If processing the input the validation of this directive fails, the scanf(...) to read the inputs and returns.

A Directive may consist of the following(s):

  • A sequence of spaces;

  • A normal character (a-za-Z0-9, etc.) as long as it is not a white space or a %;

  • A conversion specifier that is started by the %character. Inputs are read and converted according to this specifier and placed in the respective pointer (for example, scanf("%d", &i).

In your case, your formatting directive is "Day %d". With this directive, scanf(...) is waiting to read an input that starts as "Dia " and then a whole. So when you put something that does not start with "Dia " the scanf(...) failure and nothing is read for the variable dia.

Examples:

scanf(...) successfully:

int dia = 0;
scanf("Dia %d", &dia); // Input: Dia 123
printf("%d", dia); // Output: 123

scanf(...) glitch:

int dia = 0;
scanf("Dia %d", &dia); // Input: 123
printf("%d", dia); // Output: 0 (valor colocado em dia)

scanf(...) failure (day variable not initialized):

int dia;
scanf("Dia %d", &dia); // Input: 123
printf("%d", dia); // Output: int_min (valor default de inicialização do int)

For more information see this page which exhaustively describes how the scanf(...) and supported format strings.

  • Very interesting. Thanks friend! helped me a lot too.

4


There’s a lot of mistakes there. You’ve never seen it in books because of this. I think you miss at least two concepts in C. I won’t go into too many details.

Pointers

When you write &dia is the same as saying "in the address of". This is a way to use pointer. The pointer is an indicator that you will use a memory address. The scanf() waits as other parameters after the first one which is the formatting you send as memory addresses arguments. That’s why you can’t just send dia. If I sent this variable this way, I would be sending the function its value and that’s not what you should do. So then you even did it right, sent the address where dia is stored.

dia as well as h, m and s and dp are stored somewhere as you stated before. Probably one after the other. Although this is dependent on implementation and platform, probably these variables are reserving 4 bytes each which is the most common size for type int. The guy char probably has 1 byte. So you booked 17 bytes in sequence.

How did you send the address of dia to the scanf(), he will store the characters read at this address you passed. The first four characters will be in the variable dia, the following four in the variable h and so on. What if I type more than 17 characters? See below.

And can you save integer characters? Can you!

Undefined behavior

You’re taking advantage of a concept called undefined behavior that is used a lot by languages like C where you need to give flexibility, ease of adaptation to various platforms and creative ways to improve performance. C is almost a Assembly. C allows direct access to hardware. C does not control too much what the programmer is doing. C understands that the programmer must know what he is doing even if he does something potentially dangerous.

So you’re storing characters where there should be integers. No problem. Of course in your case it is not the intention, but it works (I always say that working is different from being right). Each 4 characters will form an integer. A value that probably has no meaning for your program, but works.

The problem is when you pass the 17 characters. There you will be storing data in memory area not reserved for variables. Yes, this is possible in C, so C is such a cool and powerful language but also so dangerous. C lets you write in any area of your application’s memory. And that’s where you can cause serious problems for her. In some cases, coincidence will not cause. Only that programming cannot get results by coincidence.

You could have caused an even bigger problem. You could have sent the value of dia as if it were the pointer (I’m not talking about sending the address as you sent it, it would call scanf("Dia %d", dia);). And it could "work". Of course you would be trying to store the data read by scanf() at an address you don’t even know the value of. Yes, because you didn’t initialize values for variables, so its values are those that were already in memory at that position.

Unless you know very well what you are doing, have a very strong reason, never use indefinite behavior in your programs.

Error of formatting the scanf()

I won’t say much because Omni’s answer already gave the important details of this. The string formatting is wrong. You are specifying a format that does not exist, which is not well interpreted by scanf(). This is where you end up not even being able to do anything. But there is no reason why the compiler gives any error, the failure occurs in running.

The responsibility is not the compiler in this case. It is the internal code of the scanf(). Do not forget that the scanf() is a function like any other. Some programmer created it as you create your programs. She has no privileges in C, she is just a program that goes along with C to facilitate performing some operations in a standard way. Luckily the function does not let do what it wants and does not cause all the disaster I mentioned above. But it’s also far from doing what you want and being something useful.

Completion

So this "works" of yours is a "more or less" well. It doesn’t give an error, but it works, it doesn’t work.

  • Now my question has been answered, thank you man.

Browser other questions tagged

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