Queria saber porquê estou obtendo valores nada haver como resultado [RESOLVIDO]

1. Queria saber porquê estou obtendo valores nada haver como resultado [RESOLVIDO]

Antonio Lorival Baesso
4n7onio

(usa Nenhuma)

Enviado em 01/06/2017 - 22:26h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
printf("\t\t\t\tJosephine v0.359.n beta\n");

float controle=0;
unsigned int alunos, notas;
char opcao, opcao_2, aux[40];

do{
printf("[A] Cadastro da quantidade de dados\n");
printf("[B] Cadastro dos alunos e notas\n");
printf("[C] Listagem dos dados\n");
printf("[D] Alteracao dos dados\n");
printf("[E] sair\n");

scanf(" %c",&opcao);

if(controle==0){
a:
system("clear");
printf("Quantidade de alunos\n");
scanf("%u",&alunos);
printf("Quantidade de notas\n");
scanf("%u",&notas);
controle=1;
};

float Notas[alunos][notas], resultado[alunos];
char Alunos[alunos][20];

switch(opcao){
case 'a':
if(controle==0){
goto a;
};
break;

case 'b':
if(controle==0){
goto a;
};
for(int i=0;i<alunos;i++){
b:
system("clear");
printf("Digite o nome do %d aluno: ",i+1);
scanf(" %[^\n]s", &Alunos[i][20]);
for(int j=0;j<notas;j++){
system("clear");
printf("Digite a nota do aluno %s:",Alunos[i]);
scanf(" %f",&Notas[i][j]);
resultado[i]+=Notas[i][j];
}
controle=2;
};
break;

case 'c':
if(controle==0){
goto a;
};
if(controle==1){
goto b;
}
system("clear");
printf("[A] Sem ordenar\n");
printf("[B] Ordem crescente\n");
printf("[C] Ordem decrescente\n");

scanf(" %c",&opcao_2);

switch(opcao_2){
case 'a':
for(int i=0; i<=alunos;i++){
printf("%s : %.2f", Alunos[i], resultado[i]);
};
}
break;

case 'd':
for(int i=0; i<=alunos; i++){
for(int j=0; j<=notas; j++){
controle= alunos= notas= 0;
controle= resultado[i]= Notas[i][j]= 0;
strcpy(aux, "");
strcpy(Alunos[i], "");
}
};
printf("Tudo limpo!\n");
break;

default:
printf("Digite uma tecla validade\n");
printf("[A],[B],[C],[D] ou [E]\n");
break;
};
system("clear");
}while(opcao!='e');
return 0;
}


Se poderem me explicar eu agradeço estou com muita duvida na utilização de vetores, desde já obrigado.


  


2. Re: Queria saber porquê estou obtendo valores nada haver como resultado

Paulo
paulo1205

(usa Ubuntu)

Enviado em 02/06/2017 - 15:21h

Seu código agora está um pouco mais limpo do que o anterior, mas continua com problemas potencialmente causados por mau uso de goto.

Por favor, para o seu próprio bem, leve bem a sério o conselho de rearrumar o programa, eliminando todos aqueles gotos. O programa vai ficar indubitavelmente mais fácil de ler, e pode ajudar a evitar algumas surpresas.

Quer ver uma surpresa bem real? Quando você faz o “goto b”, provoca um desvio para dentro de um laço de repetição, com comandos que utilizam o valor da variável de controle do tal laço. Mas quanto vale a variável de controle no momento em que o goto foi solicitado? Você sabe?


Outro problema: quando você seleciona a opção 'c', faz um acúmulo das notas em resultado[i], sem ter anteriormente definido um valor inicial para esse array de resultados. O conteúdo anterior é indefinido, logo o valor acumulado também o será.


Mais um erro: quando você diz “scanf(" %[^\n]s”, &Alunos[i][20])”, comete vários equívocos:

a) Ao usar de &Alunos[i][20], você dá a entender que você quer que os caracteres lidos sejam gravados a partir da 21ª posição do vetor de caracteres indicados por Alunos[i]. Duvido que seja isso o que você realmente quer, até porque cada vetor tem apenas espaço para 20 caracteres (e o 20º caráter deve ser um byte nulo). Você provavelmente quer garvar a partir do 1º byte de Alunos[i]. Sendo assim, você poderia até passar como argumento “&Alunos[i][0]”, mas provavelmente seria mais simples dizer somente “Alunos[i]” (sem o operador de obtenção de endereço, e sem o segundo índice, que aponta para um caráter dentro do vetor).

b) Na string de formatação, aquele caráter “s” após o fechamento do colchete está sobrando e, na prática, faz com que o reconhecimento do padrão por scanf() seja prematuramente interrompido. Provavelmente você entendeu que a expressão entre colchetes é um modificador da conversão “%s”, mas não assim que a coisa funciona: “%s” indica um tipo de conversão, e “%[” indica outro tipo de conversão, sendo que esta última recebe parâmetros na forma de sufixo, o qual é terminado pelo caráter “]”. Muita gente comete esse erro, inclusive muita gente boa (inclusive num artigo aqui do VoL, em que um professor de C ensina a fazer dessa maneira errônea). Mas o fato de ser um erro comum não significa que você também tem de cometê-lo.

c) Como você tem um espaço limitado para os caracteres (20 caracteres por aluno, sendo 19 úteis e 1 para o byte nulo terminador da string), poderia colocar uma proteção na string de formatação para evitar o erro pelo qual o usuário poderia provocar erro ao digitar mais do que 19 caracteres na entrada.

d) O valor de retorno de scanf() (não só deste, mas também dos demais usos feitos ao longo do programa) deveria ser testado, para saber se a leitura foi bem sucedida ou não, e se o valor eventualmente lido é válido ou não.


3. Muito obrigado

Antonio Lorival Baesso
4n7onio

(usa Nenhuma)

Enviado em 02/06/2017 - 20:30h

Realmente você esta sendo um pai pra mim nesse mundo de programação, mais ainda não sei como retornar sem usar o goto, e essa duvida permanecem nos meu colegas de classe.

e mais uma fez obrigado.


4. Re: Queria saber porquê estou obtendo valores nada haver como resultado [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 03/06/2017 - 04:55h

Pode me chamar de antiquado, mas eu não gosto de VLAs.

Eis como eu faria a coisa toda:

1) Colocaria os dados de alunos dentro de uma estrutura, para não ficar com um monte de arrays separados, mas relacionados.

struct DadosAluno {
char nome[TAM_NOME];
float *notas; // Será alocado dinamicamente.
// size_t max_notas; // Opcionalmente, cada aluno poderia ter uma quantidade diferente de notas
float resultado;
};



2) Declararia os dados dos alunos como ponteiro, para ser alocado dinamicamente com múltiplos no momento certo (i.e. após saber as quantidades).

struct DadosAluno *alunos=NULL;  // Inicialmente não aponta para lugar nenhum.
size_t max_alunos, max_notas; // Opcionalmente, max_notas pode ser um campo com valor diferente para cada aluno.
size_t n_alunos=0; // Quantidade de alunos já cadastrada.



3) Enquanto alunos==NULL, as opções de cadastro do menu ficam desabilitadas.

do {
printf(
"Menu:\n"
"\tA) Definir quantidade dos dados\n"
"%s"
"%s"
"\tD) Apaga dados\n"
"\tE) Sair",
alunos!=NULL? "\tB) Cadastrar alunos\n": "",
n_alunos>0? "\tC) Listar dados\n": ""
);
/* ... */
if(opcao=='E'){
// libera memória das notas de cada aluno e depois libera alunos.
break; // Sai do laço do-while.
}
if(opcao=='A'){
// Lê max_alunos e max_notas.
// Faz alocação de alunos e das notas de cada aluno (usando malloc() ou calloc()).
// Manipula n_alunos de acordo.
}
else if(opcao=='D'){
// Apaga dados de notas de cada aluno.
// Apaga todos os alunos.
}
else if(alunos!=NULL){
if(opcao=='B'){
// Lê alunos e seus dados.
}
else if(opcao=='C' && n_alunos>0){
// Mostra relatório dos alunos vadastrados.
}
else{
fprintf(stderr, "Opção inválida. Tente outra vez.\n");
}
}
else{
fprintf(stderr, "Opção inválida. Tente outra vez.\n");
}
} while(1);



5. Obrigado

Antonio Lorival Baesso
4n7onio

(usa Nenhuma)

Enviado em 03/06/2017 - 08:00h

Você e Muito inteligente, muito obrigado






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts