Jump to content

Problema com abertura de ficheiro txt


Psycop
 Share

Recommended Posts

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

  • Replies 48
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

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

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

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

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

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

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

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

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

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

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

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

                            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

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

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

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

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

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

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

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.