Psycop Posted April 7, 2012 Report Share Posted April 7, 2012 Boas Estou a tentar abrir um ficheiro txt que contem a seguinte informação: sessao 0 totais 0 Apenas é esta a informação que esta no ficheiro, o que acontece é que não estou a conseguir ler correctamente as strings sessão e totais. Estou a programar usando o codeblocks e Linux. Aqui fica o pedaço de código responsável pela leitura do ficheiro: printf("\t\t\t*Estatisticas Totais do Jogo*\n\n\n"); FILE *entrada; char tipo[100]; int valor; //Abrir o Ficheiro entrada = fopen("//home/nuno//Dropbox//Projectos em C//Jogo do Galo", "r"); if (entrada == NULL) { printf("Erro na Abretura do Ficheiro:\n"); getchar(); } while(entrada != EOF) { fscanf(entrada,"%s %d",tipo, &valor); printf("%s = %d\n", tipo, valor); break; } fclose(entrada); break; Não consigo entender onde está o erro uma vez que o output é o seguinte: (espaço que seria para a string ) = 0.Alguém sabe o que estou a fazer de mal? Cumps Link to comment Share on other sites More sharing options...
pmg Posted April 7, 2012 Report Share Posted April 7, 2012 entrada é um ponteiro; EOF é um inteiro: nao os podes comparar directamente. Sugestao: aumenta o nivel de warnings do teu compilador e faz compilacoes limpas, sem erros, claro! nem warnings. Outra coisa: o scanf é perigoso para buffer overflows. Para o tornares seguro limita o numero de caracteres a ler na especificacao do formato char tipo[100]; fscanf(entrada, "%99s %d", tipo, &valor); Verifica sempre o resultado do scanf! Com duas variaveis a atribuir o resultado devia ser 2; qulquer outra coisa é erro; if (fscanf(entrada, "%99s%d", tipo, &valor) != 2) /* erro no scanf */; Em vez de /* erro no scanf */ mostra uma mensagem e aborta ... Tirando isto parece-me que o programa devia funcionar. What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código! Link to comment Share on other sites More sharing options...
Psycop Posted April 7, 2012 Author Report Share Posted April 7, 2012 Olá Experimentei com as dicas que me indicaste e o retorno que tenho é um erro no fscanf, ou seja o fscan não está a ler os dois parâmetros. Agora assim: FILE *entrada; char tipo[100]; int valor; //Abrir o Ficheiro entrada = fopen("//home/nuno//Dropbox//Projectos em C//Jogo do Galo", "r"); if (entrada == NULL) { printf("Erro na Abretura do Ficheiro:\n"); getchar(); } while(fscanf(entrada,"%99s %d",tipo, &valor) != EOF) { if(fscanf(entrada,"%99s %d",tipo, &valor) != 2) { printf("Erro de Leitura"); break; } else { printf("%s = %d\n", tipo, valor); break; } } fclose(entrada); break; Ao compilar não tenho qualquer warning relativo a esta situação, mas continua a não aparecer a apresentação das palavras "sessão" e "totais". Não consigo mesmo entender o porque... Cumps Link to comment Share on other sites More sharing options...
bsccara Posted April 7, 2012 Report Share Posted April 7, 2012 Definição: Espaço branco = espaço, '\t' ou '\n'. Quando testas a condição no início do ciclo 'while' tentas ler do ficheiro até 99 caracteres ou até encontrar espaço branco, depois zero ou mais espaços brancos e depois um número inteiro. Tudo isso pode ser carregado. Mas uma linha de ficheiro de texto é terminada com um '\n' (em Linux). Quando tentas carregar a segunda linha o 'fscanf' vai encontrar isso e não os caracteres que espera e falha. Para resolver come o '\n' no fim de cada linha com: fscanf(entrada,"%99s %d ",tipo, &valor) ^------ Espaço aqui Link to comment Share on other sites More sharing options...
pmg Posted April 7, 2012 Report Share Posted April 7, 2012 Agora tens 2 fscanf seguidos (um no while, outro no if). Se o teu programa funcionasse so iria apresentar a linha com "totais 0"; a linha com "sessao 0" teria sido 'comida' no while. Verifica qual é o valor que o fscanf devolve ... while (1) { int chk = fscanf(entrada, "%99s%d", tipo, &valor); printf("o fscanf devolveu %d.\n", chk); /* ... break algures ... */ } fscanf(entrada,"%99s %d ",tipo, &valor) ^------ Espaço aqui No loop a seguir, o "%99s" 'come' os espacos que o teu espaço pretende comer. Ter, "%99s %d" e "%99s%d" é absolutamente igual: no primeiro caso os espaços sao ignorados por causa do espaço na string de conversao (e o "%d" começa logo com coisas diferentes de espaço); no segundo caso os espaços sao ignorados porque o "%d" ignora espaços. What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código! Link to comment Share on other sites More sharing options...
Psycop Posted April 7, 2012 Author Report Share Posted April 7, 2012 Correndo isto o printf devolve o valor "-1". Coisa que não esta dentro do ficheiro... Cumps Agora tens 2 fscanf seguidos (um no while, outro no if). Se o teu programa funcionasse so iria apresentar a linha com "totais 0"; a linha com "sessao 0" teria sido 'comida' no while. Verifica qual é o valor que o fscanf devolve ... while (1) { int chk = fscanf(entrada, "%99s%d", tipo, &valor); printf("o fscanf devolveu %d.\n", chk); /* ... break algures ... */ } Link to comment Share on other sites More sharing options...
bsccara Posted April 7, 2012 Report Share Posted April 7, 2012 No loop a seguir, o "%99s" 'come' os espacos que o teu espaço pretende comer. Tens razão, mas de qualquer maneira acho preferível consumir toda a linha de uma vez. Já agora, para referência futura e corrige-me se estiver enganado: todos os identificadores, com a excepção do '%c', ignoram espaço branco até que encontrem um caracter válido para eles. Só depois o espaço branco é considerado um terminador. Link to comment Share on other sites More sharing options...
pmg Posted April 7, 2012 Report Share Posted April 7, 2012 Correndo isto o printf devolve o valor "-1". Coisa que não esta dentro do ficheiro... O -1 é o sinal que o ficheiro nao tem mais dados (normalmente escreve-se EOF). É a unica maneira do scnaf devolver um numero negativo. Já agora, para referência futura e corrige-me se estiver enganado: todos os identificadores, com a excepção do '%c', ignoram espaço branco até que encontrem um caracter válido para eles. Só depois o espaço branco é considerado um terminador. um caracter válido ... on inválido. Se for válido o scanf faz a conversao; se for inválido ele pára deixando esse caracter 'pendurado'. Os conversores que nao ignoram espacos sao o "%c" e o "%[...]". What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código! Link to comment Share on other sites More sharing options...
bsccara Posted April 7, 2012 Report Share Posted April 7, 2012 Já agora, o ficheiro foi criado em Linux ou em Windows ? As linhas dos ficheiros criados em Linux terminam com '\n' mas os criados em Windows terminam com '\r' + '\n'. Sendo o teu programa compilado em Linux julgo que o fscanf não considera o '\r' como um espaço branco. Link to comment Share on other sites More sharing options...
pmg Posted April 7, 2012 Report Share Posted April 7, 2012 Um "espaço branco" é um dos caracteres para os quais a funcao isspace(), declarada em <ctype.h> devolve "TRUE". Normalmente, nos locales "C" ou "POSIX" esses caracteres sao '\f' (form-feed), '\n' (newline), '\r' (carriage return), '\t' (horizontal tab), e '\v' (vertical tab) e o espaco, claro. What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código! Link to comment Share on other sites More sharing options...
Psycop Posted April 7, 2012 Author Report Share Posted April 7, 2012 Boas Foi tudo criado em linux. O ficheiro foi com o gedit. Cumps Link to comment Share on other sites More sharing options...
Flinger Posted April 9, 2012 Report Share Posted April 9, 2012 sessao 0 está na primeira linha do ficheiro? se tiveres um \n pode estar a falhar devido a isso (embora eu ache que devia retornar 1). Para saber mais acerca do erro podes tentar algo como: while (1) { int chk = fscanf(entrada, "%99s%d", tipo, &valor); perror("resultado fscanf:"); printf("o fscanf devolveu %d.\n", chk); /* ... break algures ... */ } Link to comment Share on other sites More sharing options...
Psycop Posted April 10, 2012 Author Report Share Posted April 10, 2012 Boas Estou mesmo perdido com esta situação. Alterei o ficheiro para a seguinte forma só para testar: 0 Apenas o Zero na primeira linha do ficheiro, sem espaços antes, E usando este código: case 2: { printf("\t\t\t*Estatisticas Totais do Jogo*\n\n\n"); FILE *entrada; int sessao, totais; //Abrir o Ficheiro entrada = fopen("//home/nuno//Dropbox//Projectos em C//Jogo do Galo", "r"); if (entrada == NULL) { printf("Erro na Abretura do Ficheiro:\n"); getchar(); } while(!feof(entrada)) { fscanf(entrada,"%d",&sessao); printf("%d", sessao); break; } fclose(entrada); break; } Mesmo assim não consigo ler o conteúdo do ficheiro e apresenta-lo, tendo o 1 no ficheiro o que me é apresentado no programa é o valor zero. Link to comment Share on other sites More sharing options...
pmg Posted April 10, 2012 Report Share Posted April 10, 2012 FILE *entrada; //Abrir o Ficheiro entrada = fopen("//home/nuno//Dropbox//Projectos em C//Jogo do Galo", "r"); if (entrada == NULL) { printf("Erro na Abretura do Ficheiro:\n"); getchar(); } Tens a certeza que o nome esta bem? em vejo no meio do nome uma quebra de linha ... De qualquer maneira, se houver problemas na abertura do ficheiro o programa continua normalmente como se estivesse tudo bem. Experimenta sair do programa em vez de esperar por uma tecla. Ja agora podes tambem imprimir uma mensagem melhorzita, que explica qual o erro em vez de apenas dizer que houve erro if (entrada == NULL) { perror("entrada"); exit(EXIT_FAILURE); /* nao te esquecas de #include <stdlib.h> */ } while(!feof(entrada)) { fscanf(entrada,"%d",&sessao); printf("%d", sessao); break; } Verifica o valor devolvido pelo fscanf em vez de usares o feof(). O feof() serve para averiguar se o ultimo erro que ocorreu se deveu ao ficheiro ter chegado ao fim. Em particular, se nao tiver ocorrido um erro, o feof() devolve sempre falso. O fscanf verifica que houve erro antes. while (fscanf(entrada, "%d", &sessao) == 1) { /* ... */ } /* quando a execucao chega aqui, ocorreu um erro no fscanf(), ** se quiseres averiguar porque, podes usar o feof() */ fclose(entrada); What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código! Link to comment Share on other sites More sharing options...
Psycop Posted April 10, 2012 Author Report Share Posted April 10, 2012 Verifiquei a situação do nome e se retirar os espaços surge-me então a mensagem de erro na abertura do ficheiro e "Segmentation fault". Se voltar a colocar os espaços, não dá erro mas continua a retornar apenas o valor zero... Utilizando while (fscanf(entrada, "%d", &sessao) == 1) nem sequer é impresso qualquer valor no ecrã! Cumps Link to comment Share on other sites More sharing options...
pmg Posted April 10, 2012 Report Share Posted April 10, 2012 Olha ... mete o nome do ficheiro numa variavel, e imprime essa variavel antes de abrir o ficheiro. char nomeficheiro[] = "//home/bla bla bla/Jogo do Galo"; printf("A abrir o ficheiro '%s' ...\n", nomeficheiro); entrada = fopen(nomeficheiro, "r"); What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código! Link to comment Share on other sites More sharing options...
Psycop Posted April 10, 2012 Author Report Share Posted April 10, 2012 Implementando desta forma apena é impresso o nome do ficheiro, nada mais.... case 2: { printf("\t\t\t*Estatisticas Totais do Jogo*\n\n\n"); FILE *entrada; int sessao, totais; char nomeficheiro[] = "//home/nuno//Dropbox//Projectos em C//Jogo do Galo"; printf("A abrir o ficheiro '%s' ... \n", nomeficheiro); //Abrir o Ficheiro entrada = fopen(nomeficheiro, "r"); if (entrada == NULL) { printf("Erro na Abretura do Ficheiro:\n"); getchar(); } while(fscanf(entrada, "%d", &sessao) == 1) { printf("%d", sessao); break; } fclose(entrada); break; } Cumps Link to comment Share on other sites More sharing options...
pmg Posted April 10, 2012 Report Share Posted April 10, 2012 Eu estava a confundir as barras no nome do ficheiro com as barras ao contrario ... mas acho estranho estarem duas ou mais seguidas. Normalmente ve-se /home/nuno/Dropbox/Projects em C/etc :-) Verifica o conteudo do ficheiro com um examinador hexadecimal, por exemplo hd '/home/nuno/.../Jogo do Galo' Se nao tiveres um utilitario que funcione podes usar o teu proprio programa, mas le caracter a caracter (com fgetc()) em vez de usares scanf() int ch; fopen(); while ((ch = fgetc(entrada)) != EOF) { printf("valor lido: %d (caracter '%c')\n", ch, ch); } fclose(); What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código! Link to comment Share on other sites More sharing options...
Psycop Posted April 10, 2012 Author Report Share Posted April 10, 2012 As directorias só tem apenas uma \, mas o que aprendi e pelo que tenho lido colocam-se duas \\ devido a apenas representar um caracter. Quanto ao directorio retirei-o directamente das propriedades do ficheiro de texto. Não sei mesmo o que possa estar a acontecer... Link to comment Share on other sites More sharing options...
pmg Posted April 10, 2012 Report Share Posted April 10, 2012 A barra normal / usa-se em Unix. A barra invertida \ usa-se em Windows. Dentro do codigo fonte em C, dentro duma string literal, usa-se a barra invertida tambem para especificar "caracteres especiais", por exemplo o tab "\t". Para especificar um t a seguir a uma barra invertida tem-se de duplicar a barra invertida "\\t". A mesma logica aplica-se aos nomes de ficheiros. Mas, mesmo em Windows, o teu programa deve funcionar com barras normais nos nomes de ficheiros. As duas expressoes abaixo deviam funcionar exactamente da mesma forma fopen("C:/DOS/AUTOEXEC.BAT", "r") fopen("C:\\DOS\\AUTOEXEC.BAT", "r") /* hehe, o GeSHi atrapalha-se todo */ Se estas em Windows, provavelmente tens um BOM no ficheiro. What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now