Ir ao conteúdo
  • Comunicados

    • Gabriel Torres

      Seja um moderador do Clube do Hardware!   12-02-2016

      Prezados membros do Clube do Hardware, Está aberto o processo de seleção de novos moderadores para diversos setores ou áreas do Clube do Hardware. Os requisitos são:   Pelo menos 500 posts e um ano de cadastro; Boa frequência de participação; Ser respeitoso, cordial e educado com os demais membros; Ter bom nível de português; Ter razoável conhecimento da área em que pretende atuar; Saber trabalhar em equipe (com os moderadores, coordenadores e administradores).   Os interessados deverão enviar uma mensagem privada para o usuário @Equipe Clube do Hardware com o título "Candidato a moderador". A mensagem deverá conter respostas às perguntas abaixo:   Qual o seu nome completo? Qual sua data de nascimento? Qual sua formação/profissão? Já atuou como moderador em algo outro fórum, se sim, qual? De forma sucinta, explique o porquê de querer ser moderador do fórum e conte-nos um pouco sobre você.   OBS: Não se trata de função remunerada. Todos que fazem parte do staff são voluntários.
    • DiF

      Poste seus códigos corretamente!   21-05-2016

      Prezados membros do Fórum do Clube do Hardware, O Fórum oferece um recurso chamado CODE, onde o ícone no painel do editor é  <>     O uso deste recurso é  imprescindível para uma melhor leitura, manter a organização, diferenciar de texto comum e principalmente evitar que os compiladores e IDEs acusem erro ao colar um código copiado daqui. Portanto convido-lhes para ler as instruções de como usar este recurso CODE neste tópico:  
Aislan Silva Costa

C Ordenar Matriz de Structs em C

Recommended Posts

Boas a todos!

 

Estou com um probleminha que não consigo resolver e busco ajuda dos membros. No meu código, leio o conteúdo de um arquivo e guardo em uma string para uso no código, no loop principal, recebo esta string e repasso para a chamada da função QuebrarStrungCompleta, para quebrar separar a string por "\n" e guardar em uma matriz de strings. Depois repassa cada linha dessa matriz para a chamada da função QuebrarStruct, que ira guardar numa struct a linha separada pelos delimitadores ",", vou fornecer o exemplo do arquivos users.txt, quem for testar, pode ver que até tudo funciona bem. O problema e que agora quero ordenar essa matriz de structs, nas pesquisas não achei muitos exemplos e procuro ajuda dos mais experientes.

 

O que tentei foi o seguinte: Crio a função de comparação que e repasssada para a chamada da função qsort:
 

int comparar(const void * a, const void * b)
{

  const Cliente * ia = (Cliente *) a;
  const Cliente * ib = (Cliente *) b;
  return strcmp(ia->cpf, ib->cpf);


}

Depois chama a função qsort, passo como base o ponteiro para minha matriz de structs, e também a função comparar:

qsort(&cliente, 4, sizeof(Cliente), comparar);

printf("As struct's foram ordenadas\n");


for (int i = 0; i < 4; i++)
{

printf("%s\n", cliente[i]->cpf);


}

Tudo compila, o código roda após a chamada da função qsort, porém da erro ao printar, eu Creio que o erro seja porque, qsort espera uma matriz do tipo;

exemplo: Cliente * cliente, e minha matriz e do tipo Cliente **cliente.

 

#include<stdio.h>

#include<stdlib.h>

#include<string.h>



typedef struct Cliente
 {
		
		char cpf[13];
		char realName[60];
		char sexo[11];
		char key[15];
		char data[11];

		
}Cliente;
        
  
       
        
        
        
   char **QuebrarStringCompleta(char *string)
   {
       
       char **linha;
       char *token;
       int tamVetor = 1;
       
       int i = 0;
       
       linha  = malloc(sizeof(char*)*tamVetor);

       linha[i] = malloc(sizeof(char**)*150);
       
       token = strtok(string, "\n");
       
       strcpy(linha[i], token);
       printf("primeira linha e: %s\n", linha[i]);
       
       i++;
       tamVetor++;
       
      
        while (token != NULL)
	 {
          linha = realloc(linha, sizeof(char*)*tamVetor);

          linha[i] = malloc(sizeof(char**)*150);
       
          token = strtok(NULL, "\n");

       
            if (token == NULL)
             {
               printf("token e nulo: %s, break\n", token);
                break;
             }      
            else
              {
                strcpy(linha[i], token);
                i++;       
                tamVetor++;
              }
            }

      return linha;
   }
        
        
        
      Cliente* QuebrarStruct( char *string)
{
	
        
	Cliente *cliente;
	char *token;
       
        cliente = malloc(sizeof(Cliente));
        token = strtok(string,",");
        strcpy(cliente->cpf, token);
	token = strtok(NULL,",");
        strcpy(cliente->realName, token);
	token = strtok(NULL,",");
        strcpy(cliente->sexo, token);
        token = strtok(NULL,",");
        strcpy(cliente->data, token);

	return cliente;
			
}
	
	  


char * ObterDados(int flag)
{
         
    

	FILE *users;	
        char url[] = "/bd/users/users/users.txt";		

if (flag == 1)
{	
	users = fopen(url, "r");

}

	char *string;
        char ch;
         int i = 0;
          int tamVetor = 0;
          
          string = malloc(sizeof (char * ) * tamVetor); 

	if (users == NULL)
	{
		printf("Erro na abertura do arquivo!");
		return 1;
	}
	else
	{
	
		 while ((ch = fgetc(users)) != EOF)
		{
			if (ch == '#')
			{

				while ((ch = fgetc(users)) != EOF)
				{


					string[i] = ch;
                                        
                                        i++;
					tamVetor++;

					string = realloc(string, sizeof(char *) * tamVetor);

                                        
                                        
                                }
                        }
                 }

                 
        }

                
                return string;
       
}


int comparar(const void * a, const void * b)
{

  const Cliente * ia = (Cliente *) a;
  const Cliente * ib = (Cliente *) b;
  return strcmp(ia->cpf, ib->cpf);


}

int main ()

{
    
char *string;
char **result;

string = ObterDados(1);


printf("String e %s: ", string);

result = QuebrarStringCompleta(string);



printf("As linhas separadas sao: ");

for(int i = 0; i < 5 ; i++)
{
 
    if(result[i] == NULL)
        break;
 printf("%s\n", result[i]);   

}



Cliente **cliente;

cliente= malloc(sizeof(Cliente)*5);




if (cliente == NULL) {
   printf ("Socorro! malloc devolveu NULL!\n");
   exit (EXIT_FAILURE);
}


for (int i = 0; i < 4; i++)
{
cliente[i] = QuebrarStruct(result[i]);

printf("Dados retornados e, usuario: %s, nome real: %s, sexo: %s, data: %s\n", cliente[i]->cpf,cliente[i]->realName, cliente[i]->sexo, cliente[i]->data);

}



qsort(&cliente, 4, sizeof(Cliente), comparar);

printf("As struct's foram ordenadas\n");


for (int i = 0; i < 4; i++)
{

printf("%s\n", cliente[i]->cpf);


}


}

Aguardo a ajuda de todos!

 

users.txt

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
Postado (editado)

@Aislan Silva Costa Olá. Tenta isso p ver se resolve:

qsort(cliente, 4, sizeof(cliente[0]), comparar); // aqui estão sendo comparados 4 cpfs

Se quer ordenar por nome:

int cmp(const void *a, const void *b) {
    return strcmp(((Cliente *)a)->realName, ((Cliente *)b)->realName);
}

Como não ficou clara qual é a sua dúvida, recomendo dar uma olhada nesse link e assistir a vídeo-aula:

https://programacaodescomplicada.wordpress.com/2014/06/09/ed1-aula-55-ordenacao-usando-a-funcao-qsort/

adicionado 11 minutos depois

Também gostaria de falar q é preciso liberar a memória que você está alocando. Em nenhuma parte do seu código você libera a memória alocada (!?). A função para liberar a memória alocada é a free

Outro ponto, até por boas práticas de programação: Toda vez que criar um ponteiro faça com q ele aponte para NULL (lugar nuenhum) e, assim q fizer uso do ponteiro, faça ele voltar a apontar p NULL. Com isso você evita q seu ponteiro seja um ponteiro solto, ou "ponteiro selvagem". Ex:

char *string = NULL;
char **result = NULL;

Exemplo p liberar a memória alocada e fazer o ponteiro voltar a apontar p NULL:

printf("As struct's foram ordenadas\n");

for (int i = 0; i < 4; i++) {
    printf("%s\n", cliente[i]->cpf);
}

free(cliente); // aqui libera memória q foi alocada para esse ponteiro
free(string);

string = NULL; // aqui faz o ponteiro voltar a apontar p NULL
result = NULL;

  // fim do main

Vê se é isso. Qualquer coisa é só pedir, ok?

adicionado 35 minutos depois

Obs: No final do seu código, no último for do main faça isso e vai ver q está ordenando corretamente:

for (int i = 0; i < 4; i++) {
    printf("%s\n", cliente[i]->realName);
}

 

Editado por giu_d
Correção no código

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Aislan Silva Costa Procure perceber o quanto é importante uma boa e adequada identação de um código.

Se quiser dá uma olhada nesse link:

https://www.tutorialspoint.com/online_c_formatter.htm

Caso não esteja mesmo disposto a usar uma boa identação nos seus códigos, faça uso da ferramenta do link acima q deixa seu código devidamente identado. ISSO VALE NOTA!!!

Veja seu código identado abaixo e perceba a diferença:

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

typedef struct Cliente
{
    char cpf[13];
    char realName[60];
    char sexo[11];
    char key[15];
    char data[11];
} Cliente;

char **QuebrarStringCompleta(char *string)
{
    char **linha = NULL;
    char *token = NULL;
    int tamVetor = 1;

    int i = 0;

    linha  = malloc(sizeof(char*)*tamVetor);

    linha[i] = malloc(sizeof(char**)*150);

    token = strtok(string, "\n");

    strcpy(linha[i], token);
    printf("primeira linha e: %s\n", linha[i]);

    i++;
    tamVetor++;

    while (token != NULL)
    {
        linha = realloc(linha, sizeof(char*)*tamVetor);

        linha[i] = malloc(sizeof(char**)*150);

        token = strtok(NULL, "\n");

        if (token == NULL)
        {
            printf("token e nulo: %s, break\n", token);
            break;
        }
        else
        {
            strcpy(linha[i], token);
            i++;
            tamVetor++;
        }
    }
    return linha;
}

Cliente* QuebrarStruct( char *string)
{
    Cliente *cliente = NULL;
    char *token = NULL;

    cliente = malloc(sizeof(Cliente));
    token = strtok(string,",");
    strcpy(cliente->cpf, token);
    token = strtok(NULL,",");
    strcpy(cliente->realName, token);
    token = strtok(NULL,",");
    strcpy(cliente->sexo, token);
    token = strtok(NULL,",");
    strcpy(cliente->data, token);

    return cliente;
}

char * ObterDados(int flag)
{
    FILE *users = NULL;
    char url[] = "users.txt";

    if (flag == 1)
    {
        users = fopen(url, "r");
    }

    char *string = NULL;
    char ch;
    int i = 0;
    int tamVetor = 0;

    string = malloc(sizeof (char * ) * tamVetor);

    if (users == NULL)
    {
        printf("Erro na abertura do arquivo!");
        return 0;
    }
    else
    {
        while ((ch = fgetc(users)) != EOF)
        {
            if (ch == '#')
            {
                while ((ch = fgetc(users)) != EOF)
                {
                    string[i] = ch;
                    i++;
                    tamVetor++;
                    string = realloc(string, sizeof(char *) * tamVetor);
                }
            }
        }
    }
    return string;
}


int comparar(const void * a, const void * b)
{
    const Cliente * ia = (Cliente *) a;
    const Cliente * ib = (Cliente *) b;
    return strcmp(ia->cpf, ib->cpf);
}

int cmp(const void *a, const void *b) {
    return strcmp(((Cliente *)a)->realName, ((Cliente *)b)->realName);
}

int main ()
{
    char *string = NULL;
    char **result = NULL;

    string = ObterDados(1);

    printf("String e %s: ", string);

    result = QuebrarStringCompleta(string);

    printf("As linhas separadas sao: ");

    for(int i = 0; i < 5 ; i++)
    {
        if(result[i] == NULL)
            break;
        printf("%s\n", result[i]);
    }

    Cliente **cliente = NULL;

    cliente= malloc(sizeof(Cliente)*5);

    if (cliente == NULL) {
        printf ("Socorro! malloc devolveu NULL!\n");
        exit (EXIT_FAILURE);
    }

    for (int i = 0; i < 10; i++)
    {
        cliente[i] = QuebrarStruct(result[i]);
        printf("Dados retornados e, usuario: %s, nome real: %s, sexo: %s, data: %s\n", cliente[i]->cpf, cliente[i]->realName, cliente[i]->sexo, cliente[i]->data);
    }

    qsort(cliente, 10, sizeof(cliente[0]), comparar);

    printf("As struct's foram ordenadas\n");

    for (int i = 0; i < 10; i++) {
        printf("%s\n", cliente[i]->realName);
    }

    free(cliente); // aqui libera memória q foi alocada para esse ponteiro
    free(string);

    string = NULL; // aqui faz o ponteiro voltar a apontar p NULL
    result = NULL;
}

Consegue ver como muda tudo em um código uma boa identação?

  • Obrigado 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário






Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações 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

×