Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #57 da revista programar. Faz já o download aqui!

_SirO_

Problema de compliçao em C, array bidimensional

Mensagens Recomendadas

_SirO_    0
_SirO_

Boas! estou com um problema numa funçao, obtenho o erro de compilaçao "invalid use of array with unspecified bounds", o que eu pretendia na funçao era inicializar uma matriz com um espaço em cada posiçao....

int main(void)
{
    char jogo[3][3];
    int N=0;
    
    inicializa_jogo(jogo);
    
    while(N!=9)
    {
    escreve_tabuleiro(jogo);
    jogada_pess(jogo,&N);
    jogada_pc(jogo,&N);
    }
    
    
    return 0;
}

void inicializa_jogo(char jogo[][])
{    int i,j;
     for(i=0;i<=2;i++)
         for(j=0;j<=2;j++)
             jogo[i][j]=' ';                 
}

EDIT: Usa a ferramenta GeSHi, assim o código fica mais legível

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Destineo    0
Destineo

Boas tardes,

O teu problema é que não podes definir um função como definiste, ou seja, com char jogo[][] como parametro. Como noutros posts, já não me lembro muito de C, mas sugiro o seguinte :

void inicializa_jogo (char * jogo)
{
memset (jogo, ' ', 3*3*sizeof(char));
}

Isto irá limpar o array e colocar o espaço em todas as posições. A chamada a esta função é exactamente a mesma como tens inicializa_jogo(jogo).

Um array do estilo char xpto[9][10] faz com que a variavel xpto seja um ponteiro para o inicio do array que declaraste. Ou seja, no limite, se quisesses fazer as coisas à mão, podias navegar pelo array da seguinte forma;

for (int i = 0; i < 9; i+=3*sizeof(char))
{
char* elemento = xpto + i;
....
}

e em cada iteração, estarias a aceder à posição 0, 1 e 2 do array de chars que criaste.

Expliquem-me como deve de ser ? Se não, digam qualquer coisa que tento melhor.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
_SirO_    0
_SirO_

obrigado por essa funçao memset, nao conhecia, mas esta funçao

void inicializa_jogo (char * jogo)
{
memset (jogo, ' ', 3*3*sizeof(char));
}

também nao pode ser definida assim.... penso eu, é que sendo o array bidimensional, penso que nao podemos aceder aos endereços de memoria assim tao facilmente.... quer dizer, imaginando que pretendo a posiçao [1][2], como é que faço, em aritmetica de ponteiros?

Btw, ja descobri porque e que nao compilava, o erro estava onde disseste, tinha que indicar tambem as dimensoes do array.

void inicializa_jogo(char jogo[3][3])

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Destineo    0
Destineo

Podes aceder da forma que disse, porque quando tu crias o array bidimensional, ele aloca-te o espaço em memória consecutivamente.

Se quiseres, nunca fiz isto, mas se olhares para o assembler que é gerado para aceder a uma posição, por exemplo [1][2] do array, vais ver que ele irá fazer a aritmética simples, de 1*tamanho do array(neste caso 3) + 2.

O C alloca-te a memória consecutiva, senão tinha que manter uma tabela de endereço para saber onde estava cada elemento do array, o que é contra-produtivo, lento e ocupa mais espaço que o array em si.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
untouchables    0
untouchables

mais fácil ainda...

no topo do programa, defines algo do tipo:

typedef int MATRIZ[3][3];

no teu código,ficaria:

int main(void)
{
    MATRIZ m;
    int N=0;
    
    inicializa_jogo(m);
    
    while(N!=9)
    {
    escreve_tabuleiro(m);
    jogada_pess(m,&N);
    jogada_pc(m,&N);
    }
    
    
    return 0;
}

void inicializa_jogo(MATRIZ m)
{    int i,j;
     for(i=0;i<=2;i++)
         for(j=0;j<=2;j++)
             m[i][j]=' ';                 
}

ps: fiz isto à pressa, apenas alterei o óbvio.

utilizando assim a matriz, funciona.

experimenta :D

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
_SirO_    0
_SirO_

Ok, obrigado pelo esclarecimento, isto de compreender bem, ponteiros/etc, é uma grande ajuda.

Já acabei um programa, o jogo do galo, está porreiro por acaso, mas agora tenho um problema, nunca consigo ganhar.... :S

Bem, acho que é sinal que está bem feito....

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
_SirO_    0
_SirO_

@ untouchables

Por acaso também me ocorreu fazer uma coisa dessas.... mas só sabia fazer em Pascal, em C ainda sou muito tenrinho.... :D

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
deathseeker25    6
deathseeker25

Acho que devias acrescentar a opção de jogar novamente ao código-fonte.

Tambem joguei três vezes, não ganhei mas tambem não perdi. :D

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
brink@ero    0
brink@ero

Bem vindo ao forum _SirO_

Só agora ví o tópico. Vou te dar uns conselhos.

Não é boa política usar variáveis globais (eu sou alérgico a isso  :)). Deve-se sempre evitar, só em situações extremas é que se deve usar.

O teu problema podia ser resolvido de duas maneiras.

Pegando no teu código, como passar uma variável Matriz[N][M]?

Bem, para quem não sabe isto é um array de N vectores de dimensão M. E vectores são apontadores para uma memória pré-reservada.

Quando tens arrays de arrays, isto quer dizer que tens apontadores de apontadores. Neste momento vocês devem ter ficado confusos ou não.

Isto é complicado de explicar para quem não percebe que um array/vector é um apontador. Mas quando acedes a Matriz[2][3] o que acontece é isto:

1.º - Vais à variável Matriz buscar o valor do endereço para onde está a apontar {por exemplo a posição 2451 (n.º fictício)}

2.º - Incrementas 2 unidades para chegares à posição Martiz[2] { neste momento estás apontar para a posição 2453}

3.º - Nessa posição está outro endereço de memória (o 2.º apontador) { por exemplo 6215}

4.º - Incrementas 3 unidades e tens o endereço de memória da Matriz[2][3]

Confuso? Tanto trabalho que o compilador tem de fazer só para termos isto Matriz[N][M]!

Pois é, como o meu professor disse: A memória é linear, não existe matrizes de memórias!

Por isso é que nenhum programador com um determinado grau ou qualificação faz isso do Matriz[N][M].

Depois do sermão fica o modo de resolução. Como Matriz[N][M] é um apontador de apontadores, então fica do seguinte modo:

void teste(char **Matriz)
{
/* ... */
}

void main(void)
{
char Matriz[3][3];
/* ... */
teste(Matriz);
}

Na boa política é fazeres isto assim:

char Matriz[3*3];

Depois para acederes à linha X e coluna Y, fazes assim:

Matriz[Y + X * numero de colunas]

Depois vou verificar o IA do teu programa e comento.  :D

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
brink@ero    0
brink@ero

O programa tem um bug!! LOL

Estava eu preste a ganhar logo à primeira jogada quando ele substituiu o meu X por um O. LOL

Assim não vale, isso é batota!

Deixo aqui a sequência das minhas jogadas:

eu: 1,3

PC: 2,2

eu: 3,3

PC: 1,3

eu: 3,1

PC: 2,1

eu: 3,2 (sepostamente a jogada da vitória)

PC: 3,3 ? ??????

Nota: Conheço todos os segredos do jogo do Galo (são poucos), porque já fiz um programa de IA do jogo do galo, onde estudei todas as jogadas!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
untouchables    0
untouchables

brink@ero essas combinações não funcionam comigo... o PC não chega a substituir o caracter.

reparei num "defeito"... o pc está mais preocupado com o facto de eu nao ganhar do que ele ganhar. exemplo:

1,1

1,3 (neste momento ele ja tem 2 elementos seuigos, mas nao vou fazer com que ele nao ganhe)

3,1(neste momento, ele podia ter ganho, mas tapou a minha jogada)

só nofim disto é que ele irá ganhar, não aproveita a situação à primeira...

edit:

no fim destas 3 jogadas, se ainda fizer "3,2", ele ainda não vai acabar o jogo

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
_SirO_    0
_SirO_

lol isto esta feito um bocado à pedreiro, tens razao, tenho que alterar a IA para o gajo dar prioridade a ganhar, em vez de dar prioridade a nao deixar ganhar.

Quanto á questao de ponteiro de ponteiro, eu sabia isso, apenas nao tenho pratica  e portanto fiz como sabia :)

No que diz respeito a variavel global, ela nao e bem global ou é? quer dizer, ela esta declarada em cada cabeçalho de cada funçao, apenas resolvi manter o nome, mas podia ter alterado para outro.....

O que sugeres? que cada funçao retorne um valor que por sua vez vai ser usado em vez de ter tantas funçoes void?

EDIT: fazendo a modificação de

void escreve_tabuleiro(char jogo[3][3]);    para  void escreve_tabuleiro(char **jogo);

compila, com avisos, "incompatible pointer tipe" e assim que tento correr dá erro....  :D

EDIT 2: AI revista. está mais lixado :D

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
brink@ero    0
brink@ero

lol isto esta feito um bocado à pedreiro, tens razao, tenho que alterar a IA para o gajo dar prioridade a ganhar, em vez de dar prioridade a nao deixar ganhar.

Quanto á questao de ponteiro de ponteiro, eu sabia isso, apenas nao tenho pratica  e portanto fiz como sabia :D

No que diz respeito a variavel global, ela nao e bem global ou é? quer dizer, ela esta declarada em cada cabeçalho de cada funçao, apenas resolvi manter o nome, mas podia ter alterado para outro.....

O que sugeres? que cada funçao retorne um valor que por sua vez vai ser usado em vez de ter tantas funçoes void?

EDIT: fazendo a modificação de

void escreve_tabuleiro(char jogo[3][3]);    para  void escreve_tabuleiro(char **jogo);

compila, com avisos, "incompatible pointer tipe" e assim que tento correr dá erro....  :D

EDIT 2: AI revista. está mais lixado :P

Não, eu comentei aquilo antes de ver o código. Não tens nenhuma variável global.

Sobre o erro, não sei. Foi compilar o teu código no VC++.

Deu-me um erro:

error C2065: 'memset' : undeclared identifier

Fui a net e ví isto:

#include <string.h>
void *memset(void *s, int c, size_t n);

fonte: http://www.opengroup.org/onlinepubs/007908799/xsh/memset.html

Depois compilou sem nenhum erro.

Sobre o:

void escreve_tabuleiro(char jogo[3][3]);    para  void escreve_tabuleiro(char **jogo);

O VC++ não aceita isto, à tarde tento isso no linux. Mas tenho quase a certeza que dava assim. Agora estou confuso  :):D

Sobre a nova versão, já corrigiste o erro  :biggrin:

Mas mesmo assim consigo vencer  :P :P :P :P

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
brink@ero    0
brink@ero

Já experimentei no linux  :-[

Erro meu, afinal ele não aceita char **matriz, para uma inicialização matriz[3][3]. Confundi com outra  inicialização em que construia matrizes com memória dinâmica.

Nessa situação fazia isto: char ** matriz na inicialização, depois é que reservava o espaço. Erro meu  :wallbash:

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora


×

Aviso Sobre Cookies

Ao usar este site você aceita a nossa Política de Privacidade