• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

_SirO_

Problema de compliçao em C, array bidimensional

18 mensagens neste tópico

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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])

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

@ untouchables

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

lol não consegues ganhar? então está muito bem feito :D não tens executável, para o pessoal ver como ficou?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

bem, não consegui ganhar, mas também não perdi nenhuma vez :D está engraçado, parabéns!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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:

0

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