Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

BeDMK

Separar informações de string

Recommended Posts

Gostaria de saber como ler um arquivo e separar as informações da string de cada linha.

O arquivo a ser lido é o seguinte:

Corsa Sedan,506672,2700,1.7,2.6,1.6
Gol,402089,2300,1.7,2.2,1.6
Fiorino,307732,3100,2.1,2.8,1.7
EcoSport,204088,3500,2.2,3.0,1.8
Celta,503343,1800,1.7,2.1,1.6
Fusca,105666,2500,1.8,2.3,1.7
Yamaha R1,907523,211,1.3,1.8,0.9
Honda XRE300,902254,156,1.5,1.9,0.9
Uno,502112,1500,1.7,2,1.6
Fiesta Sedan,504356,2650,1.7,2.5,1.6
Kombi,886677,3800,2.2,3.2,1.8
Topic,804321,4000,2.3,3.3,1.8
Golf,669876,2200,1.7,2.3,1.8

 

Como posso "recortar" a string a cada vírgula encontrada e passar para as variáveis da struct através de vetores?

 

Por exemplo:

 

Corsa Sedan,506672,2700,1.7,2.6,1.6

Corsa Sedan = modelo

506672 = chassi

2700 = peso

1.7 = altura

2.6 = comprimento

1.6 = largura

 

O mesmo vale para um arquivo vagas.txt a ser lido.

 

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

struct veiculos {
       char  modelo[30];
       char  chassi[30];
       float peso;
       float altura;
       float comprimento; 
       float largura;
       } CARROS;

struct vagas {
       int   ident;
       float peso_max;
       float altura_max;
       float comprimento_max;
       float largura_max;
       } VAGAS;

char strMenuPrincipal[] =
"\nDigite uma das opcoes abaixo:\n"
"\n1 - Cadastrar novo veiculo\n"
"2 - Registrar entrada de um veiculo\n"
"3 - Registrar saida de um veiculo\n"
"4 - Listar vagas ocupadas\n"
"5 - Consultar vagas\n"
"0 - Sair do programa\n"
"=> ";
/* ******************************************************************************************
* Funcao do programa principal
* ******************************************************************************************/
int main() {
       int opt;
       //struct veiculos();
       FILE* P;
       P=fopen("veiculos.txt", "r");
       // E AGORA, O QUE FAZER?

       puts("\nMENU PRINCIPAL");
       puts("Bem vindo ao sistema para controle de estacionamento");
       while (1){ //Loop infinito para controlar programa principal
               printf(strMenuPrincipal);

               scanf("%d",&opt);
               switch (opt) {
                       case 0:
                               return 0; // Sai do programa
                               break;
                       case 1:
                               //cadastro_veiculo(NULL,NULL);
                               break;
                       case 2:
                               //registrar_entrada_veiculo();
                               break;
                       case 3:
                               //registrar_saida_veiculo();
                               break;
                       case 4:
                               //listar_vagas_ocupadas();
                               break;
                       case 5:
                               //consultar_vagas();
                               break;
                       default:
                               puts("Opcaoo invalida!");
                               break;
               }
       }
}

 

Obrigado!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá!

 

use getc() com o parâmetro de stream do arquivo.

 

Vá pegando caracteres com um while até encontrar uma vírgula.

 

FILE *FILESTREAM;

while(FILESTREAM != EOF) {
   while( ( ch = getc(FILESTREAM) ) != ',' ) {
       /* Adicionar caracter à string. */
   }

   /* Iniciar a próxima string, já que encontrou uma vírgula. */
}

/* Acabou de ler o arquivo. */

 

Eu não sei se pode usar o FILESTREAM != EOF, mas se não estou enganado dá sim.

 

 

Aí você pode ler o arquivo, separando em strings ao encontrar uma vírgula.

 

 

Abraços :D

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ola o q você precisa eh percorrer cada linha e ir verificando se ja alcançou delimitador, enquanto n encontrar o delimitador( no teu caso a virgula ) você guarda o caracter e quando encontrar você acabou de formar um token(palavra).. assim sucessivamente ateh chegar ao final da linha.. Criei uma funcao q você pode usar pra o seu problema, aproveita estuda-la e adapte pra si...

/*
*@Author: Giovanni Lima
*@Created-At: 10 - Jundo de 2011
*@Last-Modif: 10 - Junho de 2011
*@Description: funcao que permite separar uma string em tokens delimitados pelo caracter definido no parametro delimiter
*@Params: -content => a string que será fatiada em tokens ; -point => o token encontrado; -delimiter => delimitador dos tokens
*@Return: retorna 1 enquanto exitir tokens disponiveis e 0 quando atingir o final  
*/
char tokenBuffer[1000];
int nextToken(char *content, char **point, char delimiter) {
static int lastIndex;
int tokenSize  = 0;
tokenBuffer[tokenSize++] = *(content + lastIndex); 
while(*(content + (++lastIndex)) != '\0') {
	if(*(content + (lastIndex)) == delimiter) {
		tokenBuffer[tokenSize] = '\0';
		*point = tokenBuffer;
		++lastIndex; // aponta para o proximo caracter depois do espaco em branco
		return 1;
	}

	tokenBuffer[tokenSize++] = *(content + lastIndex); 
}
return 0;
}



// abaixo montei um exemplo para ver como podia usa-la

#include <stdio.h>

int main (int argc, char const *argv[]) {
char *token;
while(nextToken("giovanni-lazaro-dos-santos-lima", &token, '-')) {
	printf("%s\n", token); 
}
return 0;
}

 

o programa acima imprime:
giovanni
lazaro
dos
santos
lima

 

 

Em vez de imprimir na tela podia pegar o conteudo de token e setar na struct ou onde desejar...

Abraco, qualquer duvida falae

Compartilhar este post


Link para o post
Compartilhar em outros sites

Renato, já tinha pensado nessa solução mas dá erro ao compilar (ISO C++ forbids comparison between pointer and integer).

Giovanni, também já tinha visto algo parecido, mas como passar a função para tratar com arquivo?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá!

 

Erros de compilação se resolvem. Qual erro, exatamente, você teve? Você usa o GCC (mingw32 é GCC)

 

 

Eu tenho um outro modo aqui, mas tenho tentado não carregar o arquivo na memória, pois isso deixa o programa meio pesado. Ir lendo o arquivo caracter por caracter é muito mais leve e rápido.

 

Abraços :D

Compartilhar este post


Link para o post
Compartilhar em outros sites

A questão é que eu sou obrigado a utilizar arquivos. Não tenho opção!

Gostaria de saber como converter a função Token que funciona só com strings para lidar com arquivos também.

Compartilhar este post


Link para o post
Compartilhar em outros sites

A função responsável por quebrar strings não deve ser influenciada pela origem delas. Ela não deve ser responsável pela leitura das strings:

 

enquanto houver linhas de entrada
{
   ler linha;
   dados = separar linha; // equivalente à "Token" que você citou
   manipular dados;
}

 

 

Minha biblioteca possui a seguinte função que pode ser útil pra você:

 

char **rp_tokenize(char *target, char *separators)
{
   // worst-case scenario, so we don't have to check on every entry whether we have space
   register int addresses 	= strlen(target) / 2;

   register int i 		= 0;

   register char *current	= NULL, 
               *str 	= target, 
               *seps 	= separators,
               **ret 	= rp_malloc(addresses * sizeof (char *), NULL, NULL);	

   // we're always splitting on the same separators
   for (current = strtok(str, seps); current; current = strtok(NULL, seps), i++)
       ret[i] = current;

   // sinalize the end of the tokens
   ret[i] = NULL;

   // shrink to optimize memory usage
   ret = rp_realloc(ret, (i + 1) * sizeof (char *), NULL, NULL);

   return ret;
}

 

Dada uma string e um conjunto de separadores (cada um de tipo char), ela retorna o primeiro endereço de um vetor de ponteiros para char, cada um apontando para o primeiro elemento de strings formados pela separação da string original em fragmentos divididos pelo separador. O último elemento deste vetor tem valor NULL. O separador não é incluído nas strings resultantes.

 

Você pode adaptar minha função para torná-la independente das rotinas rp_realloc e rp_malloc. Neste caso, você precisará fazer checagem de erros - minha biblioteca os faz automaticamente.

 

Tenha em mente, quando estiver adaptando minha função, que o seguinte código é inseguro:

 

char *p = malloc( ... );
p = realloc(p, ...);

 

Se realloc retornar NULL, você perde todos os dados e há vazamento de memórias. A forma mais simples de tratamento deste erro é:

 

char *p = malloc( ... );

char *temp = realloc(p, ...);

if (temp)
   p = temp;
else
   // tratar erros

 

Sugiro que faça o mesmo tipo de teste com malloc.

 

 

@Giovanni

 

Sugiro que use a função strtok. Ela implementa a mesma funcionalidade da sua rotina e faz parte da biblioteca padrão. Isso significa que sempre será otimizada para a implementação em questão.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Consegui separar os dados a cada vírgula encontrada:

 

void ler_veiculos() {
    char arquivo1[] = "veiculos.txt"; // Nome do arquivo a ser lido
    FILE *veiculos = fopen(arquivo1, "r"); // Abre o arquivo
    if(veiculos == NULL)
         printf("Erro ao abrir arquivo ou arquivo vazio!");
    else {
         char linha[50]; // Espaço para ler a linha
         int k = 0;
         while (fgets(linha,sizeof linha,veiculos)) { // Lê cada linha
               int i;
               char *token = linha; // Ponteiro para o início da linha
               printf("\nLinha %d:\n", ++k);
               for ( i = 0; *token; ++i ) { // Loop para cada caracter da linha
                     size_t len = strcspn(token, ",\n"); // Procura pela vírgula
                     printf("Campo[%d] = \"%*.*s\"\n", i, len, len, token);
                     token += len + 1; // Vai para a próxima linha
               }
         }
    fclose(veiculos);
    }
}

 

Entrada (veiculos.txt):

 

Corsa Sedan,506672,2700,1.7,2.6,1.6
Gol,402089,2300,1.7,2.2,1.6

 

Saída:

 

Linha 1:
Campo[0] = "Corsa Sedan"
Campo[1] = "506672"
Campo[2] = "2700"
Campo[3] = "1.7"
Campo[4] = "2.6"
Campo[5] = "1.6"

Linha 2:
Campo[0] = "Gol"
Campo[1] = "402089"
Campo[2] = "2300"
Campo[3] = "1.7"
Campo[4] = "2.2"
Campo[5] = "1.6"

 

Agora a questão é jogar esses vetores para a struct:

 

struct veiculos {
       char  modelo[30];
       char  chassi[30];
       float peso;
       float altura;
       float comprimento; 
       float largura;
       } CARROS;

 

Dessa forma:

 

Campo[0] = modelo;
Campo[1] = chassi;
Campo[2] = peso;
Campo[3] = altura;
Campo[4] = "comprimento;
Campo[5] = largura

 

Como posso fazer isso?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Passaram-se quatro dias. Desde a minha sugestão, que é ajuda suficiente pra que você resolva o problema, passaram-se dois.

 

Qual sua dúvida sobre as sugestões que demos?

Eu nunca lidei com esse tipo de funções.

Só gostaria de saber como jogar o token da função para dentro da struct.

Fiz o seguinte mas imprimiu a linha toda e não apenas o modelo como eu gostaria:

 

void ler_veiculos() {
    struct veiculos veic[100];
    char arquivo[] = "veiculos.txt"; // Nome do arquivo a ser lido
    FILE *veiculos = fopen(arquivo, "r"); // Abre o arquivo
    if(veiculos == NULL)
         printf("Erro ao abrir arquivo ou arquivo vazio!");
    else {
         char linha[50]; // Espaço para ler a linha
         int aux = 0;
         while (fgets(linha,sizeof linha,veiculos)) { // Lê cada linha
               int i;
               char *token = linha; // Ponteiro para o início da linha
               printf("\nLinha %d:\n", ++aux);
               for (i=0; *token; ++i ) { // Loop para cada caracter da linha
                     int len = strcspn(token, ",\n"); // Procura pela vírgula
                     //printf("Campo[%d] = \"%*.*s\"\n", i, len, len, token);
                     strcpy(veic[i].modelo,token);
                     printf("Teste: %s", veic[i].modelo);
                     token += len + 1; // Vai para a próxima linha
               }
         }
    fclose(veiculos);
    }
}

Creio que seja coisa simples:

Campo[0] vai para modelo

Campo[1] vai para chassi

(...)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Consegui de outra forma:

void ler_veiculos() {

    char string[50]; // string armazenará a linha
    char virgula[] = ","; // Caracter delimitador
    char *info; // Ponteiro para armazenar as informações

    FILE *arq_veic;
    arq_veic = fopen("veiculos.txt","r"); // Abre o arquivo
    testaArq(arq_veic); // Chama função para testar o arquivo

    printf("\n############################################################################"
           "################################# Ve%cculos em espera ########################"
           "#######################################################################################", 161);

    while(fgets(string,sizeof(string)-1,arq_veic) != NULL) { // Loop para ler cada linha do arquivo enquanto houver linhas

        info = string; // info recebe a linha inteira
        info = strtok(string,virgula); // info recebe a primeira string antes da primeira vírgula da primeira linha

        while(info != NULL) { // Enquanto houver linhas no arquivo

            strcpy(CARROS.modelo,info); // Copia info para modelo
            printf("\n\nModelo: %s", CARROS.modelo);

            info = strtok(NULL,virgula); // Separa o chassi da string
            CARROS.chassi=atoi(info); // Copia info para chassi
            printf("\nChassi: %d", CARROS.chassi);

            info = strtok(NULL,virgula); // Separa o peso da string
            CARROS.peso=atof(info); // Copia info para peso
            printf("\nPeso: %.0f", CARROS.peso);

            info = strtok(NULL,virgula); // Separa a altura da string
            CARROS.altura=atof(info); // Copia info para altura
            printf("\nAltura: %.1f", CARROS.altura);

            info = strtok(NULL,virgula); // Separa o comprimento da string
            CARROS.comprimento=atof(info); // Copia info para comprimento
            printf("\nComprimento: %.1f", CARROS.comprimento);

            info = strtok(NULL,virgula); // Separa a largura da string
            CARROS.largura=atof(info); // Copia info para largura
            printf("\nLargura: %.1f", CARROS.largura);

            info = strtok(NULL,virgula); // Separa o modelo da string

        }
    }    
    fclose(arq_veic);     
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

@guidjos Sua Biblioteca eh bastante interessante!!! (Fussando ja kkk)

 

Soh uma obs ao usar strtok: ela altera o "string" passado como argumento. Por isso se for usar faca uma copia. Ou se for um caso trivial use o meu procedimento :)

 

Abraco

Compartilhar este post


Link para o post
Compartilhar em outros sites

Quero armazenar o conteúdo das informações "recortadas" em um array de estruturas.

O código abaixo compila e imprime o resultado correto na tela, mas na função main imprime lixo.

 

Não sei se estou fazendo certo...

 

 

 

typedef struct veiculos {
       char  modelo[TAM];
       int   chassi;
       float peso;
       float altura;
       float comprimento; 
       float largura;
       } CARROS;

CARROS model[TAM], chasi[TAM], pes[TAM], altu[TAM], comprim[TAM], larg[TAM];


void ler_veiculos() {

    char string[50]; // string armazenará a linha
    char virgula[] = ","; // Caracter delimitador
    char *info; // Ponteiro para armazenar as informações
    int i;
    FILE *arq_veic;
    arq_veic = fopen("veiculos.txt","r"); // Abre o arquivo
    testaArq(arq_veic); // Chama função para testar o arquivo

    printf("#######################################################################################"
           "################################### VE%CCULOS EM ESPERA ###############################"
           "########################################################################################\n", 214);
    printf("      MODELO      CHASSI        PESO      ALTURA     COMPRIMENTO     LARGURA\n");

    while(fgets(string,sizeof(string)-1,arq_veic) != NULL) { // Loop para ler cada linha do arquivo enquanto houver linhas

        info = string; // info recebe a linha inteira
        info = strtok(string,virgula); // info recebe a primeira string antes da primeira vírgula da primeira linha

        while(info != NULL) { // Enquanto houver linhas no arquivo
            for(i=0; i<1; i++) {
                strcpy(model[i].modelo,info); // Copia info para modelo
                printf("\n%12s", model[i].modelo);
            }

            for(i=0; i<1; i++) {
                     info = strtok(NULL,virgula); // Separa o chassi da string
                     //CARROS.chassi=atoi(info); // Copia info para chassi
                     //printf("%12d", CARROS.chassi);
                     chasi[i].chassi=atoi(info);
                     printf("%12d", chasi[i].chassi);
                     }

            for(i=0; i<1; i++) {
                     info = strtok(NULL,virgula); // Separa o peso da string
                     pes[i].peso=atof(info);
                     printf("%12.0f", pes[i].peso);
                     //CARROS.peso=atof(info); // Copia info para peso
                     //printf("%12.0f", CARROS.peso);
            }

            for(i=0; i<1; i++) {
                     info = strtok(NULL,virgula); // Separa a altura da string
                     altu[i].altura=atof(info);
                     printf("%12.1f", altu[i].altura);
                     //CARROS.altura=atof(info); // Copia info para altura
                     //printf("%12.1f", CARROS.altura);
            }

            for(i=0; i<1; i++) {
                     info = strtok(NULL,virgula); // Separa o comprimento da string
                     comprim[i].comprimento=atof(info);
                     printf("%16.1f", comprim[i].comprimento);
                     //CARROS.comprimento=atof(info); // Copia info para comprimento
                     //printf("%16.1f", CARROS.comprimento);
            }

            for(i=0; i<1; i++) {
                     info = strtok(NULL,virgula); // Separa a largura da string
                     larg[i].largura=atof(info);
                     printf("%12.1f", larg[i].largura);
                     //CARROS.largura=atof(info); // Copia info para largura
                     //printf("%12.1f", CARROS.largura);
            }

            info = strtok(NULL,virgula); // Separa o modelo da string

        }
    } 
    fclose(arq_veic);     
}

 

Como faço para acessar os dados armazenados no array? E imprimi-los fora da função?

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.