Parameters of the scanf function

4

While studying the scanf function with a little more depth, I had a question about the arguments I put before% when reading a string, that is scanf("argumentos...%s",minhastring) , in the following codes I add a space and the ' J 'before the% to verify the behavior of scanf, that is the cleaning of the buffer is not what is under study, because this is not a correct way to do such a treatment, but rather the utility of putting characters before the%:

First version of the code:

//abrindo um arquivo para escrever o resultado do que for digitado
FILE *arq = fopen("testes.txt","w");
char str1[20], str2[20];
//lendo duas strings, o %19 limita o numero de caracteres a ser armazenado, evitando o
//overflow e o [^\n] faz com que o conteudo seja lido até encontrar uma quebra de linha,
// tornando possivel a leitura de strings com espaço
printf("Digite a primeira string: ");
scanf("%19[^\n]s", str1);
printf("Digite a segunda string: ");
scanf("%19[^\n]s", str2);
//armazenando a string formatada no arquivo: testes.txt
fprintf(arq, "Foi digitado \"%s\" e \"%s\" ", str1, str2);
//fechando o arquivo
fclose(arq);

Here are some tests and their outputs in a file:

1st

  

Type the first string: Antonio

     

Type the second string:

     

"Antonio" and "NÊ8~þÿÿÿb8v¼ [= v @"

I then changed the code and put a space before the "%" of the second scanf and also added the character 'J'.

Before the change: scanf("%19[^\n]s", str2);

Now scanf(" J%19[^\n]s", str2)

I could not type the second string, after typing the first one the program was terminated, in the next example the space is probably 'catching' the '\ n', and the 'J' character is forcing the second string to start with the letter 'J':

2nd Version of the code:

FILE *arq = fopen("testes.txt","w");
char str1[20], str2[20];
printf("Digite a primeira string: ");
scanf("%19[^\n]s", str1);
printf("Digite a segunda string: ");
scanf(" J%19[^\n]s", str2);
fprintf(arq, "Foi digitado \"%s\" e \"%s\" ", str1, str2);
fclose(arq);

Here are some tests and their outputs in a file:

1st

  

Type the first string: Maria Eduarda

     

Enter the second string: Joao Carlos

     

"Maria Eduarda" and "Oao Carlos" were spelled

2nd

  

Type the first string: Maria Eduarda

     

Type the second string: Maria Joaquina

     

"Maria Eduarda" and "> Þþÿÿÿb8v¼ [= v @"

Interesting Findings: The scanf space is solving the problem of what was in stdin , the '\ n' that "left" of the first data entry was ignored. By putting the letter 'J', or any other, before the '%' sign, I can only correctly read a string if it starts with the letter entered as a parameter, and the entered letter is ignored by scanf , which does not stores it in the variable, as in the first test:

  

Type the first string: Maria Eduarda

     

Enter the second string: Joao Carlos

     

"Maria Eduarda" and "Oao Carlos" were spelled

-> This doubt arose when doing some tests and "playing around" a bit in the code blocks. I find C a very interesting language. And I would like to get this question: What happens when I put arguments between the quotation marks and the '%' in the scanf? And when they are generally used, if they are used?

    
asked by anonymous 27.06.2016 / 03:15

1 answer

3

Before you begin, I think you actually wanted to use "%19[^\n]" instead of "%19[^\n]s" . The second version actually means "a string of up to 19 characters without being \n , followed by the letter" s ".

The reason for the strange behavior of your first program is that the first scanf does not consume \n of the first line of your input file. When the second scanf tries to run, it stumbles upon this \n and can not read what is on the second line.

Apparently, when scanf using [ can not read anything it does not modify the string buffer you pass to it. I think it would make more sense if it filled the buffer with an empty string but it seems like that is not the case ... Anyway, you can disappear with that exquisite output if you initialize your buffers with a default value:

char str1[20] = "AAAA";
char str2[20] = "BBBB";

On your second program, the at the beginning of the second scanf formatting string means "consume zero or more whitespace." This includes% w / o of the first line that had stumbled the first version of your program (and would also include whitespace at the beginning of the second line).

That said, I do not recommend using \n to read entire lines in this way. As you may have guessed, it is very easy to shoot with the scanf in this case and both versions of your program have subtle bugs (the first one does not work and the second one has whitespace at the beginning of the second line).

Instead of using the scanf I recommend using the scanf function to read a whole line. It receives the output buffer, the maximum buffer size (maximum number of characters plus one) and a fgets of where the entry is going to be read:

fgets(str1, 20, stdin);
fgets(str2, 20, stdin);

The only problem with fgets is that it includes FILE* in the buffer. If you do not like \n you will need to remove it by hand.

Another possibility is to read the input characters one by one, with \n or getchar . It gives you more work but it allows you to have a fine control of what you're doing.

Returning to the question at the end of your post:

  

What happens when I put arguments between the quotation marks and the '%' in the scanf?

The first argument of the scanf function (the "format string") consists of a directive sequence. A policy can be:

  • A sequence of spaces (space, tab, line break, etc.)
  • A normal letter (without being fgetc or a spice)
  • A conversion specification, starting with the letter %
  • The semantics of scanf are to process the directives in sequence.

  • In the spaces directive, the scanf consumes zero or more spaces, stopping just before the first character of the entry that is not a space or the EOF.
  • In the case of the normal letter directive, scanf tries to read exactly one input character and fails if the read character is not as expected.
  • In the case of directives with % , scanf does something different depending on each case. Usually it will be ignore spaces followed by trying to read something from the entry.
  • For a concrete example, consider calling % . In this case the format string has 4 directives and scanf will do the following:

  • Ignore all the whitespace at the beginning of the entry.
  • Read the letter scanf(" J%d%19[abc]", &n, buf) of the entry (and fail if you did not have a J to read)
  • Ignore whitespace; read a number from the entry and store it at address J (and fail if you can not read a number)
  • Read a string (maximum 19 letters) containing only the letters &n , a , or b and store it in c . ( buf conversion is an exception and does not skip blanks before attempting to read formatted data)
  • 27.06.2016 / 04:14