C - How can I read data from a file (Considering that I use structures for it)

Asked

Viewed 3,318 times

3

Good night.

I’m working on a project for the College in C where I have a data structure to work with the data common to "Offenders," or those who committed an infraction.

typedef struct Infractores
{
    int ordemdeEntrada;//ordem de entrada da infração ... começa em 1 acaba em N
    char *marca;
    char *modelo;
    char *matricula;
    double valorportagem;
    int classeVeiculo;
    struct Infractores *seguinte;
};

If you’ve noticed I’m using pointers to *marca , *modelo ... and I have a struct Infractores *seguinte;. This happens because of having to implement lists in the project.

I happen to want to implement a method of reading the latest offenders from a file, for example those who committed offences yesterday. To achieve this I also developed a method:

void ListaInfractoresAnteriores(Infractores *f)
    {
        const char *filenameinfractors = "C:/Users/Vitor/documents/visual studio 2013/Projects/AED II/Resolucao_Teste/Projecto/VVManager/lastdayinfractors.txt";
        FILE *ficheiroInf = fopen(filenameinfractors, "r");
        //struct TesteInfractores auxiliar;
        struct Infractores *auxiliar;
        auxiliar = f;
        while (!feof(ficheiroInf))
        {

            if (fscanf(ficheiroInf, "%d %s %s %lf %d \n", &auxiliar->ordemdeEntrada, *auxiliar->marca, *auxiliar->modelo, &auxiliar->valorportagem, &auxiliar->classeVeiculo) != NULL)
            {
                printf("Marca %s",*auxiliar->marca);
            }


        }
    }

In this method I try to test on what if the input of mine fscanf() for <> (different) from NULL (Null), so he must write the mark, in this case the car, which committed the infringement.

I absolutely cannot read the file using this data structure. How can I read data from the file taking into account that did not want to use a new data structure? Do I have to create new variables?

Note: I intend to use the data structure to manipulate files and manipulate lists.

  • For what you want to do you need a data structure to read each line and store each line read in a different structure. Or create an array of structures. Second fscanf no.

  • Hi Vitor - I know it is not your question - but as it is a real case of data manipulation (and not a school porblema, as most questions in C) - I suggest you address your problem in a higher-level language than C. This is a typical system where your data could be in an SQL (or Nosql) database-and if you use Python, Java, Ruby or Javascript - you’ll have far less Boilerplate to use SQL, and life will be much quieter

  • If you want to go the way of trying to use another language there - write me that I can give a more extensive guidance (then we will document here in S.O. for the next ones if applicable). My email is in the profile.

  • Sorry - now that I’ve seen that it’s also a job for college. So, you probably don’t have an option to change language - and you’ll have to learn a lot to do it in C - pay attention to @Anthonyacioly’s comment in Rafael’s answer below.

  • I could even use a more advanced language, like java or C#, but the work is for Algorithms and it is recommended, here use structured languages, instead of object-oriented languages

  • I think it is good to study more the basic concepts of the language (blurring pointers to structures, return of function of the standard library, use of typedef etc), has many silly errors in this code, mistakes that whoever is trying to implement something more complex as a data structure should not make.

Show 1 more comment

2 answers

3


As you say you should implement chained lists, there is no way to avoid using pointers. Below I made an implementation that uses the list. It is still liable to amend the void ListaInfractoresAnteriores(Infractores * listaDeInfratores) so that you have the list of Offenders in the main function.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct infractores
{
    int ordemdeEntrada; //ordem de entrada da infração ... começa em 1 acaba em N
    char * marca;
    char * modelo;
    char * matricula;
    double valorportagem;
    int classeVeiculo;
    struct infractores * seguinte;

} Infractores;

Infractores * criaInfrator(int ordemDeEntrada, char * marca, char * modelo,
                           double valorportagem, int classeVeiculo){
    Infractores * f = (Infractores *) malloc (sizeof(Infractores));
    f->ordemdeEntrada = ordemDeEntrada;

    f->marca = malloc((strlen(marca)+1)*sizeof(char));
    strcpy(f->marca, marca);
    f->marca[strlen(marca)] = '\0';

    f->modelo = malloc((strlen(modelo)+1)*sizeof(char));
    strcpy(f->modelo, modelo);
    f->modelo[strlen(modelo)] = '\0';

    f->valorportagem = valorportagem;
    f->classeVeiculo = classeVeiculo;
    f->seguinte = NULL;

    return f;
}

void ListaInfractoresAnteriores(Infractores * listaDeInfratores){

    int i;
    int count = 0;

    FILE *fp;

    Infractores * p;

    int ordemEntrada, classeVeiculo;
    double valorPortagem;
    char marca[10], modelo[10];

    if((fp = fopen("lastdayinfractors.txt", "r")) != NULL){

        for(i = 0; !feof(fp); i++, count++)
        {
            fscanf(fp, "%d %s %s %lf %d\n",
                   &ordemEntrada, marca, modelo,
                   &valorPortagem, &classeVeiculo);

            if(i==0){
                p = criaInfrator( ordemEntrada, marca, modelo, valorPortagem, classeVeiculo);
                listaDeInfratores = p;
            }else{
                p->seguinte = criaInfrator( ordemEntrada, marca, modelo, valorPortagem, classeVeiculo);
                p = p->seguinte;
            }
        }

        p = listaDeInfratores;
        while(p!=NULL){
            printf("Marca: %s\n", p->marca);
            p=p->seguinte;
        }

        fclose(fp);
    }
    else
        puts("Não foi possível abrir o arquivo.");
}

int main(void)
{
    Infractores * listaDeInfratores;

    ListaInfractoresAnteriores(listaDeInfratores);

    return 0;
}
  • It is necessary to force or cast when this instruction : f->tag = malloc((strlen(tag)+1)*sizeof(char));

  • 1

    Of genus f->tag = (char*)malloc((strlen(brand)+1)*sizeof(char));

  • But thanks! @Sasha Nicolas

  • @VitorFerreira http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc

  • Why do you cast Infractores * f = (Infractores *) malloc (sizeof(Infractores));?

  • I do not know then what is happening with my IDE ... the visual studio gives me error if I do not make this small modification

Show 1 more comment

1

The easiest way is to create an array of structures, the hardest way would be to organize your own data structure. With array, simply to read and show I would:

#include <stdio.h> 

typedef struct infractores
{
   int ordemdeEntrada;
   char marca[20];
   char modelo[20];
   char matricula[20];
   double valorportagem;
   int classeVeiculo;
   struct infractores *seguinte;

} Infractores;

void ListaInfractoresAnteriores(Infractores f[]){

   int i;            /* índice dos arrays de struct */
   int n_linhas = 0; /* número linhas que serão lidas 
                        para uso no controle de exibição */

   FILE *fp;

   if((fp = fopen("problema.dat", "r")) != NULL){
      /* Percorre o arquivo até o fim incrementando o contador 
         do array struct e também o número de linhas */
       for(i = 0; !feof(fp); i++, n_linhas++)
       {
           fscanf(fp, "%d %s %s %lf %d\n", 
               &f[i].ordemdeEntrada, f[i].marca, f[i].modelo,
               &f[i].valorportagem, &f[i].classeVeiculo);   
       }
       /* Mostra até a última linha lida, que deve ter valor menor
          que a capacidade do array inserido. */
       for(i = 0; i < n_linhas; i++)
           printf("Marca: %s\n", f[i].marca);   

       fclose(fp);  
   }
   else
       puts("Não foi possível abrir o arquivo.");
}

/* Testando a função com um array de 50 structs */
int main(void)
{
   Infractores f[50];

   ListaInfractoresAnteriores(f);

   return 0;
}

In which I used a 2-line file for testing (remembering that the matrix used fits 50 structures):

10 Ferrari Bluhm 1.999 29
20 Fusca rafael 4.54 21

Exit

Marca: Ferrari
Marca: Fusca

Now, for dynamic uses of structures "loaded" by the file I recommend using a data structure of its own - including using this pointer that self-references the structure - instead of using arrays.

  • 1

    To complement, see that here Rafael is using vectors of 20 characters (char marca[20], etc) to store the strings. If you want dynamic sized strings you will need to use malloc / realloc (see example in Soen). Similarly Rafael is also using an array to store up to 50 offenders (Infractores f[50]), in your case you should use malloc to each offender / line and update the pointer seguinte.

  • 1

    And for a NULL at the end :)

  • Oi Rafael - has a question with your approach that you should explain in the text of the answer: you modified the structure of the OP so that the structure data was "inline" - of char * marca for char marca[20] - this is necessary yes, for it to work properly, since the 20 brand chars are in fact "inside"

  • I reiterate that it is the simplest way of doing it, and the answer is good - but it would be legsal to explain these things.

Browser other questions tagged

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