Ir ao conteúdo

C Implementar um algoritmo que leia um arquivo CSV e ordene primeira coluna


Ir à solução Resolvido por herbertbahia,

Posts recomendados

Postado

Estou muito perdido na hora de passar a struct para a ordenação do MERGE e imprimir os dados da struct de forma cresente da variavel ( int ideTipoEmpreendimentoOperacao ).

Gostaria de imprimir na tela o arquivo ordenado (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)...

Arquivo lido... DESORD_10POS_11LIN.csv 

ideTipoEmpreendimentoOperacao,nomTipoEmpreendimento,sigEmpreendimento,qtdEmpreendimento,mdaPotenciaInstaladakW,mesReferencia,anoReferencia,dthProcessamento
10,Central Geradora Hidrelétrica,CGH,0,0.00,12,2001,13/09/2017 00:00:00
9,Central Geradora Hidrelétrica,CGH,144,78400.00,12,2002,13/09/2017 00:00:00
8,Central Geradora Hidrelétrica,CGH,159,86510.00,12,2003,13/09/2017 00:00:00
7,Central Geradora Hidrelétrica,CGH,171,90050.00,12,2004,13/09/2017 00:00:00
6,Central Geradora Hidrelétrica,CGH,188,99300.00,12,2005,13/09/2017 00:00:00
5,Central Geradora Hidrelétrica,CGH,202,106772.00,12,2006,13/09/2017 00:00:00
4,Central Geradora Hidrelétrica,CGH,215,112258.00,12,2007,13/09/2017 00:00:00
3,Central Geradora Hidrelétrica,CGH,276,153400.00,12,2008,13/09/2017 00:00:00
2,Central Geradora Hidrelétrica,CGH,307,173400.00,12,2009,13/09/2017 00:00:00
1,Central Geradora Hidrelétrica,CGH,327,186120.00,12,2010,13/09/2017 00:00:00

Meu código... 

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

typedef struct TipoEmpreendimentoOperacao {
    int ideTipoEmpreendimentoOperacao;
    char nomTipoEmpreendimento[100];
    char sigEmpreendimento[10];
    int qtdEmpreendimento;
    float mdaPotenciaInstaladakW;
    int mesReferencia;
    int anoReferencia;
    char dthProcessamento[30];
};

struct TipoEmpreendimentoOperacao usinas[11];

int main(){
    setlocale(LC_ALL, "Portuguese");
  
    printf("Arqivo original\n");
    imprimir(usinas, tam);
    merge(usinas,0,tam-1);
    imprimir(usinas, tam);*/

    int tam = 11;
    FILE *arquivo = fopen("DESORD_10POS_11LIN.csv", "r");

    if (!arquivo) {
        printf("Não é possível abrir o arquivo\n");
        return 0;
    }
    
    char buf[1024];
    int cont_linhas = 0;
    int contador = 0, it = 0;
    char trans_arq[1024];

    while (fgets(buf, 1024, arquivo)) {
        contador = 0;
        cont_linhas++;

        if (cont_linhas == 1) {
            continue;
        }

        char *campo = strtok(buf, ",");
        while (campo) {

            if (contador == 0) {//int
                strcpy(trans_arq, campo);
                usinas[contador].ideTipoEmpreendimentoOperacao = atoi(trans_arq);
            }

            if (contador == 1) {//char
                strcpy(trans_arq, campo);
                strcpy(usinas[contador].nomTipoEmpreendimento, trans_arq);
            }

            if (contador == 2) {//char
                strcpy(trans_arq, campo);
                strcpy(usinas[contador].sigEmpreendimento, trans_arq);
            }

            if (contador == 3) {//int
                strcpy(trans_arq, campo);
                usinas[contador].qtdEmpreendimento = atoi(trans_arq);
            }

            if (contador == 4) {//float
                strcpy(trans_arq, campo);
                usinas[contador].mdaPotenciaInstaladakW = atof(trans_arq);
            }

            if (contador == 5) {//int
                strcpy(trans_arq, campo);
                usinas[contador].mesReferencia = atoi(trans_arq);
            }

            if (contador == 6) {//int
                strcpy(trans_arq, campo);
                usinas[contador].anoReferencia = atoi(trans_arq);
            }

            if (contador == 7) {//char
                strcpy(trans_arq, campo);
                strcpy(usinas[contador].dthProcessamento, trans_arq);
            }

            printf("Arqivo original\n");
            imprimir(usinas[contador].ideTipoEmpreendimentoOperacao, tam);
            merge(usinas[contador].ideTipoEmpreendimentoOperacao,0,tam-1);
            imprimir(usinas[contador].ideTipoEmpreendimentoOperacao, tam);

            campo = strtok(NULL, ",");//separa o texto a cada virgula

            contador++;
        }

    }


    fclose(arquivo);

    return 0;
}

void intercala(int *x, int inicio, int fim, int meio){
   int poslivre, inicio_v1, inicio_v2, i;
   int aux[fim];
   inicio_v1 = inicio;
   inicio_v2 = meio+1;
   poslivre = inicio;

   while (inicio_v1 <= meio && inicio_v2 <= fim){
        if (x[inicio_v1] <= x[inicio_v2]){
            aux[poslivre] = x[inicio_v1];
            inicio_v1 += 1;
        }else{
            aux[poslivre] = x[inicio_v2];
            inicio_v2 += 1;
        }
        poslivre++;
   }
   for (i = inicio_v1; i <= meio; i++){
        aux[poslivre] = x[i];
        poslivre++;
   }
   for (i = inicio_v2; i <= fim; i++){
        aux[poslivre] = x[i];
        poslivre++;
   }
   for (i = inicio; i <= fim; i++)
    x[i] = aux[i];

}

void merge(int *x, int inicio, int fim){
    int meio;
    if (inicio < fim){
        meio = (inicio+fim)/2;
        merge(x,inicio,meio);
        merge(x,meio+1, fim);
        intercala(x,inicio, fim, meio);
    }

}

void imprimir(int *x , int n){
    int i;
    for (i = 0; i < n; i++){
        printf("%d ", x[i]);
    }
    printf("\n");
}

 

Postado

@herbertbahia O arquivo CSV é o primeiro arquivo...

21 horas atrás, Aislan_R disse:

Arquivo lido... DESORD_10POS_11LIN.csv 

 

21 horas atrás, Aislan_R disse:

ideTipoEmpreendimentoOperacao,nomTipoEmpreendimento,sigEmpreendimento,qtdEmpreendimento,mdaPotenciaInstaladakW,mesReferencia,anoReferencia,dthProcessamento 10,Central Geradora Hidrelétrica,CGH,0,0.00,12,2001,13/09/2017 00:00:00 9,Central Geradora Hidrelétrica,CGH,144,78400.00,12,2002,13/09/2017 00:00:00 8,Central Geradora Hidrelétrica,CGH,159,86510.00,12,2003,13/09/2017 00:00:00 7,Central Geradora Hidrelétrica,CGH,171,90050.00,12,2004,13/09/2017 00:00:00 6,Central Geradora Hidrelétrica,CGH,188,99300.00,12,2005,13/09/2017 00:00:00 5,Central Geradora Hidrelétrica,CGH,202,106772.00,12,2006,13/09/2017 00:00:00 4,Central Geradora Hidrelétrica,CGH,215,112258.00,12,2007,13/09/2017 00:00:00 3,Central Geradora Hidrelétrica,CGH,276,153400.00,12,2008,13/09/2017 00:00:00 2,Central Geradora Hidrelétrica,CGH,307,173400.00,12,2009,13/09/2017 00:00:00 1,Central Geradora Hidrelétrica,CGH,327,186120.00,12,2010,13/09/2017 00:00:00

 

Postado
21 horas atrás, Aislan_R disse:

Estou muito perdido na hora de passar a struct para a ordenação do MERGE e imprimir os dados da struct de forma cresente da variavel ( int ideTipoEmpreendimentoOperacao ).

Gostaria de imprimir na tela o arquivo ordenado (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)...

 

Talvez tenha ido duas vezes por um caminho muito complicado.

 

A primeira vez

Foi na leitura. Para sua sorte não são 45 campos ,mas apenas 7 ;) strtok() não foi uma boa opção. csv é um arquivo formatado, muito bem definido. Deve ter imaginado quando escreveu aquilo que deveria ter outra maneira...

 

Registros e Campos
Na terminologia de scanf() e de banco de dados, cada linha é um registro e cada registro tem N campos, 7 no seu caso.

 O loop

O mais simples seria usar um loop de leitura até o fim do arquivo, e para cada registro lido --- linha --- criar um registro na estrutura e incrementar um contador. Só isso. um arquivo csv é uma tabela, uma matriz MxN de M campos com N colunas cada um. E scanf() foi escrita para consumir esse tipo de entrada. Seria bem mais fácil. Avise se quiser ver um exemplo.

 

A segunda vez
Foi o sort. Provavelmente não precisava incluir funções de sort. Podia usar muito bem o qsort() que já está em stdlib. 

Mas, imaginando que o sort que usou está ok para um vetor de int, sem problemas, sort é sort. Eis o que se faz nesses casos: cria um vetor de int com um int para cada linha que leu do csv. 1500 linhas, 1500 int. Aí você numera essas linhas de 0 a N-1. O óbvio. leu 10 registros, 0 a 9.

E chama o sort. Só que na função ou no momento de comparação do sort, ao invés de comparar o valor de int no vetor, tipo vetor[ i ], você compara as struct correspondentes.  E inverte os índices.

Nada original porque o sort() do C++ faz isso, o qsort() do C faz isso e praticamente todo algoritmo genérico de sort faz isso. 

Ao final do sort o vetor vai estar em ordem de seja lá qual for o campo que você escolheu do csv para ordenar. As vezes se usa isso para classificar por critérios externos à struct. Um exemplo: classificar um cadastro de pacotes a despachar pela posição em que o caminhão que cobre o destino de entrega estacionou nas bais do estacionamento.

 

E aí você usa o vetor classificado para imprimir os dados e tudo sai certinho. Sem por a mão no cadastro. E pode ter vetores distintos para listar por ano e mes de referencia, ou por potência instalada e tal... Espero que tenha entendido. É um conceito importante: usar o vetor como uma tabela de referência.

  • Curtir 1
Postado

@arfneto Olá, obrigado pela explicação, o strtok() foi o único jeito que eu achei na hora de fazer e armazenar os valores. Mas eu não tenho muita noção de como implementar isso que você falou da struct, e meu problema é ordenar a struct pela primeira coluna que seria o dado int ideTipoEmpreendimentoOperacao; da struct.

Em 20/06/2020 às 23:31, Aislan_R disse:

int ideTipoEmpreendimentoOperacao;

 

Postado

Você leu mesmo o que te expliquei antes? Era exatamente como fazer isso....

 

Exceto pela parte de NÃO usar strtok()...

 

Aquela parte que começa assim:
 

Citação

"Eis o que se faz nesses casos"...

 

Talvez possa ler de novo e me dizer se não entendeu ainda e tento explicar de outro modo.

 

Sobre o primeiro dos 2 problemas de que falei

 

Entendeu que um arquivo csv é uma tabela, imagino. Veja o seu arquivo importado para o Google Planilhas, por exemplo. com um click só:

csv.png.083baefac6acd1d8d3c7afad51e65187.png

 

É só isso. scanf() foi escrita por caras muito bons, muito bons mesmo, e para ler esse tipo de dado. Para você ver a diferença, pense assim: aí acima tem 10 linhas de dados e a primeira linha com os nomes dos campos, como é o padrão para csv. é uma tabela MxN coo eu falei. 8 campos e 11 linhas aqui. 

 

Planilhas foram a razão de pessoas comprarem computadores num primeiro momento: Visicalc foi a razão de alguém comprar um Apple II, por exemplo. Lotus 123 foi a razão de muitas empresas cogitarem de ter um PC.

 

De volta ao tópico:
 

Então MxN, 11 linhas, 8 campos = 88 campos. Então um programa que leia isso vai ler os 88 campos...
 

Veja essa listagem:

[  1,  0    1] 'ideTipoEmpreendimentoOperacao'
[  1,  1    2] 'nomTipoEmpreendimento'
[  1,  2    3] 'sigEmpreendimento'
[  1,  3    4] 'qtdEmpreendimento'
[  1,  4    5] 'mdaPotenciaInstaladakW'
[  1,  5    6] 'mesReferencia'
[  1,  6    7] 'anoReferencia'
[  1,  7    8] 'dthProcessamento'
[  2,  0    9] '10'
[  2,  1   10] 'Central Geradora Hidrelétrica'
[  2,  2   11] 'CGH'


...


[ 11,  6   87] '2010'
[ 11,  7   88] '13/09/2017 00:00:00'


Lidos 88 campos em 11 registros

Que "consome" o arquivo todo. 

 

Eis o programa que gerou isso

int main()
{
    //CSV_TEO usina[20];
    setlocale(LC_ALL, "Portuguese");
    char campo[80], delim[4];
    int  n = 0;
    int campos = 1;
    int registros = 1;
    FILE* ent = fopen("campos.csv", "r");
    while ((n = fscanf(ent, "%[^,\n]%c", campo, delim)) > 0)
    {
        printf("[%3d,%3d  %3d] '%s'\n", registros,
               ((campos-1)%8), campos, campo);
        campos += 1;
        if (delim[0] == 10) registros += 1;
    };   //while()
    printf("\n\nLidos %d campos em %d registros\n",
        campos-1, registros);
    fclose(ent);
    return 0;
};

Esse programa, que foi escrito em minutos, apenas lê direitinho TODOS os campos. Isso quer dizer que você pode importar os dados assim. Talvez seja interessante você ver a diferença entre usar strtok() que foi escrita com outro propósito, e scanf() como aqui... O programa tem só 8 instruções e já leu tudo certinho.

scanf() é para isso: scan formatted input.

 

Sobre o segundo dos 2 problemas de que falei: o sort

 

Sobre a classificação, o que eu te expliquei antes foi que você usa o seu sort em um vetor de int. Mas na hora de comparar usa o int para apontar para a struct. E no sort quanto precisa inverter inverte os índices no vetor, sem mexer na estrutura. 

É um conceito muito comum e muito poderoso. Look-up table.


Exemplo: ID, a coluna A no seu arquivo, as primeiras 4

 10
  9
  8
  7

 

Então você cria um vetor

 

int ref[4] = { 0,1,2,3 };


E classifica o vetor a partir dessas ID, que são 10, 9, 8 e 7. Vai ficar com 

 

ref = 3, 2, 1, 0

 

Se você escrever

    // imprime por ordem de entrada no arquivo
    for (int i = 0; i < 4; i += 1)
        printf("%d\n", usina[i].ideTipoEmpreendimentoOperacao);

vai imprimir na ordem em que leu do arquivo. 


Por outro lado, se imprimir assim:

    // imprime por ordem de ID
    for (int i = 0; i < 4; i += 1)
        printf("%d\n", usina[ref[i]].ideTipoEmpreendimentoOperacao);

vai mostrar classificado pela coluna A, como quer.

 

Apenas trocando [ i ]  por [ ref [ i ] ].

E pode ter um outro vetor que classifica por ano/mes de referencia, outro que classifica por Potência Instalada, tudo isso sem tocar no chato vetor de struct...

 

E pode usar o qsort() do C que é bem rápido e já tem onde inserir a função de comparação...

void qsort(
  void *endereco, 
  size_t itens, 
  size_t tamanho, 
  int (*comparador)(const void *, const void*)
);

 

 

  • Curtir 1
Postado

@arfneto Muito obrigado, porém a função qsort() não é o que eu preciso, pois tenho que implementar o MERGESORT. Mas no teu ultimo comentário entendi melhor.

Postado
5 minutos atrás, Aislan_R disse:

@arfneto Muito obrigado, porém a função qsort() não é o que eu preciso, pois tenho que implementar o MERGESORT. Mas no teu ultimo comentário entendi melhor.

 

O sort não faz diferença. Apenas entenda que tem separar e isolar a parte de comparação e inversão dos valores em algo bem separado, uma função talvez, como é feito no sort() da biblioteca

adicionado 4 minutos depois

Como muitos iniciantes tem dificuldade em receber e enviar funções como argumento de funções, achei que você poderia trocar pelo qsort(). Mas dá na mesma.

  • Curtir 1
Postado

@arfneto Estou lendo sobre essa função , achei muito boa, até entendendo ela em alguns exemplos além do que você colocou, para inserir ela no programa, porém ainda está meio complicado.

Postado
Em 22/06/2020 às 17:08, Aislan_R disse:

Estou lendo sobre essa função , achei muito boa, até entendendo ela em alguns exemplos além do que você colocou, para inserir ela no programa, porém ainda está meio complicado.

 

Continuo curioso por saber qual a função de que está falando :) 

fez progressos?

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...