Ir ao conteúdo
  • Cadastre-se

C# problema em exercício com string


88games16

Posts recomendados

estou com dificuldade no seguinte problema tenho que ler uma frase e printar todas as palavras que tenham 3 ou + vogais 

 

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



int main(){

  
    char str[80];
    char str2 [20];
    int i,j,tam,qt;
    i=0;
    j=0;
    qt =0;
    for (j=0;j<20;j++){
        str2[j]='\0';
    }
    j=0;
    printf("digite a sequencia de strins: ");
    fgets (str,80,stdin); // frase digitada
    while (str[i]!='\0'){
        while (str[i]!=' '){
            str2[j] = str[i]; // copiando as palavras para um vetor 
            i = i+1;
            }
         while (str[i] == ' '){
                i=i+1;  
          }
        tam = strlen(str2);
        
        for (j=0;j<tam;j++){
            if ( str2[j] == 'a' || str2[j] == 'e' || str2[j] == 'i' || str2[j] == 'o' || str2[j] == 'u'){
                qt = qt+1;
            }
        }
        if (qt >=3){
            printf("palavra %s\n",str2);
        }
        
        for (j=0;j<20;j++){
            str2[j]='\0';
        }
        j=0;
        qt =0;
      

    }

    return 0;
}

 

Link para o comentário
Compartilhar em outros sites

@88games16 Se for permitido usar funções da linguagem, há um modo mais fácil de fazer isso.

Pode usar a função strtok para quebrar a frase em strings menores (em palavras) e então contar a quantidade de vogais na palavra atual. Se o resultado for 3 ou mais, só imprimir na tela essa palavra e depois mover o ponteiro do strtok para a próxima palavra.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Olá!

 

Você só precisa

  • imprimir as palavras com 3 ou mais vogais

Você então não precisa

  • se "lembrar" das palavras que não tenham ao menos 3 vogais
  • salvar palavra por palavra em outro vetor
  • se for salvar, ela tem que ter o mesmo tamanho que a linha inicial, então se str1 tem 80 str2 teria que ter ao menos 80 ou seu programa vai dar erro se testar com mais 20 (no seu caso)
  • mas não pode cancelar também com mais de 80 na frase

Pense assim: você nem mesmo precisa salvar a linha toda: basta:

  • ir lendo as letras
  • monta a palavra
  • se tem ao menos 3 vogais imprime
  • ao acabar a palavra continua lendo
  • ao acabarem as letras acabou o programa

Só isso. Acha que consegue escrever assim? 

adicionado 9 minutos depois

Não se esqueça que as vogais maiúsculas também tem direitos...

 

Link para o comentário
Compartilhar em outros sites

@arfneto o str2 tem 20 apenas pois uso esse vetor para ler cada palavra que foi digitada na frase e estou assumindo que cada palavra individualmente não será maior que 20 na forma que escrevi o código é para o vetor str2 ler cada palavra da frase verificar se a palavra tem ao menos 3 vogais e imprimir depois de cada print eu zero ele para ler a segunda palavra da frase porém não esta fazendo isso ele imprime a primeira palavra porém não continua não sei o que esta errado no código na cabeça esta certo 

Link para o comentário
Compartilhar em outros sites

20 minutos atrás, 88games16 disse:

@arfneto o str2 tem 20 apenas pois uso esse vetor para ler cada palavra que foi digitada na frase e estou assumindo que cada palavra individualmente não será maior que 20 na forma que escrevi o código é para o vetor str2 ler cada palavra da frase verificar se a palavra tem ao menos 3 vogais e imprimir depois de cada print eu zero ele para ler a segunda palavra da frase porém não esta fazendo isso ele imprime a primeira palavra porém não continua não sei o que esta errado no código na cabeça esta certo 

 

Entendo. Mas está seguro de que o enunciado te dá essa liberdade de supor limites? Se o instrutor testar seu programa apenas digitando um monte de letras seu programa vai cancelar...

 

Como eu te disse, você não precisa ler e salvar palavras e tal. Muito menos que isso. É como se seu programa ficasse parado vendo as letras passarem...

  • Começou uma palavra? Começa a contar as vogais
  • Terminou a palavra? se tem mais de 3 vogais imprime. Se não tem esquece tudo e começa de novo. Não se esqueça das vogais maiúsculas... Elas também tem direitos ;) 

Insisto: está fazendo muito mais que o necessário

  • Imprima a frase que você leu pra ir te guiando nos testes
  • Não precisa zerar a str2 a cada palavra. Você vai escrever as próximas palavras no mesmo lugar: basta colocar um único 0 quando acabar de copiar a palavra e estará ok
  • Teste seu programa com uma string local ao invés de ficar lendo: demora muito e fica mais difícil de reproduzir um erro

Veja

char*     linha1 = "      teste aaaaa AEITEstetee";
char *    linha2 = "teste";
char*     linha3 = "teste testea testea";

já são testes válidos pra sua rotina...

 

Use essas strings antes de passar a usar gets(). Vai progredir mais rápido e depois deixa as que já testou como comentário e continua... Acha que sabe fazer assim? quer um exemplo? 

 

Acho que seu programa não funciona se a cadeia de teste começar por brancos...

 

É mais simples ler uma letra por vez e não se preocupar com a linha, porque na verdade não faz diferença: veja seu loop em str tem que passar por possíveis várias ocorrências de str2...

 

Veja o exemplo acima linha3 por exemplo

adicionado 21 minutos depois

Veja a diferença de usar isso em seu próprio programa:

    i = 0;
    j = 0;
    qt = 0;
    // copia linha de teste sem usar strcpy()
    char* linha1 = "      teste aaaaa AEITEstetee";
    char* linha2 = "teste";
    char* linha3 = "teste testea testea";
    //
    i = strlen(linha1);
    for (j = 0; j <= i; j++)
    {
        str[j] = linha1[j];
    }
    printf("Linha de teste:\n[%s]\n", str);
    printf(" 0....*....0....*....0....*....0....*....0....*....0....*....0]\n");
    printf("           1         2         3         4         5         6]\n");
    /*
        // depois testa lendo do teclado. E um porre e demora demais
        j = 0;
        printf("digite a sequencia de strins: ");
        fgets(str, 80, stdin); // frase digitada
    */
    //if (!qt) return 0;
    while (str[i] != '\0')

Apenas acrescentei essas linhas antes do fgets(). Aí o programa roda com as linhas de teste. basta mudar a cópia no primeiro loop

    i = strlen(linha2);
    for (j = 0; j <= i; j++)
      str[j] = linha2[j];  

E imprime a linha que vai usar pro teste e uma "régua" com os números de coluna que pode precisar durante o teste já que tem muitos índices...

 

Veja para a linha2:

Linha de teste:
[      teste aaaaa AEITEstetee]
 0....*....0....*....0....*....0....*....0....*....0....*....0]
           1         2         3         4         5         6]

Depois pra usar outros testes pode digitar direto sobre o texto lá na declaração...

 

Continue escrevendo

 

Link para o comentário
Compartilhar em outros sites

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


int main(){

    char * str = "caixa cafe telefone casa";
    char str2 [20];
    int i,j,tam,qt;
    i=0;
    j=0;
    qt =0;
    for (j=0;j<20;j++){
        str2[j]='\0';
    }
    j=0;
    //printf("digite a sequencia de strins: ");
    //fgets (str,80,stdin); // frase digitada
    while (str[i]!='\0'){
        while (str[i]!=' '){
            str2[j] = str[i]; // copiando as palavras para um vetor
            i = i+1;

         }
         while (str[i] == ' '){
                i=i+1;
         }

        tam = strlen(str2);
        for (j=0;j<tam;j++){
            if ( str2[j] == 'a' || str2[j] == 'e' || str2[j] == 'i' || str2[j] == 'o' || str2[j] == 'u'){
                qt = qt+1;
            }
        }
        if (qt >=3){
            printf("palavra: %s\n",str2);
        }

        for (j=0;j<20;j++){
            str2[j]='\0';
        }
        j=0;
        qt =0;

    }

    return 0;
}

mesmo ja definindo uma frase ainda sim da errado só que não estou conseguindo achar o erro na lógica

Link para o comentário
Compartilhar em outros sites

Olá!

 

Muito bem. Assim vai progredir muito mais depressa... 

 

Definir a frase não vai corrigir nada, só vai acelerar a solução...  

Devia ter copiado o resto que eu coloquei lá, inclusive a "régua"

 

Antes de tudo: 

considere que o seu loop mais externo tem que consumir todos os caracteres da string de entrada. TODOS. Se você olhar para o que escreveu ele sequer faz isso...

  while (str[i] != '\0')
    {
        while (str[i] != ' ') {
            str2[j] = str[i]; // copiando as palavras para um vetor 
            i = i + 1;
        }
        while (str[i] == ' ') {
            i = i + 1;
        }
        tam = strlen(str2);

O segundo loop aí, esse que era pra copiar a palavra --- e não as palavras, como você escreveu --- vai "comer" a string inteira inclusive o \0....

 

Pense dessa maneira:

  • as letras estão vindo, até vir um \0 ou um fim de arquivo.
  • Cada letra pode ou não ser um espaço, e o significado de ser um espaço depende de eu estar já lendo uma palavra ou não.

Só isso

  • Só isso

 

adicionado 25 minutos depois

Veja a diferença de começar seu programa assim:

{
    char        str[80];
    char        str2[80];
    int i, j, tam, qt;
    i = 0;
    j = 0;
    qt = 0;
    // primeiras linhas de teste
    char* linha1 = "      teste aaaaa AEITEstetee";
    char* linha2 = "  testeee";
    char* linha3 = "teste testea testea";
    // copia uma
    i = strlen(linha2);
    for (j = 0; j <= i; j++)
        str[j] = linha2[j];
    //
    short t_str = (short) strlen(str);
    short ix = 0;
    printf("\n\nLinha de teste - tamanho = %d:\n\n[%s]\n", t_str, str);
    printf(" 0....*....0....*....0....*....0....*....0....*....0....*....0]\n");
    printf("           1         2         3         4         5         6]\n");
    while (str[ix] != '\0')
    {
        printf("[%d/%d]=[%c] (%d em decimal)\n", ix, t_str, str[ix], str[ix]);
        ix++;
    }

E ele imprimir isso

Linha de teste - tamanho = 9:

[  testeee]
 0....*....0....*....0....*....0....*....0....*....0....*....0]
           1         2         3         4         5         6]
[0/9]=[ ] (32 em decimal)
[1/9]=[ ] (32 em decimal)
[2/9]=[t] (116 em decimal)
[3/9]=[e] (101 em decimal)
[4/9]=[s] (115 em decimal)
[5/9]=[t] (116 em decimal)
[6/9]=[e] (101 em decimal)
[7/9]=[e] (101 em decimal)
[8/9]=[e] (101 em decimal)

Então você já sabe que ele leu a linha2 direitinho. Ela tem 9 letras. Tem 4 vogais. Na régua você vê que "testeee"começa na coluna 2 e as duas primeiras  estão em branco.

Nas linhas você as letras passando e os códigos delas....

A partir daí você constrói sua lógica. Use seu programa pra te ajudar.

Link para o comentário
Compartilhar em outros sites

@arfneto mas o primeiro loop ele vai ler ate '\0' como isso não vai ler a string toda ? 

e o segundo loop eu tenho que ler cada palavra da string ler ela toda ate o "espaço" que separa cada palavra

refiz o código e agora esta imprimindo só tem um problema se a ultima palavra tiver 3 vogais ou + imprime 

int main(){

   // char * str = "caixa jujuba casa bar telefone marinha melao";
    char str [80];
    char str2 [20];
    int i,j,tam,qt,tam2;
    i=0;
    j=0;
    qt =0;
    for (j=0;j<20;j++){
        str2[j]='\0';
    }

    printf("digite a sequencia de strinsca: ");
    fgets (str,80,stdin); // frase digitada
    printf("frase %s",str);
    while (str[i]!='\0'){
        j=0;
        while (str[i]!=' '){
            str2[j] = str[i]; // copiando as palavras para um vetor

            i = i+1;
            j = j+1;
         }
         if (str[i] == ' '){
            str2[j]='\0';
            i=i+1;
         }
        tam = strlen(str2);
        for (j=0;j<tam;j++){
            if ( str2[j] == 'a' || str2[j] == 'e' || str2[j] == 'i' || str2[j] == 'o' || str2[j] == 'u'){
                qt = qt+1;
            }
        }
        if (qt >=3){
            printf("palavra: %s\n",str2);
        }
        qt =0;

    }

    
    return 0;
}

 

Link para o comentário
Compartilhar em outros sites

Eu te disse no início que esse caminho é mais complicado. Você não precisa sequer salvar a linha de entrada porque o programa não tem memória.

 

Depois de ler toda a linha pode ter uma palavra ainda sendo lida e você pode ter que  que imprimir também

 

Você precisa tratar também

  • Se a linha começa  por espaços
  • Se a linha termina com espaços
  • Se a linha está toda em branco

 

 

Não entendi porque voltou a ler da entrada padrão se o seu programa não funciona ainda nem para as linhas de teste

// char * str = "caixa jujuba casa bar telefone marinha melao"; 
char str [80];

 

 

 

 

 

 

 

 

 

Link para o comentário
Compartilhar em outros sites

1 hora atrás, 88games16 disse:

só botei para ler entrada padrão para testar as modificações que fiz agora do jeito que está só não imprime a ultima palavra mas se tiver um espaço em branco ou qualquer coisa após ela a imprime tudo certo 

 

Entendo. 

Mas o objetivo de inserir aquelas linhas lá e deixar de ler --- porque demora e é chato de reproduzir --- é justamente facilitar os testes e salvar algumas condições significativas, como essas

    char* linha1 = "      teste aaaaa AEITEstetee";
    char* linha2 = "  testeee";
    char* linha3 = "teste testea testea";
    char* linha4 = "               ";
    char* linha5 = "";
    char* linha6 = "aaaaa aaa";
    char* linha7 = "  aaaaa aaa              ";

Claro que cada um tem seu estilo de fazer as coisas, mas parece estranho você testar outras coisas antes de seu programa funcionar com sua única linha de teste, e mais ainda você não criar simplesmente outras para testar.

 

Entendeu o que eu expliquei sobre a possível palavra interrompida pelo final da linha? Deve estar também faltando isso no seu caso...

 

Vou te dar um exemplo. O programa que eu te mostrei antes e que imprimia isso

Linha de teste - tamanho = 9:

[  testeee]
 0....*....0....*....0....*....0....*....0....*....0....*....0]
           1         2         3         4         5         6]
[0/9]=[ ] (32 em decimal)
[1/9]=[ ] (32 em decimal)
[2/9]=[t] (116 em decimal)
[3/9]=[e] (101 em decimal)
[4/9]=[s] (115 em decimal)
[5/9]=[t] (116 em decimal)
[6/9]=[e] (101 em decimal)
[7/9]=[e] (101 em decimal)
[8/9]=[e] (101 em decimal)

Varre todas as linhas de teste e conta certo os tamanhos e passa pelas letras todas.

Esse loop, que seria o seu loop em str:

    while (str[ix] != '\0')
    {
        printf("[%d/%d]=[%c] (%d em decimal)\n", ix, t_str, str[ix], str[ix]);
        ix++;
    }	// end while
    return 0;

Usando a mecânica que você criou, e as variáveis e tal. A partir daí você pode considerar o que eu disse antes: vem um caracter em str, que pode ou não ser um espaço.

  1. Se vem um espaço você tem duas situações: está procurando uma palavra
  2. ou está no meio de uma palavra.
  3. Se vem uma letra você tem duas situações: ou está procurando uma palavra ou
  4. está no meio de uma.

Só isso. E a qualquer momento pode acabar a linha e aí você tem duas situações:

  1. se estava procurando uma palavra: aí já era, porque não tem nada mais pra fazer e pode encerrar.
  2. se não estava procurando tem uma palavra sendo montada lá em str2 e você tem que processá-la. É o que provavelmente está faltando em sua solução


Voltando ao exemplo:

Se

você tinha um loop que varria a string e imprimia aquela tabela que está aí acima, e sabe que

o processamento de uma letra ou espaço é definitivo, que não há razão pra voltar atrás.

Então

não toque naquele índice do loop externo em outros loops porque só vai criar problema pra você controlar.

O loop original só imprimia o caracter, um por linha, como está aí, e incrementava o contador. Agora não queremos mais imprimir então comentamos a chamada a printf() porque ainda pode ser útil.

E testamos as 4 possíveis situações e pronto.  Quais 4? As que listei acima.

 

Então seria algo assim

 

ch-191010-loop-zoom.png.7cb3ba37651b15dfcd805f7065f8bd2d.png

 

Para 4 condições precisamos de dois if. Fica mais fácil se usarmos um indicador de estar ou não em uma palavra e vamos supor 

    int            em_palavra = 0;            // quando 1 indica que esta em uma palavra

E temos as 4. E por nada nesse mundo mexemos no índice externo, aquela variável ix no exemplo, i no seu programa

 

Veja as condições, com o seu programa

Para um branco

            // estaria  em uma palavra ja?
            if (em_palavra == 0)
            {    
                // um espaco: nao faz nada
            }
            else
            {    // estava lendo uma palavra: acabou
                em_palavra = 0;            // agora acabou a palavra
                str2[i_str2] = 0;        // termina a string
                if (nVogais > 2)        // essa sim
                {
                    printf("%s\n", str2);
                }    // end if
            }    // end if        

Para uma letra

            if (em_palavra == 0)
            {    // primeira letra de uma palavra nova
                nVogais = 0;            // zera o contador
                str2[0] = str[ix];        // salva a primeira letra
                i_str2 = 1;                // inicio da palavra
                em_palavra = 1;            // agora em uma palavra
                if (e_vogal(str[ix]))
                    nVogais = 1;        // comecou com vogal ja
                else
                    nVogais = 0;        // ok continua lendo
            }
            else
            {    // continua na palavra
                str2[i_str2] = str[ix];    // salva a primeira letra
                i_str2 = i_str2 + 1;
                if (e_vogal(str[ix]))
                    nVogais = nVogais + 1;        // comecou com vogal ja
            }    // end if

E no final?

Quase igual... Como vimos são só duas condições e em uma não é preciso fazer nada --- e por isso seu programa funciona quando não a linha tem brancos no final :D

    // aqui acabou a linha mas pode
    // ter uma palavra sem terminar
    if (em_palavra == 1)
    {
        str2[i_str2] = 0;        // termina a string
        if (nVogais > 2)        // essa sim
        {
            printf("%s\n", str2);
        }    // end if
    }

Funciona?

Claro. Mas como eu te disse é mais complicado assim: não precisa fazer isso tudo

adicionado 22 minutos depois

É claro que antes de tudo a gente quer testar aquelas com aquelas sete linhas e não ficar digitando e compilando toda hora então.. Eis um arquivo de teste com as sete linhas e esse seu programa usando os dois if e tal

Linha de teste - tamanho = 29:

[      teste aaaaa AEITEstetee]
 0....*....0....*....0....*....0....*....0....*....0....*....0]
           1         2         3         4         5         6]
aaaaa
AEITEstetee


Linha de teste - tamanho = 9:

[  testeee]
 0....*....0....*....0....*....0....*....0....*....0....*....0]
           1         2         3         4         5         6]
testeee


Linha de teste - tamanho = 19:

[teste testea testea]
 0....*....0....*....0....*....0....*....0....*....0....*....0]
           1         2         3         4         5         6]
testea
testea


Linha de teste - tamanho = 15:

[               ]
 0....*....0....*....0....*....0....*....0....*....0....*....0]
           1         2         3         4         5         6]


Linha de teste - tamanho = 0:

[]
 0....*....0....*....0....*....0....*....0....*....0....*....0]
           1         2         3         4         5         6]


Linha de teste - tamanho = 9:

[aaaaa aaa]
 0....*....0....*....0....*....0....*....0....*....0....*....0]
           1         2         3         4         5         6]
aaaaa
aaa


Linha de teste - tamanho = 25:

[  aaaaa aaa              ]
 0....*....0....*....0....*....0....*....0....*....0....*....0]
           1         2         3         4         5         6]
aaaaa
aaa

Procure ver como essas linhas foram escolhidas

Link para o comentário
Compartilhar em outros sites

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