Ir ao conteúdo

C Dificuldade com variavel char


Ir à solução Resolvido por devair1010,

Posts recomendados

Postado

Tenho um programa que preciso identificar a quantidade de vogais e consoantes de cinco palavras porém so esta mostrando da primeira palavra

como posso mostrar de todos? 


void conta(char *str, int *vog, int *con){
    char *s = str;
    *vog = *con = 0;
    while(*s){
        char c = tolower(*s);
        if(c >= 'a' && c <= 'z'){
            if(c == 'a' || c == 'e' ||
                c == 'i' || c == 'o' ||
                c == 'u'){
                *vog += 1;
            }else{
                *con += 1;
            }
        }
        *s++;
    }
}

int main()
{
    int v, c;
  	char str[5][100];
  	int i, vowels, consonants;
  	i = vowels = consonants = 0;

    int count;
	for (i=0;i<5;i++)
        {
        	printf ("\nescreva uma string: ");
        	gets (str[i]);
        }

        printf ("\nas strings que voce digitou foram:\n");
	for (i=0;i<5;i++)
        printf ("%s\n",str[i]);


conta(str, &v, &c);
    printf("Vogais = %d\nConsoantes = %d\n", v, c);
  	return 0;
}

 

  • Obrigado 1
  • Solução
Postado

@carlinhos andrade    na hora de enviar as string's para a função  , conta  ,  você precisa indicar qual string está enviando , e para isso você pode usar hum Loop , e seu código poderia ser assim  :

#include <stdio.h>
#include <ctype.h>
void conta(char *str, int *vog, int *con){
    char *s = str;
    *vog = *con = 0;
    while(*s){
        char c = tolower(*s);
        if(c >= 'a' && c <= 'z'){
            if(c == 'a' || c == 'e' ||
                c == 'i' || c == 'o' ||
                c == 'u'){
                *vog += 1;
            }else{
                *con += 1;
            }
        }
        *s++;
    }
}

int main()
{
    int v, c;
    char str[5][100];
    int i, vowels, consonants;
    i = vowels = consonants = 0;
    int qtd;
    for (i=0;i<5;i++)
    {
        printf ("escreva uma string: ");
        gets (str[i]);
    }
    printf ("\n\nas strings que voce digitou foram:\n");
    for (i=0;i<5;i++)
        printf ("%s\n",str[i]);
    printf("\n");
    for(i=0;i<5;i++)
    {
        conta(str[i], &v, &c);
        printf(" %s Tem  : \n",str[i]);
        printf(" Vogais -----: %3d\n",v);
        printf(" Consoantes -: %3d\n\n", c);
    }
    return 16;
}

 

  • Curtir 1
  • Obrigado 1
Postado
17 horas atrás, carlinhos andrade disse:

*s++;

 

É só isso que está errado. O código está funcionando, mas isto está errado. O certo é escrever apenas
 

	s++;


ou mesmo

	s += 1;


Tire esse asterisco daí. Você quer incrementar o ponteiro para que avance para a próxima letra. No fundo esses operadores bonitinhos x++, ++x, --x, x-- são uma bobagem. A ideia era tornar o código mais compacto e em alguns casos funciona. Um caso em que funciona é quando usado numa expressão de controle de um while(), porque fica dentro da expressão e assim pode simplificar o loop: Incrementar o ponteiro fica dentro da própria expressão de controle do while(). Mas é arriscado demais porque o costume de usar isso pode gerar erros que são o d1@b0 pra achar. Isso acaba indo nos argumentos de função, dentro de expressões, em chamadas a printf()... 

Um exemplo comum é usar isso dentro de um printf() e depois tirar o printf() ou mudar de lugar, sem perceber que dentro dele tem um comandinho desses --isso ou ++aquilo que vai sumir ou mudar de lugar.

 

Qual o problema?
 

Por exemplo aqui: s++ usa o valor de s na expressão e depois incrementa o valor de s. * tem prioridade inferior a ++. Então é como escrever *(s++); 

Aqui então incrementa o ponteiro s e usa o * para pegar o valor que tem lá. E nada faz com esse valor. Um erro aqui inofensivo. Mas um erro.

 

Um exemplo o seu código:

void conta(const char *str, int *vog, int *con){
    const char *s = str;
    *vog = *con = 0;
    char teste = 0;
    while(*s){
        char c = tolower(*s);
        if(c >= 'a' && c <= 'z'){
            if(c == 'a' || c == 'e' ||
                c == 'i' || c == 'o' ||
                c == 'u'){
                *vog += 1;
            }else{
                *con += 1;
            }
        }
        teste = *s++;
        printf("valor de *s++: %c\n", teste);
        printf("valor de *s: %c\n", *s);
    };
};

 

Apenas declarei teste, um char, para ver o que resultaria daquela expressão...

 

Eis o que mostra para "azul":
 

valor de *s++: a
valor de *s: z
valor de *s++: z
valor de *s: u
valor de *s++: u
valor de *s: l
valor de *s++: l
valor de *s: 
Para "azul" contou 2 vogais e 2 consoantes

 

E veja que depois de ler o 'l' ainda dentro do loop o ponteiro s fica apontando para o '\n'. Num outro contexto, se fosse um vetor de estruturas, poderia estar apontando para FORA do espaço alocado e acabar em um crash.

 

Sobre seu programa

 

  • Ao postar um problema poste o programa completo. Incluídos os #define e #include. Assim quem estiver disposto a ajudar e quiser testar seu código não tem que ficar adivinhando quais headers incluiu, por exemplo.
     
  • main() deve ser sempre a primeira função de seu programa. Vai gostar disso quando seu programa for grande ou estiver lendo um programa que não foi você que escreveu.
     
  • em geral deixe main() em um arquivo separado, para não ficar compilando a toa todas as funções do programa só porque mudou uma linha em main(), e vice-versa. Por exemplo:
     
    int main()
    {
        const char* teste = "azul";
      	int consonants = 0;
      	int vowels = 0;
    
        conta( teste, &vowels, &consonants );
        printf("\
    Para \"%s\" contou %d vogais e %d consoantes\n",
            teste, vowels, consonants);
      	return 0;
    }

     

  • esse código serve para o teste que mostrei. Não precisa compilar a função conta() só porque mudou main(), certo?
  • declare variáveis de controle DENTRO do for(). Nunca deixe uma variável com um nome desses, i, solta e válida durante todo o seu programa. É uma bomba relógio.
  • não declare mais de uma variável por linha. É grátis usar mais linhas. E só ajuda.
  • entenda que uma declaração declara nomes. Esses nomes podem ser qualquer coisa, mas se declaram nomes, identificadores. Então nessa declaração por exemplo
     
    void conta(char *str, int *vog, int *con);
     

          

conta é (void)(char* ,int* ,int* );
vog é int*,
con é int*

e assim está declarando
 

    int*     vog;
    int*     con;

por exemplo. É provavelmente mais expressivo declarar o que de fato é. É claro que em main() argv é char**. Então *argv é char*, **argv é um char, a primeira letra do nome do programa. MAs argv é char**.
         

  • NUNCA use gets(). Foi marcada como obsoleta há décadas e é um desastre: não tem como controlar o tamanho do que vai ler: é uma avenida para injeção de código ---  hacking --- e pode cancelar seu programa a toa: basta o cara digitar mais do que cabe na string e seu programa já era. Use o óbvio:
     
    	fgets(nome[i],100,stdin);

    no seu caso. E o computador controla a leitura e não deixa estourar a capacidade.
     
  • nunca leia valores do teclado durante os testes de seu programa. Só atrasa e você pode acabar não fazendo os testes mais importantes.

    Veja esse vetor:
     
      	const char* teste[] =
          {
              "azul",
              "a z u l",
              "",
              "%%%%%%%%",
              "a",
              "z"
          };

     

 Essas strings tem casos comuns importantes de teste que você pode ir editando e repetindo sempre, sem ter que ficar parado em frente ao teclado digitando num menu por exemplo. Isso é o que importa para entregar seu projeto e receber sua nota ou emitir sua nota fiscal e cobrar o trabalho: testar o mais possível o mais cedo possível. Uma strong vazia? Só símbolos? Uma vogal só? uma consoante só? Essas coisas...

E não precisa nem contar. Essa expressão sempre dá o total de testes a fazer:

	    int n = sizeof(teste)/sizeof(char*);


Veja essa saída:

 

6 testes:

01/06   Para "azul" contou 2 vogais e 2 consoantes
02/06   Para "a z u l" contou 2 vogais e 2 consoantes
03/06   Para "" contou 0 vogais e 0 consoantes
04/06   Para "%%%%%%%%" contou 0 vogais e 0 consoantes
05/06   Para "a" contou 1 vogais e 0 consoantes
06/06   Para "z" contou 0 vogais e 1 consoantes

 

Esse trecho de código chama a função para todos os valores naquele vetor, e mostra o quadro acima. Sem prompt, e sem digitar nada:
 

    int n = sizeof(teste)/sizeof(char*);
 	printf ( "\n%d testes:\n\n", n );
    for (int i=0;i<n;i++)
    {
        conta( teste[i], &v, &c );
        printf("\
%02d/%02d\tPara \"%s\" contou %d vogais e %d consoantes\n",
        1+i,n, teste[i], v, c);
    }; // for()

 

Espero que dê pra entender a diferença. Eis o programa de teste

 

Spoiler


#include <ctype.h>
#include <stdio.h>

void conta(const char*, int*, int* );

int main()
{
  	const char* teste[] =
      {
          "azul",
          "a z u l",
          "",
          "%%%%%%%%",
          "a",
          "z"
      };
    int v = 0;
    int c = 0;

    int n = sizeof(teste)/sizeof(char*);
   	printf ( "\n%d testes:\n\n", n );
	for (int i=0;i<n;i++)
    {
        conta( teste[i], &v, &c );
        printf("\
%02d/%02d\tPara \"%s\" contou %d vogais e %d consoantes\n",
        1+i,n, teste[i], v, c);
     }; // for()
  	return 0;
};

void conta(const char *str, int *vog, int *con){
    const char *s = str;
    *vog = *con = 0;
    while(*s){
        char c = tolower(*s);
        if(c >= 'a' && c <= 'z'){
            if(c == 'a' || c == 'e' ||
                c == 'i' || c == 'o' ||
                c == 'u'){
                *vog += 1;
            }else{
                *con += 1;
            }
        }
        s++;
    };
};

/*
https://www.clubedohardware.com.br/forums/topic/
1499669-dificuldade-com-variavel-char/
*/

 

 

  • Curtir 1

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!