Abreviando nomes em C.

557 views
Skip to first unread message

Rubens M

unread,
Jun 9, 2013, 1:15:05 PM6/9/13
to DeAlunoP...@googlegroups.com
Opa, galera.
Então, estou fazendo uma lista de exercicios de strings aqui e tava indo bem até esse exercicio que encontrei:

* Faça um programa que receba nomes de pessoas e gere o login conforme os exemplos abaixo. As palavras e, de, da, do,
das e dos deverão ser suprimidas do login.
Entrada – Maria José Pereira
Saída – mjpereira
Entrada – Pedro Paulo da Silva
Saída – ppsilva

Ou seja, ele quer abreviar todos os primeiros nomes e deixar o ultimo por completo e todas em minusculo...
Tentei fazer algo aqui, mas nao tenho nem ideia de como remover letras e deixar somente as primeira, procurei alguma função q fizesse isso mas nao encontrei...
Aí o codigo da vergonha (hehe) que eu tentei fazer:


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


main () {
    
     char nome[100], copia;
     int i, espacos=0;
    
     printf ("Digite um nome: ");
     gets(nome);
    
     for (i=0; i<=strlen(nome); i++) {
         if (nome[i] == 32) {espacos++;
         nome[i+1] = copia;}
}

     else printf ("%c%c", nome[0], copia);
    
     system ("pause");
    
}


Se alguem puder me ajudar, fico muito agradecido!
Valeu.

Ítalo Grossi

unread,
Jun 10, 2013, 8:08:38 AM6/10/13
to
uuuhh..

Esse programa requer algumas dezenas de linhas para ser implementado.

Vou considerar que você esteja ok com manipulação de string na Linguagem C... principalmente na parte mais "crua" da manipulação.
Existem diversas maneiras de se fazer esse programa vou listar as etapas que acredito necessárias para fazer a implementação de modo mais simples possível.

Como disse é um programa que vai requerer digitar bastante e quebrar um pouco a cabeça.. baseado na lógica abaixo tente implementar o código e a medida que for aparecendo dúvidas vai postando aqui.

Passo 1 (fácil)
Ler o nome completo do usuário.

Passo 2 (Médio)
O nome de login não inclui as palavras "do", "da" "dos" "das" "de"
Por exemplo: Se o nome digitado for Maria das Graças será necessário ignorar a string "das" para criar o login.

O objetivo da segunda etapa é criar um filtro que vai alterar a string contendo o nome do usuário caso as strings "do ", "da " "dos " "das " "de " estejam contidas no nome.

Segue um código pra fazer isso.
No programa abaixo removerSubstring faz o serviço que você precisa.. Basta implementar no seu código controlando todos os casos "do ", "da " "dos " "das " "de ".

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


int main ()
{
   
void removerSubstring(char *s,const char *toremove);
   
char string1[] = "Maria da Padaria";
   
    removerSubstring
(string1, "da ");
       
    printf
("Nova string %s\n", string1);
   
   
return 0;
}


//Essa funcao remove a string informada por "remover" de "s"
void removerSubstring(char *s,const char *remover)
{
   
while((s = strstr(s,remover)) != NULL)
        memmove
(s, s + strlen(remover), 1 + strlen(s+strlen(remover)));
}


Passo 3(Médio)
Agora você já tem uma string que eliminou qualquer string que não seja válida para criar o login. Vamos agora criar uma outra função para passar qualquer caractere que seja maiúsculo para minúsculo.

Utilize o código abaixo se quiser para criar essa função

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


int main(void){
   
   
char str[20];
   
int i;
   
    printf
("Digite uma string com letras maiusculas e minusculas: ");
    fgets
(str, 20, stdin);
   
    printf
("Voce digitou: %s", str);
   
   
for(i = 0; i <= strlen(str); ++i){
       
if(str[i] >= 65 && str[i] <= 90){
            str
[i]=str[i]+32;
       
}
   
}
   
    printf
("Apenas com letras minusculas: %s",str);
   
   
return 0;
}

Intervalo

Antes de prosseguir teste o seu código com diversos nomes.. O código que você tem até agora deve ser suficiente para ler qualquer nome que o usuário digitar, remover qualquer palavra que não seja permitida como parte do login e converter qualquer caractere maiúsculo para minúsculo. Enquanto essas 3 etapas não estiverem funcionando não prossiga com o código.

Isso quer dizer que nos exemplos abaixo o seu programa deve ser capaz de:

Maria das Morena -> maria morena
Pedro Cardoso -> pedro cardoso
HAUhau -> hauhau
etc etc

Passo 4(Complicado)

Agora você deve criar a última função que irá converter a string perfeitamente formatada em um login.

Vamos revisar a lógica pra isso.
O último nome será mantido intacto e qualquer outro nome será abreviado apenas com a primeira letra.

Novamente existem dezenas de maneira de fazer isso mas acho que essa será a mais fácil... não sei se é a mais eficiente mas ao meu ver a menos trabalhosa.

- crie uma função para contar quantos caracteres a string possui excluindo o caractere nulo. Esse vídeo pode te ajudar a obter esse resultado.

- Crie uma variável auxiliar que irá contar quantos quantos espaços a string possui.. o valor inicial dessa variável será 0.
- Agora que você sabe quantos caracteres a string possui crie um laço decrescente.. ou seja...que irá ler do último caractere até o primeiro caractere da string.

A cada execução do laço for você deve escrever os caracteres lidos em uma outra string, que vamos chamar de LOGIN(a string LOGIN inicialmente vai conter o login invertido)até encontrar o caractere espaço.. Quando o caractere lido for um espaço quer dizer que você terminou de ler o último nome do usuário por completo. Para fazer esse controle utilize a variável auxiliar que falei pra você criar ali em cima.

****Pausa - Então até agora você tem uma nova string chamada LOGIN que contem o último nome do usuário totalmente em minúsculas invertido.

O laço for continuará a ser executado até o primeiro caractere da string.. Então agora os demais controles que você deve fazer:

Você precisará de uma outra variável auxiliar.
Essa variável auxiliar irá conter o caractere lido na execução anterior do laço for.

Por exemplo:
Se o laço estiver lendo em forma decrescente a string "la le".
Na primeira execução o ciclo irá ler 'e' e a variável auxiliar não irá conter nenhum caractere.
Sa segunda execução o laço irá ler o caractere 'l' e a variável auxiliar irá conter o caractere 'e' (da leitura anterior).
Na terceira o laço irá ler o caractere ' ' e a variável auxiliar irá conter o caractere 'l'(da leitura anterior).
E assim por diante...

Isso irá ser útil para você saber se você está lendo a primeira letra de um nome.

A lógica é...
Se o caractere lido na execução atual do laço for ' ' (espaço) então escreva na string LOGIN o caractere da variável auxiliar que contem a letra lida anteriormente.

Esse processo irá se repetir até que você atinja o primeiro caractere da string. Quando você atingir o primeiro caractere apenas escreva o primeiro caractere direto na string LOGIN.

Passo 5 (Fácil)

Agora a sua string LOGIN contem o login do usuário.. o único detalhe é que ele está invertido.. então basta criar uma função que inverta os caracteres  e UALÁ.. você terminou o problema.

ufff.. Como disse vai requerer quebrar a cabeça e digitar bastante.
Se você encontrar algum erro nessa lógica sinta-se a vontade para adaptar ao seu gosto....acredito que isso deve funcionar mas como não escrevi o código pra esse programa pode ser que tenha me perdido em alguma etapa.

Boa sorte




Rubens M

unread,
Jun 10, 2013, 3:45:56 PM6/10/13
to DeAlunoP...@googlegroups.com
Opa, fala aí, ítalo.
Primeiramente, queria agradecer o tempo que tu levou pra escrever essas explicações todas pra mim.
Então, eu tentei fazer seguindo seus passos e empaquei no último passo e tive algumas dúvidas...

Aí vai algumas dúvidas:...

Você poderia me explicar o porque do uso do *(asterisco) antes das variaveis "s" e "remover" da função que vc postou?

   void removerSubstring (char *s,const char *remover)

{
       
    while((s = strstr(s,remover)) != NULL)
        memmove(s, s + strlen(remover), 1 + strlen(s+strlen(remover)));
}

outra... esse comando "memmove" q vc usou na funçao removerSubstring, procurei eles bastante mas não consegui entender muito bem o que ele faz... eu entendi que, como vc declarou lá embaixo: removerSubstring(nome, "da ");, ele vai remover a substring "da ", da string que eu recebo, só q não entendi muito bem esses parametros + 1 strlen(s+strlen(remover)) e s + strlen(remover).



Bom, por final... aí está o que eu consegui fazer:

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

void removerSubstring (char *s,const char *remover)

{
       
    while((s = strstr(s,remover)) != NULL)
        memmove(s, s + strlen(remover), 1 + strlen(s+strlen(remover)));
}

void letras_minusculas (char recebido[]) {
     int i;
     for (i=0; i<=strlen(recebido); i++) {
         if (recebido[i] >= 65 && recebido[i] <= 90) recebido[i] = recebido[i] + 32;
         }}






int main ()
{
    char nome[50];
    char login[50];
    char auxiliar[50];
    int i, n_caracteres=0, contador=0, espacos=0;

    printf ("Digite um nome: ");
    fflush(stdin);
    gets(nome);
   
    letras_minusculas(nome);
    removerSubstring(nome, "da ");
    removerSubstring(nome, "de ");
    removerSubstring(nome, "do ");
    removerSubstring(nome, "dos ");
    removerSubstring(nome, "das ");
   
    n_caracteres = strlen(nome);
   
   
    for (i=n_caracteres; i >= 0; i--) {
   
    if (espacos < 1) {login[0+contador] = nome[i];
    contador++;}
    if (nome[i] == 32) {auxiliar [0+espacos] = nome[i+1];
    espacos++;}

   
   
}
    printf("%c%s%s\n", nome[0],strrev(auxiliar), strrev(login));
    printf ("%s", strrev(login));

   
    system ("pause");
    return 0;
    }


Eu consegui fazer as letras iniciais aparecerem, porem nao conseguir armazenar os dados na string "login" como vc falou, tentei usar uma condiçao do espacos ser menor que 1 para ele pegar apenas a primeira palavra (de trás pra frente) e um contador pra poder armazenar as letras do nome recebido nas posições da string "login", só que parece que ela nao recebe nada...
e tambem há um pequeno problema em relação a alguns sobrenomes: se eu digite por exemplo: João Andrade Silva Gomes.
Como o "Andrade " possui o "de ", ele não vai armazenar a inicial "s" de "Silva" pois acho que há um conflito entre a primeira função que vc criou de retirar os "da, de, dos...". ficando: jag...
E, por ultimo, na variavel "auxiliar", ele armazena as iniciais corretamente, porem, ele armazena tambem a inicial do ultimo nome (que seria armazenado na variavel login), ou seja, se eu tivesse conseguido fazer o programa corretamente, ele armazenaria o ultimo nome (variavel login) e tambem a primeira inicial dele seria um dos vetores da string "auxiliar", fazendo com que houvesse 2 letras repetidas.
Exemplo:
Felipe Souza Gomes Junior:
fsgjjunior <-> o j foi escrito juntamente com o "junior", ficando 2 "j".


Bom, é isso. Sei que devo tar pedindo demais para você, mas eu tenho prova essa semana e me dei bastante mal na primeira (sou horrivel em programaçao hehe), então, se achar que é muito não precisa se preocupar com esse post e responda apenas quando tiver tempo etc...

Valeu, cara, agradeço de coração o esforço que tu tá tendo aí pra me ajudar!
Fica com Deus, abraços!



Ítalo Grossi

unread,
Jun 11, 2013, 7:35:12 AM6/11/13
to DeAlunoP...@googlegroups.com
O motivo para os asteriscos é porque em C um vetor de caracteres ou stirng são tradados como ponteiros à char.

Isso quer dizer que..

void umaFunacao(char vetor[]);

é visto na Linguagem C como :
void umFuncao(char *c);

Um vetor de caracteres como parâmetro de uma função nada mais representa que o endereço de memória do primeiro caractere do vetor.

Resumindo.. se você ver
void umaFunacao(char vetor[]);
ou
void umFuncao(char *c);

Amabas funções recebem uma string ou vetore de caractere... OU.. o endereço de memória do primeiro caractere do vetor.. É tudo a mesma coisa escrito de maneira diferente.


A função memmove recebe 3 parâmetros

O primeiro - Destino inicial onde a função vai mover dados
O segundo - A fonte de onde os dados serão movidos
Terceiro - Quantos dados serão movidos contando a partir do segundo parâmetro.

Observe o programa abaixo:
Preste bastante atenção em cada parâmetro
#include <stdio.h>
#include <string.h>


int main ()
{
    char str[] = "Pao com Mortadela";
    
    memmove (str + 4, str + 8, 10);
    
    puts (str);
    
    return 0;
}

1 - str + 4 Está apontando para o QUINTO caractere de str
p = 0
a = 1
o = 2
   = 3
c = 4

2 - str + 8 está apontando para o nono caractere de str e indica o ponto inicial de onde dados devem ser movidos para str + 4

3 - O último argumento 10 informa quantos caracteres devem ser copiados a partir de str + 8


O resultado do programa acima move a palavra motadela em cima da palavra com.
Os parâmetros passados a essa função foram apenas para fazer essa mágica funcionar :).


Vou ter um teste em alguns dias.. estou meio apertado com tempo essa semana... como disse requer sentar na frente do computador e quebrar um pouco a cabeça pra resolver esse exercício.

Se fizer alterações no código vá postando aqui.. eu tenti rodar seu código aqui mas não executa :/

Boa sorte no prova
Até mais ;)
Reply all
Reply to author
Forward
0 new messages