paulo1205
(usa Ubuntu)
Enviado em 06/06/2016 - 05:02h
No título você fala em
strcmp (), mas no programa você usa
stricmp (). Esse
i no meio do nome da função faz toda a diferença:
strcmp () faz parte da biblioteca padronizada do C, ao passo que
stricmp () é uma função não-padronizada, provida como extensão somente por alguns compiladores, sobretudo no ambiente Windows.
No mundo POSIX (UNIX em geral, além de Linux e MacOS/X), a função equivalente a essa que você usou se chama
strcasecmp (). Infelizmente, ela padece do problema reverso: a maioria dos compiladores para Windows não a implementa com esse nome.
Entretanto, o melhor para o seu programa é não usar nenhuma delas. O que você quer de informação é só um caráter -- então que tal ler só um caráter? Eis como você pode fazer:
unsigned char sexo; /* <-- Tem de ser unsigned por causa de toupper() (ver abaixo). */
int rc;
while(1){
printf("Digite 'M' para masculino, 'F' para feminino, ou 'S' para sair: ");
rc=scanf(" %c", &sexo); /* <-- Note o espaço após as aspas e antes do %c. */
if(rc==EOF || rc==0){
fprintf(stderr, "Erro de leitura ou final inesperado da entrada.\n");
break;
}
sexo=toupper(sexo); /* <-- toupper() é declarada em <ctype.h>. */
if(sexo=='M')
conteM++;
else if(sexo=='F')
conteF++;
else if(sexo=='S')
break;
else
fprintf(stderr, "Você digitou um caráter inválido.\n");
}
-----
EM TEMPO: No seu programa original, você cometeu outro erro: em vez de dizer “
scanf("%s", &sexo) ”, sendo
sexo , naquele caso, um array de caracteres, você deveria ter dito simplesmente “
scanf("%s", sexo) ”.
Para entender o motivo, considere os seguintes aspectos:
1) O especificador de formato
"%s" de
scanf () indica que o argumento correspondente é do tipo “ponteiro para
char ”.
2) O padrão do C, ao tratar de expressões, e mais particularmente dos tipos de dados usados em tais expressões, diz que quando o nome de um array aparece em qualquer expressão que não envolva a aplicação dos operadores
& (obtenção de endereço) ou
sizeof (cálculo da quantidade de bytes ocupados) diretamente sobre o array então o tipo do array deve ser interpretado como se fosse um ponteiro para o tipo do seu elemento (por exemplo: se eu tiver um array de caracteres, ele será entendido como um ponteiro para caracteres; se eu tiver um array de inteiros, ele será entendido como um ponteiro para inteiros etc.).
2.1) Note que eu disse “caracteres” e “inteiros”, no plural, e não “caráter” e “inteiro”. Em C, um ponteiro pode ser usado para apontar para um único objeto ou para uma sucessão de objetos do mesmo tipo. Cabe ao programador saber se está se referindo a um único objeto ou a uma coleção.
3) Se a expressão envolver os operadores
& ou
sizeof aplicados diretamente sobre o array, então o array inteiro é entendido como um único dado, em vez de um agregado de dados do mesmo tipo.
4) No caso do operador
& aplicado a um array com
N elementos do tipo
X , ele devolverá um dado do tipo “ponteiro para (uma possível sucessão de) arrays com
N elementos do tipo
X ” (note como isso é diferente de “ponteiro para (uma possível sucessão de) elementos do tipo
X ”).
Erros como esse são relativamente comuns, especialmente entre iniciantes (mas não só!). Até por ser algo que ocorre por envolver apenas um caráter no código fonte (o “
& ”), esse erro pode acontecer até por acidente. Mas algo que atrapalha o diagnóstico de problemas desse tipo é que, em muitos casos, o endereço do array como um todo (e.g.
&array ) e o endereço do seu primeiro elemento (e.g. apenas
array ) serem numericamente equivalentes, mesmo que os tipos de cada expressão sejam diferentes e incompatíveis entre si. Se o compilador não for instruído a verificar ou a obrigar a correspondência entre tipos, ou se ele não puder fazer isso (por exemplo, em funções que usem listas de parâmetros variáveis, como é o caso de
printf () e
scanf ()), erros desse tipo podem passar batidos durante a compilação e seguir sem identificação por um longo tempo. O programa está matematicamente errado, mas uma coincidência numérica permite que ele não manifeste esse erro... até o dia em que você estiver num computador em que essa coincidência não vale, ou quando você fizer uma ligeira alteração na forma do programa, e tal alteração inocente for suficiente para revelar a diferença de sentido.
Sempre que possível, instrua seu compilador a lhe dar o máximo possível de mensagens de diagnóstico, e até a tratar mensagens de alerta como se fossem erros (porque geralmente são mesmo, ainda que acidentais!). Alguns compiladores, quando instruídos a trabalhar assim, conseguem até mesmo diagnosticar erros de correspondência de tipos em funções com listas argumentos variáveis e que são definidas no padrão do C (particularmente
printf () e
scanf () e suas correlatas). No caso do GCC (gcc e g++), eu sempre recomendo usar as seguintes opções de compilação:
-Wall -Werror -O2 -pedantic .