Jump to content

Problema de compliçao em C, array bidimensional


Recommended Posts

Posted

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

Posted

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.

- Destineo

Posted

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

Posted

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.

- Destineo

Posted

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 😄

Posted

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

Posted

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

Posted

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!

Posted

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

Posted

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

EDIT 2: AI revista. está mais lixado 😄

Posted

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

EDIT 2: AI revista. está mais lixado 😛

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  🙂😄

Sobre a nova versão, já corrigiste o erro  😁

Mas mesmo assim consigo vencer  😛 :P 😛 :P

Posted

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:

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.