Function scanf with variable amount of parameters, how to implement?

3

I have a text file (txt) that contains the following values:

12 90

These two values I keep and my variables a and b , that is a is equal 12 and b is equal 90 , and I'm using scanf() function to receive these values in the following way:

#include <stdio.h>

int main()
{
    int a, b;

    scanf("%d %d", &a, &b);

    printf("Valor a = %d, b = %d", a, b);

    return(0);
}

Output:

  

Value a = 12, b = 90

I run the program with the following command scanfTeste.exe < arquivo.txt at the prompt of Windows to run the program.

However, the structure of my file will change, time it will have two values or an indeterminate amount, see the examples:

  • Example one of the contents file: 12 90
  • Example two of the contents file: 12 90 33 77

Considering that values are separated by spaces, to make it easier to read the data.

My question:

As you can see the amount of parameters passing to scanf("%d %d ...", &a, &b, ...) changes depending on the amount of values in the file line, how can I make the scanf() function receive a number of parameters according to the amount of values in the file line?

    
asked by anonymous 02.05.2016 / 20:42

2 answers

3

One way is to use normal reading by adapting to needs, something like this:

char arquivo[] = "1 2 3 4 5";
int a, b, c, d, e;
sscanf (arquivo, "%d %d %d %d %d", &a, &b, &c, &d, &e);
printf ("%d - %d - %d - %d - %d", a, b, c, d, e);

See running on ideone .

Obviously you need to use fscanf() which is the correct one for file and not the one I used for easy.

Another possibility, seems to me to be , if you do not want to create all the variables and make reading easier it would read one by one in a loop. Something like this:

int i = 0;
int tamanho = 5;
int array[tamanho];
FILE * arquivo = fopen("file.txt", "r");
while (fscanf(arquivo, "%d", &array[i++]) == 1);

See running on CodingGround .

You can also do this in variable length lists with vfscanf() giving you more flexibility, if you specify the format of the data that will be received in each of the positions. I've never used it and do not have the details, but the documentation provides this example:

#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>

bool checked_sscanf(int count, const char* buf, const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    int rc = vsscanf(buf, fmt, ap);
    va_end(ap);
    return rc == count;
}

int main(void)
{
    int n, m;

    printf("Parsing '1 2'...");
    if(checked_sscanf(2, "1 2", "%d %d", &n, &m))
        puts("success");
    else
        puts("failure");

    printf("Parsing '1 a'...");
    if(checked_sscanf(2, "1 a", "%d %d", &n, &m))
        puts("success");
    else
        puts("failure");
}
    
02.05.2016 / 21:29
1

Well if you want to read through the end of the file do so:

#include<stdio.h>

int main(){
    int a[30], n = 0;

    while(scanf("%d", &a[n++]) != EOF && n < 30)
        printf("a[%d] = %d, ", n-1, a[n-1]);
}

Scanf returns EOF when it arrives at the end of the file and you do not have anything else to read, comparing this you know when the file is finished!

  

Entry:
  2 4 23
  55 12

     

Output:
  a [0] = 2, a [1] = 4, a [2] = 23, a [3] = 55, a [4] = 12,

If you just want to read until you finish the line, it gets a bit more complicated:

#include<stdio.h>

int main(){
    int a[30], n = 0, c;
    char linha[512], *plin;

    scanf("%510[^\n]", linha);
    plin = linha;

    while(sscanf(plin, "%d%n", &a[n++], &c) != EOF && n < 30){
        printf("a[%d] = %d, ", n-1, a[n-1]);
        plin += c;
    }
}
  

Entry:
  2 4 23
  55 12

     

Output:
  a [0] = 2, a [1] = 4, a [2] = 23,

Notice that this time he only read the first line. Scanf% d will not tell you when you skipped a line, it just swallows and line and moves on to the next one. So if you read only the first line with the limiter% [^ n], which reads until you find a \ n and then use sscanf on that line, you can only read the integers of the line!

Remembering that I have put a maximum of 30 numbers, you can increase the limit or make a malloc if 30 is not enough.

Just like you used scanfTeste.exe < arquivo.txt to run the program. The right thing would be to open the file and use it with fscanf

    
02.05.2016 / 23:25