paulo1205
(usa Ubuntu)
Enviado em 26/05/2018 - 11:04h
GuilhermeFernan escreveu:
Então man o problema não é usar dessa forma com strings e sim os benditos vetores, cujo professor pediu com char.
Não sei onde você estuda, mas uma triste verdade em grande parte dos cursos de formação em TI é que os professores frequentemente não entendem nada daquilo que estão ensinando.
Assim sendo, não limite seu aprendizado àquilo que diz o professor. Quando você tiver uma tarefa para entregar, especialmente se valer nota, siga o que ele manda, mas não permita de maneira nenhuma que isso limite o seu próprio horizonte. Estude além do que ele pede. Saiba mais do que ele. Vá além.
No windows com utilização do dev c++ plus ele compila de boas junto com as bibliotecas.
#include <iostream>
#include <stdlib.h>
#include<conio.h>
Não vejo nenhum motivo para você usar <conio.h> nesse programa. Você não usou nenhuma função dessa interface não-padronizada, então poderia suprimir sumariamente esse cabeçalho obsoleto do seu programa.
Quanto ao resto, uma vez que você está usando C++, você deveria provavelmente usar a forma C++ “<cstdlib>” em lugar de “<stdlib.h>”, que é a forma do C.
using namespace std;
main()
Essa forma de declarar uma função, omitindo o tipo de retorno, é inválida, e provavelmente será rejeitada por compiladores modernos bem configurado.
Se você foi ensinado a fazer desse jeito, isso reforça o que eu disse sobre professores (ou autores de apostila) que não sabem o que estão ensinando.
C++ tem aversão ao recurso de versões antigas do C de assumir implicitamente o tipo
int quando o nome do tipo é omitido numa declaração. Desde muito cedo na história do C++ (ou seja, antes mesmo de haver um padrão oficial para a linguagem, o qual foi publicado em 1998) isso era considerado um erro. O próprio C, aliás, passou a repudiar tal prática a partir da revisão de seu padrão de 1999. Que alguns compiladores aceitem isso, ainda mais em C++, é um relaxamento do padrão, em favor de compatibilidade com código obsoleto. O correto mesmo seria atualizar código velho, e jamais produzir código novo com a cara de código antigo.
É uma boa prática configurar seu compilador para gerar a maior quantidade possível de mensagens de diagnóstico, que ajudem a localizar e apontar código perigoso ou obsoleto. Se você estiver usando um compilador da família do GCC, eu recomendo as opções “
-Wall -Werror -O2 -pedantic-errors ”.
{
char nomes [2][30], x, escolha;
int indice;
int ano_atual, ano_nascimento, idade[2];
do
{
cout<<"Digite o ano atual: ";
cin>>ano_atual;
for (indice = 0; indice < 2; indice++)
{
cout << "Digite o nome: ";
x = getchar();
gets(nomes[indice]);
Muita gente — inclusive eu — entende que não é muito bom misturar o uso de funções de entrada e saída de dados em C e em C++. No mínimo, por uma questão de consistência. Num caso extremo, pode não haver sincronismo entre as operações com funções do C e os objetos de
stream do C++.
Além disso, você usou essas funções sem ter incluído <cstdio>. Dependendo da implementação, isso pode vir a causar erros de compilação, por causa de símbolos não-declarados.
Mais ainda:
getchar() retorna um valor do tipo
int , mas você atribui esse valor a uma variável do tipo
char , o que implica que pode haver truncamento. Sobre este ponto, gostaria de fazer dois comentários. O primeiro é que você deve se acostumar a não misturar esses tipos (como subcomentário, ressalto que esse é outro erro comumente cometido por maus professores), por dois bons motivos: o primeiro é que
getchar ()/
fgetc ()/
getc () empregam os bits que um
int tem a mais que um
char para sinalização de erro, e tais bitas são desprezados quando você trunca o valor de retorno para caber num
char . Tão grave (ou até mais grave) que isso é que, dependendo da implementação,
char pode ser com sinal (funcionalmente equivalente a
signed char , com valores que vão de -128 a 127) ou sem sinal (funcionalmente equivalente a
unsigned char , com valores de 0 a 255). Quando
getchar () recebe um caráter válido (ou seja, sem erro), ela sempre devolve um valor que seria compatível um um
unsigned char (i.e. de 0 a 255), e que, portanto, é compatível com as funções de <cctype>/<ctype.h>. Se você converter esse valor para
char numa máquina em que esse
char é com sinal, pode acabar ficando com valores negativos, e tais valores negativos se mantêm negativos ao serem convertidos de volta para
int , tornando-se incompatíveis com as funções de <cctype>/<ctype.h> (e possivelmente até com outras funções da biblioteca padrão).
O segundo é que você simplesmente despreza o valor que acabou de ler para
x . Por um lado, seria interessante sempre tratar todos os resultados de operações de leitura. Mais cedo ou mais tarde, você vai encontrar situações em que os dados dispostos na entrada terão um formato diferente daquilo que você esperaria, que por fim prematuro dos dados, quer por letras onde você esperaria números, ou mesmo por conteúdo corrompido. Cada uma das operações de leitura (no seu caso, são três:
scanf (),
getchar () e
gets ()) deveria ser tratado. Isso pode parecer tedioso — e em boa medida é mesmo! —, mas é algo melhor de se aprender a praticar desde quando você ainda tem programas simples, para que você não descubra isso apenas quando já tiver programas bem mais complexos, e portanto mais difíceis de depurar.
Eis como isso poderia ter sido feito (seguindo o formato atual, misturando os estilos de C e C++).
int ano_atual, x;
char nome[50];
/* ... */
cout << "Informe o ano atual: ";
if(!(cin >> ano_atual)){
cerr << "Erro de leitura.\n";
exit(1);
}
do
x=getchar();
while(isspace(x) && x!='\n'); // Descarta espaços em branco; para ao encontrar fim de linha.
if(x==EOF){
cerr << "Erro de leitura.\n";
exit(1);
}
else if(x!='\n'){
cerr << "Dados extras na linha (deveria haver apenas um número). Abortando.\n";
exit(1);
}
if(!fgets(nome, sizeof nome, stdin)){
cerr << "Erro de leitura.\n";
exit(1);
}
else{
// fgets() captura também a marca de fim de linha ('\n'), então verifica
// se essa marca existe, para poder removê-la, ou se ela não existe,
// indicando leitura truncada.
size_t tam_nome=strlen(nome);
if(nome[tam_nome-1]!='\n'){
// Não achou fim de linha: a entrada está truncada.
if(tam_nome+1>=sizeof nome){
// Usuário digitou uma linha longa demais.
cerr << "Nome longo demais. Abortando.\n";
}
else{
// Trucamento mesmo havendo espaço livre: isso indica erro de leitura
// ou fim prematuro dos dados de entrada.
cerr << "Erro de leitura.\n";
}
exit(1);
}
nome[--tam_nome]='\0'; // Remove a marca de fim de linha. Tamanho da string encolhe uma posição.
if(tam_nome==0){
// Usuário digitou uma linha vazia. Essa situação pode não ser válida, dependendo do contexto.
cerr << "Leitura inválida: nome vazio.\n";
exit(1);
}
}
// Se chegar neste ponto, todas as leituras feitas acima foram válidas.
Com leituras puramente em C++, o tratamento de erros poderia ser feito com exceções.
int ano_atual;
char nome[50];
try {
cin.exceptions(ios::bad_bit);
cout << "Digite o ano atual: ";
cin >> ano_atual;
cin.ignore(numeric_limits<std::streamsize>::max(), '\n');
cin.getline(nome, sizeof nome);
}
catch(ios_base::failure &e){
cerr << "Erro de leitura\n";
exit(1);
}
(Contudo, se você de todo decidir que não quer tratar o valor de retorno, poderia ter desprezado também o valor retornado por
getchar (), em lugar de o atribuir a uma variável com o tipo errado.)
cout <<"Digite o ano de nascimento de " << nomes[indice] << ": ";
cin >>ano_nascimento;
system("cls");
Você tem realmente de limpar a tela aqui? Chamar
system () significa executar um programa externo ao seu através do sistema operacional. Essa operação é computacionalmente cara, e sujeita a vários erros — inclusive ao fato de que o comando invocado pode ter outro nome ou nem mesmo existir em máquinas diferentes (no Linux, por exemplo, o comando para limpar a tela é
clear , não
CLS , como no mundo Microsoft).
idade[indice] = ano_atual - ano_nascimento;
}
for (indice = 0; indice < 2; indice++)
{
cout <<nomes[indice]<< " tem " << idade[indice] << " anos. \n\n";
}
cout<<"Deseja refazer? ";
cin >>escolha;
system("cls");
}while (escolha = 's');
}
agora no Linux esse bendito gets() não funciona e da maneira como me informou ali em cima, não consegui utilizar da forma que me informou.
Essa já foi respondida na outra mensagem.