BeDMK 0 Denunciar post Postado Junho 14, 2011 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
Renato Utsch 24 Denunciar post Postado Junho 14, 2011 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
Giovanni Ritchie 0 Denunciar post Postado Junho 14, 2011 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
BeDMK 0 Denunciar post Postado Junho 14, 2011 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
Renato Utsch 24 Denunciar post Postado Junho 14, 2011 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
BeDMK 0 Denunciar post Postado Junho 15, 2011 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
guidjos 65 Denunciar post Postado Junho 15, 2011 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
BeDMK 0 Denunciar post Postado Junho 15, 2011 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
guidjos 65 Denunciar post Postado Junho 17, 2011 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? Compartilhar este post Link para o post Compartilhar em outros sites
BeDMK 0 Denunciar post Postado Junho 17, 2011 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
BeDMK 0 Denunciar post Postado Junho 19, 2011 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
Giovanni Ritchie 0 Denunciar post Postado Junho 19, 2011 @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
BeDMK 0 Denunciar post Postado Junho 19, 2011 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