Jump to content
SirDave

Ler mapa em ficheiro de texto para array bi-dimensional

Recommended Posts

SirDave

Olá pessoal,

Eu não customo fazer perguntas aqui no fórum, mas agora estou com uma dúvida.

1111111111111111111111111
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1111111111111111111111111

Tenho um ficheiro de texto como o de cima, com 1's e 0's. E preciso de o ler para uma array de integers.

int map[26][24];
int map_width = 26;
int map_height = 24;
int x;
int y;
FILE *map_file = fopen("map.txt", "r");
for (x = 0; x < map_width; x++)
{
  for (y = 0; y map_height; y++)
  {
     fscanf(map_file, "%d", &map[x][y]);
  }
  fscanf(map_file, "\n"); // Skip newlines
}

Esse é o código que já fiz, mas não me parece estar a dar, porque eu a seguir estou a imprimir a array e não me dá o que está no ficheiro:

for (x = 0; x < map_width; x++)
{
  for (y = 0; y < map_height; y++)
  {
    printf("%d", map[x][y]);
  }
  printf("\n");
}

Este é o código para imprimir a array toda bonitinha ^.

O que estarei a fazer mal? Obrigado.


Be nice to see your eyes, blink them from time to time to relax your retina when using the computer. Blink now!

Share this post


Link to post
Share on other sites
pmg

O fscanf está a ler-te um inteiro ("%d").

Supondo que os teus inteiros têem 32 bits, cada linha acima resulta em cada map[ x ][ y ] ficar com o valor 2147483647.

Aconselho-te a verificar o valor de retorno do fscanf ...

    // fscanf(map_file , "%d", &map[x][y]);
    if (fscanf(map_file , "%d", &map[x][y]) != 1) {
        fprintf(stderr, "Erro de leitura para o elemento (%d, %d)\n", x, y);
        exit(EXIT_FAILURE);
    }

Para meteres cada '0' ou '1' no array, tens duas hipóteses

a) les caracter a caracter com fgetc() e ignoras tudo o que não é '0' ou '1'

:P limitas a scanf() a um digito, com "%1d"


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!

Share this post


Link to post
Share on other sites
SirDave

"Limitas a scanf() a um dígito". A scanf ou a fscanf?

int map[26][24];
int map_width = 26;
int map_height = 24;
int x;
int y;
FILE *map_file = fopen("map.txt", "r");
for (x = 0; x < map_width; x++)
{
  for (y = 0; y < map_height; y++)
  {
    fscanf(map_file, "%1d", &map[x][y]);
  }
  fscanf(map_file, "\n"); // Skip newlines
}

Tenho este código agora. Mudou um bocado, mas ainda não lê bem o ficheiro. Devia ser um quadrado com 1's na borda e 0's no meio:

111111111111111111111111
110000000000000000000000
011000000000000000000000
001100000000000000000000
000110000000000000000000
000011000000000000000000
000001100000000000000000
000000110000000000000000
000000011000000000000000
000000001100000000000000
000000000110000000000000
000000000011000000000000
000000000001100000000000
000000000000110000000000
000000000000011000000000
000000000000001100000000
000000000000000110000000
000000000000000011000000
000000000000000001100000
000000000000000000110000
000000000000000000011000
000000000000000000001100
000000000000000000000110
000000000000000000000011
111111111111111111111111
00-103479296032718-104476916032718-103478886432718-10530380163271810304000-103461526432718-1100-10347929603271841960900


Be nice to see your eyes, blink them from time to time to relax your retina when using the computer. Blink now!

Share this post


Link to post
Share on other sites
pmg

"Limitas a scanf() a um dígito". A scanf ou a fscanf?

A fscanf() ... mas quando eu digo scanf(), em principio, refiro-me à familia completa (o mesmo para printf)

Quanto a ainda não ler bem, parece-me que estás a ler 26 linhas de 24 valores, mas cada linha do ficheiro original tem 25 valores ...


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!

Share this post


Link to post
Share on other sites
SirDave

A fscanf() ... mas quando eu digo scanf(), em principio, refiro-me à familia completa (o mesmo para printf)

Quanto a ainda não ler bem, parece-me que estás a ler 26 linhas de 24 valores, mas cada linha do ficheiro original tem 25 valores ...

Bem reparado. Fui ao ficheiro e mudei, mas agora dá-me isto:

111111111111111111111111
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
100000000000000000000001
111111111111111111111111
5853438432767-1637544500-60207544326135853442432767-6000568832613-622015013261300-6020754432613100010-6000568832613
00-6018252832613-7015872832613-6017843232613-784275843261310304000-6000483232613-1100-601825283261341960900

Está mais parecido, mas ainda dá erros :S Obrigado!


Be nice to see your eyes, blink them from time to time to relax your retina when using the computer. Blink now!

Share this post


Link to post
Share on other sites
pmg

Aconselho-te a verificar o valor de retorno do fscanf ...

Aparentemente estás a ler mais valores do que o que tens disponível no ficheiro de input.

Quando tentas ler um valor, mas o ficheiro de input acabou, o resultado do scanf() (da familia dele!) não é confiável: só o valor de retorno é que é!

Verifica sempre se o retorno do scanf() é o esperado e dá uma mensagem de erro se não for.


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!

Share this post


Link to post
Share on other sites
pikax

tens os tamanhos errados

    int map[24][25];
    int map_width = 24;
    int map_height = 25;
    int x;
    int y;
    FILE *map_file = fopen("map.txt", "r");
    for (x = 0; x < map_width; x++)
    {
      for (y = 0; y < map_height; y++)
      {
        fscanf(map_file, "%1d", &map[x][y]);
      }
      if(fgetc(map_file)!='\n')
        printf("ERRROR!\n";//fscanf(map_file, "\n"); // Skip newlines
    }

conta lá quantas linhas e colunas tem

1111111111111111111111111
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1000000000000000000000001
1111111111111111111111111


Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Share this post


Link to post
Share on other sites
KTachyon

Devias fazer:

int map_width = 24;
int map_height = 25;
int map[map_width][map_height];

Assim só necessitas mudar os valores num sítio.


“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Share this post


Link to post
Share on other sites
pmg

Devias fazer:

int map_width = 24;
int map_height = 25;
int map[map_width][map_height];

Os Variable Length Arrays (VLA) só funcionam em C99 (acho que o compilador do Visual Studio, por exemplo, não aceita VLAs). Se for importante manter compatibilidade com C89, usa #define.

#define MAP_WIDTH 24
#define MAP_HEIGHT 25
int map[MAP_WIDTH][MAP_HEIGHT];


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!

Share this post


Link to post
Share on other sites
KTachyon

Não coloquei essa informação, porque assumi que seria óbvio que a alternativa seria essa ou alocar a memória com o espaço necessário. :P


“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Share this post


Link to post
Share on other sites
SirDave

Pessoal, obrigado pelos conselhos, mas fico com mais uma dúvida. E se o mapa tiver "bytes" em vez de números:

1111111111111111111111111111111111111111111111111111
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000001
1111111111111111111111111111111111111111111111111111

Faço fscanf(my_file, "%2d", &map[y][x]);    mas isso resulta para valores tipo "02"? Ou seja, fica guardado o valor 2 no integer map[y][x]?

Obrigado.


Be nice to see your eyes, blink them from time to time to relax your retina when using the computer. Blink now!

Share this post


Link to post
Share on other sites
pmg

... se o mapa tiver "bytes" em vez de números ...

O 2 na especificação de conversão do scanf limita o número de caracteres significativos (digitos) a serem consumidos; não tem nada a ver com os valores apresentados.

Por exemplo, se o ficheiro tiver "123456789" e se se lhe aplicar o scanf("%1d%2d%3d%4d") a primeira conversão consome (e grava) o "1"; a segunda conversão consome (e grava) o "23"; a terceira consome o "456" e a última (só usa 3 caracteres do limite de 4) consome "789".

Com a definição normal de "bytes" não é possível isolá-los com scanf ou de outra forma qualquer. Um byte vai de 0 a 255 ... a sequência "154" tanto pode ser formada por 3 bytes (1, 5, e 4) como por 2 (duas formas: 15 e 4 ou 1 e 54) como por apenas 1 byte (154).

Normalmente usa-se um separador entre os valores: 1,54 ou 1 54 ou 1, 54 ou 1<TAB>54


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!

Share this post


Link to post
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

×
×
  • 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.