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

Raquel7112

Programa com array bidimencional

Mensagens Recomendadas

Raquel7112

Olá pessoal, mais uma vez tenho uma dúvida com um enunciado de um programa. O enunciado é o seguinte:

Elabore um programa que:

-memorize a primeira letra de cada conjuje, cabendo ao operador indicar essas letras

-o numero de casais é quatro

-no final o programa deve mostrar quem está casado com quem.

O programa que fiz não deu muito certo, pois ele salta o casal tres.. alguém consegue me ajudar?

#include <stdio.h>

int main(){

               const int LINHAS=4;
               const int COLUNAS=2;
               int a,b, c;
               unsigned char tabela[LINHAS][COLUNAS];

               for(a=0;a<4;a++){
                 for(b=0;b<2;b++){
                               tabela[a][b]=0;
                 }
               }



               for(a=0;a<4;a++){
                                                printf("Introduza as duas letras para o %d casal[b]\n[/b]", a+1);
                 for(b=0;b<2;b++){
                                                  printf("Introduza %d membro do casal:[b]\n[/b]", b+1);
                                                        scanf("%c",&tabela[a][b]);
                                                        fflush(stdin);
                 }
               }

                  for(a=0;a<4;a++){
                               printf("%d casal:[b]\n[/b]", a+1);
                               for(b=0;b<2;b++){
                                        printf("%d membro do %d casal: %c[b]\n[/b]", b+1, a+1, tabela[a][b]);
                 }
               }

               getchar();
               getchar();
               }

Editado por Rui Carlos
Conteúdo recuperado.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31

  • Tens de melhorar a indentação.
  • Depois "const" não define uma constante propriamente dita como define, por exemplo, em Pascal.
  • Não percebo porque tens dois getchar's no final, basta um.
  • O main não está a retornar nada, e devia retornar (e a sua declaração devida deveria ser int main(void), mas isso já é outro pormenor) - não obtiveste um erro de compilação ou um warning?
  • Tens declarada uma variável "c" para nada.
  • Não inicializas as variáveis, para além da array em runtime.
  • Por fim, o scanf deveria ser scanf("%c\n", &tabela[a]); <- o scanf estava à espera de um caracter, e tu deste-lhe o caracter e um enter, pelo que em tabela[a][0] fica o caracter e em tabela[a][1] fica o "\n". Portanto, neste caso, tens de indicar ao scanf que vais dar um caracter e um enter.

Estavas a dizer que o programa saltava o terceiro casal - nos meus testes não mostrava era o 2º elemento de cada casal.

EDIT: Definiste as "constantes" e só as utilizaste na definição da array, mas não as utilizaste nos ciclos for. Porquê?

Editado por thoga31

Knowledge is free! | Occasional Fortnite player

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31

Tens de usar as flags para o gcc relatar avisos e afins. O gcc é muito permissivo e por defeito dá poucos avisos ou nenhuns:

gcc -Wall -Wextra -pedantic

O scanf é um pouco dúbio no que diz respeito a strings e chars. Uma solução que podes aplicar é a utilização do getchar, inicializando a array toda com "\n".

while (tabela[a][b] == '\n') tabela[a][b] = getchar();

Desta forma consegues sempre ignorar o "\n" que o getchar obviamente iria ler quando fazes enter.

Os meus colegas que estão mais habituados ao C do que eu poderão dizer se é uma solução boa ou má... mas que resultou, lá isso resultou :D

Mostra depois o teu código final quando terminares.

Editado por thoga31

Knowledge is free! | Occasional Fortnite player

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
HappyHippyHippo

além do que já foi dito :

#include <stdio.h>

/* maneira "correcta" de criar constantes em C
* já agora, se as tens, usa-as nos ciclos ... */
#define LINHAS 4
#define COLUNAS 2
#define BUFFER_SIZE 256

int main(){
 /* tenta dar nomes mais razoáveis as tuas variáveis */
 int linha, coluna;
 char tabela[LINHAS][COLUNAS];

 /* variáveis usadas para leitura do teclado */
 char buffer[bUFFER_SIZE];
 int ok;

 /* ciclo pesado e desnecessário */
 /*
 for(linha = 0; linha < LINHAS; linha++) {
   for(coluna = 0; coluna < COLUNAS; coluna++) {
     tabela[linha][coluna] = 0;
   }
 }
 */

 /* como colocar a tabela a zeros de uma só vez, mas como disse,
  * desnecessário porque vais ler valores e preencher a tabela logo a seguir */
 memset(tabela, 0, sizeof(char) * LINHAS * COLUNAS);

 /* ciclo de leitura do teclado */
 for(linha = 0; linha < LINHAS; linha++) {
   printf("Introduza as duas letras para o %d casal\n", a + 1);
   for(coluna = 0; coluna < COLUNAS; coluna++) {
     /* não podes ler dados do teclado de forma "leviana" como a usada
      * e um erro muito comum de quem esta a começar a dar os primeiros passos
      * em programação em C, mas isso passa logo quando se depara com coisas
      * estranhas como o que te esta a acontecer */ 
     /*
     printf("Introduza %d membro do casal:\n", b + 1);
     scanf("%c", &tabela[a][b]);
     fflush(stdin);
     */

     /* o que necessitas de fazer e : */
     do {
       /* fazer o pedido */
       printf("Introduza %d membro do casal:\n", b + 1);

       /* ler tudo o que foi escrito do teclado
        * (ninguém vai estar a escrever 256 caracteres ... mas para isso também
        * existe solucao, mas nao vou complicar) */
       fgets(buffer,       // onde guardar a informação
             BUFFER_SIZE,  // quanto espaço existe no array que ira guardar a informação
             stdin);       // de onde ler a informação (stdin quase sempre será o teclado)

       /* ler do array usado para ler tudo que foi escrito
        * o sscanf retorna o numero de valores lidos correctamente, por isso
        * ao guardar esse valor na variável "ok", estas a guardar se leu bem o
        * valor ou nao */
       ok = sscanf(buffer, "%c", &tabela[a][b]);

     } while(!ok); /* ciclo enquanto nao leres uma valor correcto do teclado */
   }
 }

 /* ciclo de apresentação */
 for(linha = 0; linha < LINHAS; linha++) {
   printf("%d casal:\n", a + 1);
   for(coluna = 0; coluna < COLUNAS; coluna++) {
     printf("%d membro do %d casal: %c\n", b + 1, a + 1, tabela[a][b]);
   }
 }

 getchar();

/* basta um ... */
/*
 getchar();
*/

 /* em C, o main deverá retornar um valor numérico inteiro */
 return 0;
}


IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Raquel7112

Bom.. o código do usuário Stack n deu certo aqui e tem cenas desse código que n entendi direito pq ainda estou estudando.. Mas eu perguntei pra um professor e ele me ensinou a fazer esse programa..

Editado por Rui Carlos
Conteúdo recuperado.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31

Só uma nota: nenhum dos membros que aqui ajudou se chama "Stack". Stack Overflow é um título dado consoante o nº de posts. Eu sou o @thoga31 e o meu colega é o @HappyHippyHippo.

Quanto ao código, andei a escrever uma lista com 8 pontos a melhorar, e o @Happy teve a gentileza de fazer um código muito bem explicado, para que só um problema tivesse sido resolvido.

Por mim tudo bem, não me importo de falar para o vácuo. Tu é que ficas sem aprender a fazer as coisas como deve ser em C...

Editado por thoga31

Knowledge is free! | Occasional Fortnite player

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
HappyHippyHippo

Bom.. o código do usuário Stack n deu certo aqui e tem cenas desse código que n entendi direito pq ainda estou estudando.. Mas eu perguntei pra um professor e ele me ensinou a fazer esse programa..

dizer que o código não funciona sem dizer porquê, é o mesmo que não fazer nada.

o código não funcionava por uma simples razão : eu alterei o nome das variáveis de a e b para linha e coluna respectivamente, só que não alterei em todas as ocorrências.

por outras palavras, nem te deste ao trabalho de ler o código ou a mensagem de erro de output do compilador.

... enfim ...


IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pikax
Eu anotei os comentários e dicas do pessoal aqui e proguntei para o professor, porque com um professor ao lado te explicando tudo, consegue-se aprender muito mais rápido.. afinal paguei muito caro por essas aulas..

Consegues aprender mais rapido e tirar duvidas mais facilmente, mas sinceramente o codigo que o @HappyHippyHippo postou esta' melhor implementado do que tu postaste.

Depois "const" não define uma constante propriamente dita como define, por exemplo, em Pascal.
/* maneira "correcta" de criar constantes em C
* já agora, se as tens, usa-as nos ciclos ... */
#define LINHAS 4
#define COLUNAS 2

Conforme, depende do compilador, mas para o VC e' basicamente igual definires uma constante com o define ou com o const

#include <iostream>

#define DEF_NUM 152
int main()
{
const int CONST_NUM = 152;

int res = DEF_NUM + CONST_NUM;

std::cout<<res;
}

--Retirei muitas linhas do assembly, porque gera muita coisa por causa do iostream

Flags de debug

/GS /analyze- /W3 /Zc:wchar_t /ZI /Gm /Od /sdl /Fd"Debug\vc110.pdb" /fp:precise /D "_MBCS" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /Fa"Debug\" /EHsc /nologo /Fo"Debug\" /FA /Fp"Debug\TesteASM.pch"

Assembly gerado em debug:

; File g:\documents\visual studio 2012\projects\teste\testeasm\main.cpp
; Line 5
push	ebp
mov	ebp, esp
sub	esp, 216				; 000000d8H
push	ebx
push	esi
push	edi
lea	edi, DWORD PTR [ebp-216]
mov	ecx, 54					; 00000036H
mov	eax, -858993460				; ccccccccH
rep stosd
; Line 6
mov	DWORD PTR _CONST_NUM$[ebp], 152		; 00000098H
; Line 8
mov	DWORD PTR _res$[ebp], 304		; 00000130H
; Line 10
mov	esi, esp
mov	eax, DWORD PTR _res$[ebp]
push	eax
mov	ecx, DWORD PTR __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
call	DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
cmp	esi, esp
call	__RTC_CheckEsp
; Line 11
xor	eax, eax
pop	edi
pop	esi
pop	ebx
add	esp, 216				; 000000d8H
cmp	ebp, esp
call	__RTC_CheckEsp
mov	esp, ebp
pop	ebp
ret	0
_main	ENDP
_TEXT	ENDS

flags da release

/GS /GL /analyze- /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"Release\vc110.pdb" /fp:precise /D "_MBCS" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /Fa"Release\" /EHsc /nologo /Fo"Release\" /FA /Fp"Release\TesteASM.pch"

assembly gerado com optimizacoes:

; File g:\documents\visual studio 2012\projects\teste\testeasm\main.cpp
; Line 10
mov	ecx, DWORD PTR __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
push	304					; 00000130H
call	DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
; Line 11
xor	eax, eax
ret	0
_main	ENDP
_TEXT	ENDS
; Function compile flags: /Ogtp

tem aqui uns artigos bastante bons a falar do assembly gerado pelo o compilador do VC++ :)

Ja' agr o compilador e' o do Visual Studio 2012 Update 3

EDIT: Esquecime de dizer que o Visual Studio Optimiza o const se o dizer-mos para fazer :)

EDIT2: se for preciso explicar, tambem posso, mas acho que o numero de linhas da' para entender :D

o nome esquecito "__imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z" e' a funcao do cout

Reparei agr qe e' a seccao de C e escrevi codigo em C++

EDIT3:

Apos uma discussao no IRC com @pwseo

E cheguei a conclusao que o que disse aqui esta' errado, porque pode-se mudar o valor da constante em C e nao em C++, por isso o que escrevi aqui nao tem nexo dentro do contexto do topico.

Editado por pikax

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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31

@pikax, complicaste o tópico que supostamente era relativamente simples. A rapariga tem dificuldades em programação e tu espetas um monte de ASM... :D

Não confundas C com C++, tem cuidado. São semelhantes na espreita mas diferentes na prova ;)

@Raquel7112, esse código final a que chegaste continua incorrecto no contexto daquilo que é o C. Mas enfim, não pretendo entrar muito no mundo do ensino da programação que isso dá pano para mangas. Hoje em dia paga-se comummente caro para se ter falta de qualidade disfarçada de boa qualidade...


Knowledge is free! | Occasional Fortnite player

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
PsySc0rpi0n

Não consigo concordar mais com o thoga31...

Uma das coisas básicas que eu gostava de saber de cor e salteado e de trás para a frente e não sei, é perceber em que situações o '\n' e o '\0' vem fazer estragos em funções como fgets(), scanf() e companhia, e perceber bem quando é que estes caracteres "implicam" com o buffer do teclado e com o preenchimento de uma variável que é uma cadeia de caracteres ou uma string. São pormenores que me dão dores de cabeça.

E foram coisas que ninguém nas minhas aulas se preocupou em ensinar aos alunos.

Outra coisa é perceber o spacing ou lá como se chama isso quando usamos o '\t' e depois o output não é o que a gente espera. Já me deram aqui uma explicação mas eu não a consegui perceber.

Outro pormenor é o facto do C ver os caracteres como caracteres mas também como inteiros.

Bem, são inúmeros os pormenores que eu adorava dominar a 100% e que aqui o pessoal mais entendido se farta de chamar à atenção e batalhar...

Isto para dizer que é mais que verdade que hoje nas universidades, muitas vezes ensina-se a programar mas muito mal...

  • Voto 1

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Flinger

Existe um recurso bastante importante para dominares esse tipo de assuntos, mas que tem vindo a cair em esquecimento.

Trata-se do "man", um utilitário dos sistemas linux que tem toda a informação essencial das funções da glibc e outras.

existem versões online, mas o pessoal ou desconhece, ou não quer ter o trabalho de usar.

http://linux.die.net/man/3/fgets

Tens aqui a entrada para o fgets. Eu acho que a descrição da função é perfeitamente clara, e permite-te saber exactamente o que precisas acerca da função. A minha sugestão é exactamente, quando tiveres dúvidas acerca de uma função, pesquisa na net "man <nome_funcao>". Aprendes imenso.

Nas universidades não entram em detalhes destes, até porque muitas vezes são específicos dos SO, e não estão dentro do programa da cadeira. Era aquele tipo de conhecimento que mais depressa ia passando de aluno para aluno, no meu tempo. A questão do buffer do teclado é muito simples. O stdin só recebe a informação quando o utilizador prime o enter "\n" ou o ctrl+d "EOF" (pelo menos em sistemas linux, fica aqui a dica para quem quiser brincar um pouco).

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31

Os conteúdos das mensagens e do tópico escritos por parte da OP foram apagados pela sua acção. Os conteúdos serão recuperados, se possível.

O tópico está trancado. Relembro a todos que os tópicos e as mensagens não devem ser apagados, seja em que circunstância for.


Knowledge is free! | Occasional Fortnite player

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Convidado
Este tópico está fechado a novas respostas.

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.