Use a variable to limit character reading with fscanf and data mask

1

I've created a structure that holds any three records. These records I read from a file f. They have a definite size, in the case below the first die has three characters, the second 17 and the third three. I use it because data can come in anyway, but the pattern is guaranteed. Example inside file f:

999 Eduardo Oliveira SI

111EduardoOliveira SI (Two spaces before SI, I could not put here)

for (i = 0; i < qtde_registros; i++)
{
    fscanf(f,"%3s",rt[i].m);
    rt[i].m[3]='
int tamPrimeiroDado=3;
int tamSegundoDado=17;
int tamTerceiroDado=3;

for (i = 0; i < qtde_registros; i++)
{
    fscanf(f,"% >>AQUI(tamPrimeiroDado)<< s",rt[i].m);
    rt[i].m[tamPrimeiroDado]='
for (i = 0; i < qtde_registros; i++)
{
    fscanf(f,"%3s",rt[i].m);
    rt[i].m[3]='
int tamPrimeiroDado=3;
int tamSegundoDado=17;
int tamTerceiroDado=3;

for (i = 0; i < qtde_registros; i++)
{
    fscanf(f,"% >>AQUI(tamPrimeiroDado)<< s",rt[i].m);
    rt[i].m[tamPrimeiroDado]='%pre%';
    fscanf(f,"% >>AQUI(tamSegundoDado)<< c",rt[i].n);
    rt[i].n[tamSegundoDado]='%pre%';
    fscanf(f,"% >>AQUI(tamTerceiroDado)<< c",rt[i].c);
    rt[i].c[tamTerceiroDado]='%pre%';
}
'; fscanf(f,"%17c",rt[i].n); rt[i].n[17]='%pre%'; fscanf(f,"%3c",rt[i].c); rt[i].c[3]='%pre%'; }
'; fscanf(f,"% >>AQUI(tamSegundoDado)<< c",rt[i].n); rt[i].n[tamSegundoDado]='%pre%'; fscanf(f,"% >>AQUI(tamTerceiroDado)<< c",rt[i].c); rt[i].c[tamTerceiroDado]='%pre%'; }
'; fscanf(f,"%17c",rt[i].n); rt[i].n[17]='%pre%'; fscanf(f,"%3c",rt[i].c); rt[i].c[3]='%pre%'; }

It is working perfectly, the problem is that I do not want to leave this fixed size, I want to get the size of each of the three data with the user or another file. How can I replace these "3,17,3" numbers with variables. Example of what I want:

%pre%

With one or more 'for', 'fseek', 'fgetc' ... I get what I want, but is there any way I can do this with C data masks? Thank you.

    
asked by anonymous 13.10.2018 / 21:33

1 answer

1

Scanf, sscanf, and fscanf do not directly support the field variable size specification.

You can however use tricks, as shown here .

The best solution however is to use fgets and calloc , and separate the fields manually.
These functions (scanf, fscanf, sscanf) are very fragile, in practice they are not used "in real life".

#include <stdio.h>  // fgets, printf
#include <stdlib.h> // calloc
#include <string.h> // memcpy

int main()
{
  // definicao dos tamanhos dos campos
  int tamCpo1 = 3;
  int tamCpo2 = 17;
  int tamCpo3 = 3;

  // definicao do tamanho do registro
  int tamRegistro = tamCpo1 + tamCpo2 + tamCpo3;

  // aloca memoria para os campos individuais
  // soma 1 para zero binario no final
  char* cpo1 = calloc(tamCpo1+1, 1);
  char* cpo2 = calloc(tamCpo2+1, 1);
  char* cpo3 = calloc(tamCpo3+1, 1);

  // aloca memoria para o registro
  // soma 2 para reservar espaco para \n
#include <stdio.h>  // fgets, printf
#include <stdlib.h> // calloc
#include <string.h> // memcpy

int main()
{
  // definicao dos tamanhos dos campos
  int tamCpo1 = 3;
  int tamCpo2 = 17;
  int tamCpo3 = 3;

  // definicao do tamanho do registro
  int tamRegistro = tamCpo1 + tamCpo2 + tamCpo3;

  // aloca memoria para os campos individuais
  // soma 1 para zero binario no final
  char* cpo1 = calloc(tamCpo1+1, 1);
  char* cpo2 = calloc(tamCpo2+1, 1);
  char* cpo3 = calloc(tamCpo3+1, 1);

  // aloca memoria para o registro
  // soma 2 para reservar espaco para \n%pre%
  char* registro = calloc(tamRegistro+2, 1);

  // para computar tamanho do registro lido
  int tamRegLido;

  // arquivo a ser lido
  FILE* arq;

  // abre arquivo arq
  arq = fopen("teste.txt", "r");
  if (!arq)
  {
    printf("*\n");
    printf("* arquivo 'teste.txt' inexistente\n");
    printf("*\n");
    exit(1);
  }

  printf("*\n");

  // loop de leitura dos registros
  for (;;)
  {
    // tenta ler um registro
    if (!fgets(registro, tamRegistro+2, arq))
    {
      printf("*\n");
      if (feof(arq))
        printf("* fim de arquivo\n");
      else
        printf("* erro na leitura\n");
      break; // sai do while
    }

    // ok, leu um registro

    // computa o tamanho do registro lido
    tamRegLido = strlen(registro);

    if (tamRegLido < tamRegistro + 1)
    {
      printf("* ignorando registro com tamanho menor\n");
      continue; // volta para inicio do while
    }

    if (registro[tamRegistro] != '\n')
    {
      printf("* ignorando registro com tamanho maior\n");
      continue; // volta para inicio do while
    }

    // registro lido com tamanho correto

    // separa os campos
    memcpy(cpo1, registro, tamCpo1);
    memcpy(cpo2, registro+tamCpo1, tamCpo2);
    memcpy(cpo3, registro+tamCpo1+tamCpo2, tamCpo3);

    // mostra os campos1 lidos
    printf("* campo 1: [%s]\n", cpo1);
    printf("* campo 2: [%s]\n", cpo2);
    printf("* campo 3: [%s]\n", cpo3);
    printf("*\n");
  }

  printf("*\n");
  printf("* fim\n");
  printf("*\n");
}
char* registro = calloc(tamRegistro+2, 1); // para computar tamanho do registro lido int tamRegLido; // arquivo a ser lido FILE* arq; // abre arquivo arq arq = fopen("teste.txt", "r"); if (!arq) { printf("*\n"); printf("* arquivo 'teste.txt' inexistente\n"); printf("*\n"); exit(1); } printf("*\n"); // loop de leitura dos registros for (;;) { // tenta ler um registro if (!fgets(registro, tamRegistro+2, arq)) { printf("*\n"); if (feof(arq)) printf("* fim de arquivo\n"); else printf("* erro na leitura\n"); break; // sai do while } // ok, leu um registro // computa o tamanho do registro lido tamRegLido = strlen(registro); if (tamRegLido < tamRegistro + 1) { printf("* ignorando registro com tamanho menor\n"); continue; // volta para inicio do while } if (registro[tamRegistro] != '\n') { printf("* ignorando registro com tamanho maior\n"); continue; // volta para inicio do while } // registro lido com tamanho correto // separa os campos memcpy(cpo1, registro, tamCpo1); memcpy(cpo2, registro+tamCpo1, tamCpo2); memcpy(cpo3, registro+tamCpo1+tamCpo2, tamCpo3); // mostra os campos1 lidos printf("* campo 1: [%s]\n", cpo1); printf("* campo 2: [%s]\n", cpo2); printf("* campo 3: [%s]\n", cpo3); printf("*\n"); } printf("*\n"); printf("* fim\n"); printf("*\n"); }
    
13.10.2018 / 23:20