Ir ao conteúdo
  • Cadastre-se

C como ler ficheiros em C


Posts recomendados

oii, gostaria que alguem ajudasse-me ,eu quero ler numeros grandes em ficheiros mas no codigo que eu tenho só me considera uma casa decimal, por exemplo tenho um ficheiro que lê um tabuleiro desta forma:

25 25 ->coordenada do vetor do tabuleiro

. 0 1 (o '.' representa a bomba e os numeros as coordenas x e y)

mas quando tenho essas coordenadas não me lê esses números porque não os considera

. 12 0

. 10 11

. 0 13

 

e outra coisa que eu quero fazer é se no ficheiro se tiver uma palavra escrita alem de coordenadas eu quero que dê uma mensagem de erro assim:

25 25

. 0 1

. 12 0

. 10 11

. 0 13

ola ->tem que dar mensagem de erro se tiver algum do genero

Link para o comentário
Compartilhar em outros sites

@arfneto eu ja fiz isso, eu vou mostrar o meu código

o que eu quero é fazer um campo minado e ler essas coordenadas pelo ficheiro criado ja esta feito ele imprime um tabuleiro com as coordenadas passadas ao ficheiro mas só que ele só escreve as coordenadas se elas forem de 0 a 9 se for de >10 não conta.

e a outra coisa que não estou a conseguir verificar é caso se dentro do ficheiro tiver algo escrito eu quero detetar isso e escrever uma mensagem de erro no ecra

#include <stdio.h>
int main ()
{
if(strcmp(texto, "read") == 0){ 
	scanf("%s", nome_do_ficheiro);
   	arq1 = fopen (nome_do_ficheiro, "r");
    if(arq1 == NULL)
  	{
       printf("Error opening file\n");
  	}
  	while(!feof(arq1))
    {
      strcpy(str, "\0");
      fgets(str, TAMANHO, arq1);
      if(!feof(arq1))
      {
        if(str[0] == '.' || str[0] == '*' )
        {                    
          count1linhas = 2;
          count2colunas=0;
          while(str[count1linhas] != ' ')
          {
            temp[count1linhas-2] = str[count1linhas];
            count1linhas++;
          }
          linha = atoi(temp);
          count1linhas++;

          while(str[count1linhas] != '\n')
          {
            tempcoluna[count2colunas] = str[count1linhas];
            count1linhas++;
            count2colunas++; 
          }
          coluna = atoi(tempcoluna);

          if(str[0] == '*')
          {
          	campominado[linha][coluna] = '*';

          }else if(str[0] == '.')
          {
          	campominado[linha][coluna] = '.';
          }          
       }
           count++;
     }

    }
                    
    fclose(arq1);
  
}

 

meu ficheiro de input

25  25
. 0 1
. 0 2
* 0 3
* 5 9
* 6 4
* 6 5
eojah (aqui eu quero poder mostrar uma mensagem de erro)
. 1 4
. 2 3
. 2 6
. 2 9
. 3 4
. 7 6
. 8 3
. 18 6
. 12 2
. 22 10
 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Não mudou muito em relação ao post anterior :(

 

Você quer dizer que você que ler uma linha com a dimensão do tabuleiro em linhas e colunas e depois uma série de dados em linhas, na forma letra linha coluna?

E letra pode ser um asterisco ou um ponto?

 

Seu programa parece muito complicado e incompleto. O que é ´texto´  por exemplo?

 

Se a sua entrada é formatada o caminho óbvio é usar fscanf() que foi escrita para isso --- f é de file scan é de scan e f é de formatted: fscanf().

 

Você tem um livro? um manual? 

 

teste o retorno de fgets() e fscanf() e saberá se leu algo...

 

Use funções.

 

Poste um programa completo

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@arfneto

o que eu quero é fazer isso

 

A leitura do ficheiro deverá ser realizada até detectar o fim do ficheiro.

Caso não seja possível abrir o ficheiro, o programa deverá imprimir a mensagem Error opening file e deverá voltar a esperar novo comando do utilizador.

Para cada bomba, deverá existir o estado, uma coordenada X e uma Y. Caso isso não se verifique, significa que o ficheiro está mal formatado. Nesse caso o programa deverá mostrar a mensagem File is corrupted e deverá voltar a esperar novo comando do utilizador. O caracter que separa o estado, a coordenada X e a coordenada Y poderá ser um espaço ou um tab, e todo o texto que apareça após a coodenada Y da bomba deverá ser simplesmente ignorado.

A mesma mensagem deverá ser mostrada caso alguma coordenada presente no ficheiro não seja válida (fora dos limites). Se isso acontecer, a leitura do ficheiro deverá terminar e o programa deverá voltar a esperar novo comando do utilizador.

Caso seja detectado algum erro no ficheiro, o mapa deverá ser limpo, eliminando todas as bombas que tiverem sido lidas até ao momento. ** Não é necessário guardar uma cópia do mapa existente. Se ocorrer um erro na leitura do ficheiro, o mapa deverá ficar limpo (sem bombas), independentemente de existirem bombas no mapa antes da leitura do ficheiro.

'.' significa bomba armada

'*' bomba desarmada

a variavel texto é uma das opções do programa 

2 horas atrás, catherineprokhorov disse:

@arfneto eu ja fiz isso, eu vou mostrar o meu código

o que eu quero é fazer um campo minado e ler essas coordenadas pelo ficheiro criado ja esta feito ele imprime um tabuleiro com as coordenadas passadas ao ficheiro mas só que ele só escreve as coordenadas se elas forem de 0 a 9 se for de >10 não conta.

e a outra coisa que não estou a conseguir verificar é caso se dentro do ficheiro tiver algo escrito eu quero detetar isso e escrever uma mensagem de erro no ecra



#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TAMANHO 6000
int main ()
{
  char texto[TAMANHO];
    char nome_do_ficheiro[TAMANHO], str[TAMANHO];
    FILE *arq2;
    char novo_ficheiro[TAMANHO];
    char campominado[25][25];
    int linha, coluna;
    int count=0;
    int count1linhas = 0;
    int count2colunas = 0;
    char temp [TAMANHO]; /*variavel temporaria*/
    char tempcoluna[TAMANHO];
    FILE *arq1;
    int x, y;

    printf("+-----------------------------------------------------\n");
    printf("read <filename>     - read input file\n"
    "show                - show the mine map\n"
    "trigger <x> <y>     - trigger mine at <x> <y>\n"
    "plant <x> <y>       - place armed mine at <x> <y>\n"
    "export <filename>   - save file with current map\n"
    "quit                - exit program\n" 
    "sos                 - show menu\n");
    printf("+-----------------------------------------------------\n");
if(strcmp(texto, "read") == 0){ 
	scanf("%s", nome_do_ficheiro);
   	arq1 = fopen (nome_do_ficheiro, "r");
    if(arq1 == NULL)
  	{
       printf("Error opening file\n");
  	}
  	while(!feof(arq1))
    {
      strcpy(str, "\0");
      fgets(str, TAMANHO, arq1);
      if(!feof(arq1))
      {
        if(str[0] == '.' || str[0] == '*' )
        {                    
          count1linhas = 2;
          count2colunas=0;
          while(str[count1linhas] != ' ')
          {
            temp[count1linhas-2] = str[count1linhas];
            count1linhas++;
          }
          linha = atoi(temp);
          count1linhas++;

          while(str[count1linhas] != '\n')
          {
            tempcoluna[count2colunas] = str[count1linhas];
            count1linhas++;
            count2colunas++; 
          }
          coluna = atoi(tempcoluna);

          if(str[0] == '*')
          {
          	campominado[linha][coluna] = '*';

          }else if(str[0] == '.')
          {
          	campominado[linha][coluna] = '.';
          }          
       }
           count++;
     }

    }
                    
    fclose(arq1);
  
}

 

meu ficheiro de in

Spoiler

 

put

25  25
. 0 1
. 0 2
* 0 3
* 5 9
* 6 4
* 6 5
eojah (aqui eu quero poder mostrar uma mensagem de erro)
. 1 4
. 2 3
. 2 6
. 2 9
. 3 4
. 7 6
. 8 3
. 18 6
. 12 2
. 22 10
 

 

Link para o comentário
Compartilhar em outros sites

Como cada linha tem um formato preciso parece conveniente usar fscanf() e simplesmente ler os valores usando uma máscara como 

    const char* mascara = "%s%d%d";

 

e funciona, claro. Só que 
 

22 horas atrás, catherineprokhorov disse:

e todo o texto que apareça após a coodenada Y da bomba deverá ser simplesmente ignorado.

 

com isso quer dizer que precisa ignorar texto que esteja à direita das coordenadas e fscanf() não funciona bem com campos opcionais. Você pode usar
 

    const char* mascara = "%s%d%d%*s";

 

Para ler uma letra, dois números, e ler e ignorar uma última string. Como um campo opcional. O asterisco em %*s diz pra ignorar o campo. Só que ela precisa estar lá pra ser ignorada. 

E assim daria problema quando a linha tiver apenas a bomba e as coordenadas, que é o caso normal

 

Para esse arquivo
 

25  25
. 0 1
* 6 5
eojah(aqui eu quero poder mostrar uma mensagem de erro)
. 18 6
* 22 10

 

Sai 

 

Campo em entrada "campo.txt"
Mapa com 25 linhas e 25 colunas
Linha: 2, bomba desarmada em (0,1)
Linha: 3, bomba armada em (6,5)
Linha: 4 (erro), bomba eojah(aqui
Linha: 5 (erro), bomba eu
Linha: 6 (erro), bomba quero
Linha: 7 (erro), bomba poder
Linha: 8 (erro), bomba mostrar
Linha: 9 (erro), bomba uma
Linha: 10 (erro), bomba mensagem
Linha: 11 (erro), bomba de
Linha: 12 (erro), bomba erro)
Linha: 13, bomba desarmada em (18,6)
Linha: 14, bomba armada em (22,10)

 

E lê todas as bombas ok, e a linha com erro gera várias saídas de erro...

 

Isso para esse programa
 

#define LIMITE_ 100

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

int main(int argc, char** argv)
{
    const char* e_padrao = "campo.txt"; // entrada padrão
    unsigned    limite = LIMITE_; // limite padrão
    char        arquivo_e[80];
    char        na_tela = 0;
    if (argc > 1) // saida: o padrão = a tela mesmo
        strcpy(arquivo_e, argv[1]);
    else
        strcpy(arquivo_e, e_padrao);

    fprintf(stderr, "Campo em entrada \"%s\"\n", arquivo_e);

    FILE* E = fopen(arquivo_e, "r");
    if (E == 0) return -1; // nao abriu entrada

    unsigned    colunas;
    unsigned    linhas;
    int         res;
    const char* estado[2] = { "armada", "desarmada" };
    // '*' desarmada '.' armada
    res = fscanf(E, "%d %d", &linhas, &colunas);
    if (res != 2) return -1;
    printf("Mapa com %d linhas e %d colunas\n", linhas, colunas);
    const char* mascara = "%s%d%d";
    char    bomba[80];
    int     l;
    int     c;
    unsigned saida = 2;
    while (!feof(E) && saida < limite)
    {
        res = fscanf(E, mascara, bomba, &l, &c );
        if (res == 3)
        {
            printf("Linha: %d, bomba %s em (%d,%d)\n",
                saida, estado[ bomba[0] == '.'], l, c);
        }
        else
        {
            printf("Linha: %d (erro), bomba %s\n",
                saida, bomba);
        }
        saida++;
    }
    fclose(E);
    return 0;
};  // main()

 

E podia ser pior se a linha com erros tivesse números e formato que pudesse ser confundindo com uma bomba...

 

Então é preciso ler o texto linha a linha e rodar scanf() dentro da linha pra ver se está bem formada. Uma função seria o caso aqui.

 

Esse trecho funciona

 

        char* ret = fgets(linha, 250,E);
        if (ret == NULL) return -2;
        res = sscanf(linha,mascara, bomba, &l, &c);
        if (res == 3)
        {
            printf("Linha %d: bomba %s em (%d,%d)\n",
                saida, estado[bomba[0] == '.'], l, c);
        }
        else
        {
            if ( (strlen(linha) > 0) && (linha[strlen(linha) - 1] == '\n')) 
                linha[strlen(linha) - 1] = 0;
            printf("Linha %d (erro): [\"%s\"]\n",
                saida, linha);
        }

 

porque a leitura é feita por linha então consome tudo que tem na linha, mesmo que venha algum texto depois das coordenadas...

 

Para esse arquivo
 

23  26 linhas e colunas
. 0 1 texto
* 6 5 depois
eojah(aqui eu quero poder mostrar uma mensagem de erro)
. 18 6 erro
*a 22 10

 

Essa é a saída
 

Campo em "campo.txt"
Mapa com 23 linhas e 26 colunas
Linha 2: bomba desarmada em (0,1)
Linha 3: bomba armada em (6,5)
Linha 4 (erro): ["eojah(aqui eu quero poder mostrar uma mensagem de erro)"]
Linha 5: bomba desarmada em (18,6)
Linha 6: bomba armada em (22,10)


Desse programa

 

#define LIMITE_ 100

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

int main(int argc, char** argv)
{
    const char* e_padrao = "campo.txt"; // entrada padrão
    unsigned    limite = LIMITE_; // limite padrão
    char        arquivo_e[80];
    char        na_tela = 0;
    char linha[256];
    if (argc > 1) // saida: o padrão = a tela mesmo
        strcpy(arquivo_e, argv[1]);
    else
        strcpy(arquivo_e, e_padrao);

    fprintf(stderr, "Campo em \"%s\"\n", arquivo_e);

    FILE* E = fopen(arquivo_e, "r");
    if (E == 0) return -1; // nao abriu entrada

    unsigned    colunas;
    unsigned    linhas;
    int         res;
    // '*' desarmada '.' armada
    const char* estado[2] = { "armada", "desarmada" };
    res = fscanf(E, "%d %d", &linhas, &colunas);
    fgets(linha, 256, E); // le o resto da linha
    if (res != 2)
    {
        printf("Error opening file\n");
        return -1;
    }
    printf("Mapa com %d linhas e %d colunas\n", linhas, colunas);
    const char* mascara = "%s%d%d";
    char    bomba[80];
    int     l;
    int     c;
    unsigned saida = 2;
    while (!feof(E) && saida < limite)
    {
        char* ret = fgets(linha, 250,E);
        if (ret == NULL) return -2;
        res = sscanf(linha,mascara, bomba, &l, &c);
        if (res == 3)
        {
            printf("Linha %d: bomba %s em (%d,%d)\n",
                saida, estado[bomba[0] == '.'], l, c);
        }
        else
        {
            if ( (strlen(linha) > 0) && (linha[strlen(linha) - 1] == '\n')) 
                linha[strlen(linha) - 1] = 0;
            printf("Linha %d (erro): [\"%s\"]\n",
                saida, linha);
        }
        saida++;
    }
    fclose(E);
    return 0;
};  // main()

 

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

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

×
×
  • Criar novo...