Ir ao conteúdo
  • Cadastre-se

C Programa para abreviação de nomes


Visitante

Posts recomendados

Bom dia/tarde/noite pessoal,

estou desenvolvendo um programa que abrevia nomes e venho tendo algumas dificuldades.

O programa tem certas restrições de desenvolvimento, como não poder usar vetores auxiliares, ou seja, todas as alterações devem ser feitas no vetor original, que no caso chamei de nome[], e também não posso usar funções "prontas" do próprio C, como por exemplo strlen() e etc. Abaixo alguns detalhes do que consegui desenvolver:

 

1. O programa deve manter o primeiro e último nome sem alterações.

    Ex1: Maria Paula Estevão ----> Maria P. Estevão

    Ex2: Carlos de Oliveira Filho ----> Carlos de O. Filho

2. O programa não abrevia preposições de nome.

3. O programa consegue abreviar nomes com 3 "elementos" e com preposições. Ex. João Paulo da Silva ----> João P. da Silva

 

O único problema que não consigo resolver é abreviação com 4 ou mais "elementos" (não sei uma palavra melhor), como por exemplo "João Pedro da Silva Costa".

 

Segue o código:

 

#include<stdio.h>
void abrevia(char nome[]);
void desloca(char nome[]);
void apaga(char nome[]);

int main(void){
	char nome[]="João Pedro da Silva Costa";
	abrevia(nome);
	desloca(nome);
	puts(nome);
}

void abrevia(char nome[]){
	int i=0, ultimo=0;
	while(nome[ i ]){
		if (nome[ i ] == ' '){
			ultimo = i+1;
		}
		i++;
	}
	for (i=1; nome[ i ]; i++){
		if ((nome[ i ] >='A' && nome[i] <='Z') && (i != ultimo)){
			nome[i+1] = '.';
		}
	}
}

void desloca(char nome[]){
	int i=1, j=1, desloc=1;
	while(nome[ i ]){
		if(nome[ i ]=='.'){
			j = i+2;
			while(nome[j]!=' '){
				j++;
			}
		}else{
				nome[ i ]=nome[j];
				j++;	
			}
		}
		i++;
	}
}

 

A função abrevia(nome) identifica qual letra pertence ao último sobrenome para que ele não seja abreviado, coloca os pontos e espaços depois das letras maiúsculas que não são o primeiro nome e nem o último sobrenome, mas as outras letras que não foram sobrepostas continuam.

A função desloca(nome) deveria encontrar o próximo espaço depois do nome a ser abreviado e fazer o deslocamento dos elementos dos vetores para trás, para que o nome abreviado saia corretamente, porém quando digito, por exemplo, "Carlos de Oliveira Santos Filho", o puts() devolve o seguinte: Carlos de O. S. tos FIlho.

Percebi que o problema ocorre quando i se desloca e encontra o . do S (na função desloca()), mas não sei como resolver o problema. 

 

Será que alguém poderia me ajudar?

Desde já agradeço a atenção e a ajuda.

 

Link para o comentário
Compartilhar em outros sites

@PG19  Olá. Deu para fazer aqui. 

Devo dizer que não estou entendendo o que você quer fazer com while (nome).

A dica q daria para navegar por todos os índices do nome seria essa:

 

for (i = 0; i < strlen(nome); i++)

Outro ponto: Quando você procura pelas letras maiúsculas q estão no nome, faça a seguinte mudança:

 

if ((nome[i] >= 'A' && nome[i] <= 'Z') && (i != ultimo))

Mas devo dizer q sua forma de raciocinar está ótima. Bastou algumas pequenas mudanças como essas q mencionei para resolver o exercício.

Tem um outro ponto na função desloca(), seria fazer isso:

 

for (i = 0; i < strlen(nome); i++)
{
    if(nome[i] == '.')

Se você fazer essas mudanças é bem provável q resolva o exercício.

Com respeito a primeira dica q dei, fiz dessa forma todas as vezes q foi preciso navegar pelos índices no nome, deixando d fazer do modo como você vinha fazendo: while (nome)

 

Se quiser posso postar a resposta, mas acredito q com essas dicas você vai conseguir resolver o problema

Fica a seu critério essa questão de eu postar ou não a resposta p o exercício, mas recomendo você seguir essas dicas e com isso resolver sozinho o exercício.

Até 

Link para o comentário
Compartilhar em outros sites

@giu_d Acabei de descobrir que o [ i ] deixa a letra em itálico, e por isso alguns indices do código sumiram, mas o while(nome[ 'i' ]) seria para percorrer todo o vetor até o '\0', pois uma das restrições da atividade é não usar funções como strlen(), entre outros.

Link para o comentário
Compartilhar em outros sites

Tem um outro ponto na função desloca(): você está fazendo algo como: nome = nome[j].

Partindo do princípio q você está usando o for q comentei para navegar pelos índices do nome, o correto seria isso para facilitar mais um pouco:

nome[i] = nome[j];

Creio q se você seguir essas dicas q passei você resolve o exercício

Pra ser sincero pequei ele quase pronto

adicionado 1 minuto depois

@PG19  Ops... passou despercebida essa parte

Link para o comentário
Compartilhar em outros sites

@PG19  Agora ficou bem claro seu código do modo como postou.

Acredito q a questão aí seja alguma forma de navegar por todos os índices do nome, já q você não pode usar a função strlen().

Mas deu para fazer aqui. Só que para dar certo o algoritmo usei os nomes mencionados como exemplo para fazer o exercício.

A dica dessa vez q vou dar está na função abrevia, navegue nos índices do nome como você vem fazendo, mas nessa função faça uso de dois while como você fez. Só q é importante ressaltar que para o 1º while da função, inicie a variável i com 0. Já no segundo inicie a mesma variável com 1

Seria isso no segundo while da função abrevia:

 

i = 1;
while (nome[i])

Esse pequeno detalhe faz toda diferença para q o exercício funcione.

Deixe d usar o for na função desloca e faça uso de 2 while tal como mencionei e daí creio q resolve o exercício

adicionado 3 minutos depois

desculpa, me enganei, o uso de dois while seria na função abrevia()

Link para o comentário
Compartilhar em outros sites

@PG19  Na função desloca(), experimenta inicializar a variável 'i' com 0 e não com 1 como vem fazendo

adicionado 11 minutos depois

@PG19  Se não for difícil poste como ficaram suas funções. Assim fica mais fácil saber onde está ocorrendo o erro.

Link para o comentário
Compartilhar em outros sites

na função abrevia(), o primeiro while tem o 'i' inicializado com 0, já o segundo while, com 1. Na desloca(), com i=0, o puts devolve o seguinte: arlos de O.. S.ntos Filho para o nome Carlos de Oliveira Santos Filho.

 

Uma coisa que percebi é que na função desloca() é que em casos de abreviação de dois nomes, quando o if da função localiza o primeiro '.', a função começa a deslocar os outros elementos de forma correta, mas conforme i é incrementado no while, o mesmo vai achar o segundo '.' antes do término do deslocamento correto e já começa a deslocar o ultimo sobrenome, e por isso a saída fica toda errada. Não sei se deu pra entender do jeito que expliquei, mas se precisar posso tentar explicar de forma mais clara

void desloca(char nome[]){
	int i=1, j=1, desloc=1;
	while(nome[ i ]){
		if(nome[ i ]=='.'){
			j = i+2;
			while(nome[j]!=' '){
				j++;
			}
		}else{ //creio que o problema estaria nesse else, mas não tenho certeza
				nome[ i ]=nome[j]; 
				j++;	
			}
		}
		i++;
	}
}

 

adicionado 4 minutos depois
4 minutos atrás, PG19 disse:

@giu_d na função abrevia(), o primeiro while tem o 'i' inicializado com 0, já o segundo while, com 1. Na desloca(), com i=0, o puts devolve o seguinte: arlos de O.. S.ntos Filho para o nome Carlos de Oliveira Santos Filho.

 

Uma coisa que percebi é que na função desloca() é que em casos de abreviação de dois nomes, quando o if da função localiza o primeiro '.', a função começa a deslocar os outros elementos de forma correta, mas conforme i é incrementado no while, o mesmo vai achar o segundo '.' antes do término do deslocamento correto e já começa a deslocar o ultimo sobrenome, e por isso a saída fica toda errada. Não sei se deu pra entender do jeito que expliquei, mas se precisar posso tentar explicar de forma mais clara


void desloca(char nome[]){
	int i=1, j=1, desloc=1;
	while(nome[ i ]){
		if(nome[ i ]=='.'){
			j = i+2;
			while(nome[j]!=' '){
				j++;
			}
		}else{ //creio que o problema estaria nesse else, mas não tenho certeza
				nome[ i ]=nome[j]; 
				j++;	
			}
		}
		i++;
	}
}

 

 

Link para o comentário
Compartilhar em outros sites

@giu_d O correto seria Carlos de O. S. Filho. O programa não deve abreviar o primeiro nome e nem o último sobrenome. Portanto, se eu entrasse com Carlos Filho, a saída seria a mesma.

adicionado 6 minutos depois

 

@giu_d segue código completo

#include<stdio.h>
void abrevia(char nome[]);
void desloca(char nome[]);
void apaga(char nome[]);

int main(void){
	char nome[]="Carlos de Oliveira Santos Filho";
	abrevia(nome);
	desloca(nome);
	//apaga(nome);
	puts(nome);
	return 0;
}

void abrevia(char nome[]){
	int i=0, ultimo=0;
	while(nome[i]){
		if (nome[i] == ' '){
			ultimo = i+1;
		}
		i++;
	}
	i=1;
	while(nome[i]){
		if ((nome[i] >='A' && nome[i] <='Z') && (i != ultimo)){
			nome[i+1] = '.';
		}
		i++;
	}
}

void desloca(char nome[]){
	int i=0, j=1, desloc=1;
	while(nome[i]){
		if(nome[i]=='.'){
			j = i+2;
			while(nome[j]!=' '){
				j++;
			}
		}else{
			nome[i]=nome[j];
			j++;	
			}
		i++;
	}
}

 

Link para o comentário
Compartilhar em outros sites

@giu_d Com a ajuda de um amigo, a gente conseguiu fazer isso aqui 

#include<stdio.h>
void abrevia(char nome[]);
void desloca(char nome[]);
void copia(char nome[]);
int main(void){
	char nome[40];
	printf("Nome: ");
	gets(nome);
	abrevia(nome);
	copia(nome);
	puts(nome);
	return 0;
}

void abrevia(char nome[]){
	int i=0, ultimo=0;
	while(nome[i]){
		if (nome[i] == ' '){
			ultimo = i+1;
		}
		i++;
	}
	i=1;
	while(nome[i]){
		if ((nome[i] >='A' && nome[i] <='Z') && (i != ultimo)){
				nome[i+1] = '.';
		}
		i++;
	}
}

void copia(char nome[]){
	int i=0;
	while(nome[i]){
		if(nome[i] == '.' && nome[i+1]!= ' '){ 
			nome[i+1]=nome[i+2];
            desloca(nome);
		}
		i++;
    }
}

void desloca(char nome[]){
	int i=0;
	while(nome[i]){
		if(nome[i]==nome[i+1]){
			nome[i+1]=nome[i+2];
		}
 		i++;   
	}
	copia(nome);
}

talvez gaste bastante processamento por causa das funções se chamando toda hora, mas funciona!:)

Link para o comentário
Compartilhar em outros sites

@PG19  Maravilha. Valeu pelo empenho q você teve para resolver o exercício!

Rapaz, ficou um código bem trabalhado.

No meu caso, como estava vendo q tava meio assim, não tava saindo de forma alguma, resolvi dar um break, mas me surpreendeu voltar aqui e me deparar com a resposta. Valeu, amigo!

O interessante no exercício, do modo como ficou, é q agora a gente pode escolher nomes para usar no mesmo, com isso não é preciso usar o tal nome do cidadão q tava sendo usado hehe

Devo dizer q umas das coisas q pude aprender (na verdade inda não tinha feito assim por usar normalmente a função strlen() dentro de um for ) foi a maneira de percorrer todos os índices de uma string com o while

Agradeço por essa amigo

Abração!

Link para o comentário
Compartilhar em outros sites

@giu_d Imagina!
Eu que agradeço pelo seu esforço de me ajudar até agora, normalmente o pessoal desiste kkk
Fico feliz que tenha servido de aprendizado pra você, e agora dá certo pra todos os nomes :D
Um abraço e boa noite!

Link para o comentário
Compartilhar em outros sites

Ola..!

Estava acompanhando o desenvolvimento, e foi bom ter esperado.

Aguardei com uma solução pronta que postaria para comparação.

 

Nesta solução o ponto chave é o mesmo que já apresentado: copiar por cima do nome os nomes restantes assim abreviar.

Spoiler

/* Abreviar nomes */
#include <stdio.h>
void copiar_( char nome [], int a, int b ){
	while( (nome [b] = nome [a]) != '\0' ){
		++a;
		++b;
		}
	return;
	}
void abreviar_( char nome [] ){
	unsigned c, tmp;
	char offset;

	c = 0;
	while( (offset = nome [c]) != '\0' ){
		++c;
		if( offset == ' ' ){
			if( !('A' > (offset = nome [c]) || offset > 'Z') ){
				++c;
				tmp = c;
// escanear em busca de mais uma ocorrencia de espaco, caso nao
// encontre então se chegou no fim do nome
				while( (offset = nome [tmp]) != ' ' && offset != '\0' ){
					tmp++;
					}
// testa se este he ultimo dos nomes e sai logo depois
// se nao então troca a segunda letra por ponto
				if( offset == '\0' ){
					break;
					}else{
						if( nome [c] != ' ' ){
							nome [c] = '.';
							}else{
								--c;
								continue;
								}
						}
// e copia no restante do nome os proximos Nomes na sequencia.
				++c;
				copiar_( nome, tmp, c );
				}
			}
		}
	return;
	}
int main( void ){
	char nome [] = "Joaquim Jose da Silva Xavier";

	abreviar_( nome );
	puts( nome );
	return 0;
	}

 

 

Link para o comentário
Compartilhar em outros sites

@AnsiC Obrigada pela resposta! Não posso usar dois ou mais vetores nesse exercício, pois uma das restrições é que todas as alterações devem ser feitas no mesmo vetor, mas seu código é interessante!

Uma dúvida que tenho é como funciona o char msn[BUFSIZ], pois ainda não aprendi em aula e gostaria de saber mais sobre isso.

Link para o comentário
Compartilhar em outros sites

@PG19

18 horas atrás, PG19 disse:

Obrigada pela resposta!

Por nada, postei para que outros do fórum possam ver mais de uma perspectiva ou resolução do problema, ainda que a ideia principal para resolução seja a mesma: rescrever sobre o vetor de caracteres (string) do nome original.

 

18 horas atrás, PG19 disse:

Não posso usar dois ou mais vetores nesse exercício, pois uma das restrições é que todas as alterações devem ser feitas no mesmo vetor, mas seu código é interessante!

Mas o meu código cumpre com a essa exigência, você poderia me indicar qual parte do algoritmo você enxerga o contrário.

Talvez possa ter confundido os nomes das variáveis no parâmetro da função como sendo novo vetor:

Por exemplo:
 

int func( char nome [], char * nome_ );



//Chamar a função assima

char nome [10] = "ANSIC"

func( nome, nome );

 

No caso acima o vetor nome é o mesmo em ambos os parâmetros, e não dois vetores.

Para evitar tal confusão com relação aos conceitos editei o poster anterior. Obrigado

 

 

18 horas atrás, PG19 disse:

Uma dúvida que tenho é como funciona o char msn[BUFSIZ]

char : Tipo primitivo de 8 bits;

BUFSIZ: é macro contendo o tamanho mínimo de buffer que é 1024,  interno a biblioteca stdio;

msn: nome do objeto char (*)[1024];

 

ou seja, char msn [BUFSIZ] é um vetor de largura igual a 1024 do tipo char.

Link para o comentário
Compartilhar em outros sites

Vi a pergunta na semana passada e respeitando as restrições que citou iria sugerir o uso de ponteiros, mas como você chegou a uma solução antes de que eu expusesse a ideia resolvi esperar até que o exercício fosse entregue o que assumo que já ocorreu.

 

Estou postando as soluções abaixo somente a titulo de conhecimento ao contrário de explicar ponto a ponto como normalmente aconteceria.

 

Com ponteiros:



#include <stdio.h> char* proximoEspaco(char *nome) { //enquanto o valor apontado por nome for diferente de zero while(*nome) //Avança o ponteiro para o proximo caractere e verifica se ele é um espaço if(*++nome == ' ') //Caso seja retorna um ponteiro para ele return nome; //Alternativamente //while(*nome != '\0') { // nome++; //ou ++nome; //ou nome = nome + 1; //nessa situação não faz diferença // if(*nome == ' ') // return nome; //} //Caso chegue ao final da string returna NULL return NULL; } void deslocar(char *de, char *para) { //Copia o valor apontado por de em para, verifica se o valor apontado por para é diferente de 0 e avança ambos os ponteiros. // Ex: Jet Von Li que este ponto seria //Passo1: Jet V.n Li // 0123456789 // ^^ // parade <- Obs: quero indicar as variaveis para e de e não a palavra parade //Passo2: Jet V. Li // 0123456789 // ^^ // parade //Passo3: Jet V. LLi // 0123456789 // ^^ // parade //Passo4: Jet V. Lii // 0123456789 // ^^ // parade //Result: Jet V. Li while(*para++ = *de++); //Alternativamente //while(*para != '\0') { // *para = *de; // de++; // para++; //} } void abreviar(char *nome) { char *proximo; //Procura o espaço a partir do valor apontado por nome e caso encontre procura // um proximo espaço a partir do ponteiro retornado //Caso encontre ambos continua while( (nome = proximoEspaco(nome)) && (proximo = proximoEspaco(nome)) ) //Se a quantidade de caracteres entre eles for igual ou superior a 3 // Pois por mais que seja improvável, caso exista menos de dois caracteres // alem do espaço não existe local nem motivo para colocar o ponto // Ex: Jon A Long // 0123456789 // nome no primeiro espaço 3, proximo no segundo espaço 5 // 5 - 3 = 2 //Avança o ponteiro nome e verifica se o valor armazenado está entre A e Z if(proximo - nome >= 3 && *++nome >= 'A' && *nome <= 'Z') { //Avança o ponteiro nome e armazena o ponto no local *++nome = '.'; //Desloca o texto do proximo espaço até a posição seguinte ao ponto(nome + 1) deslocar(proximo, nome + 1); } //Alternativamente //nome = proximoEspaco(nome); //proximo = proximoEspaco(nome); //while(nome != '\0' && proximo != '\0') { // if(proximo - nome >= 3) { // nome++; //ou ++nome; //ou nome = nome + 1; //Não faz diferença // if(*nome >= 'A' && *nome <= 'Z') { // nome++; //ou ++nome; //ou nome = nome + 1; //Não faz diferença // *nome = '.'; // deslocar(proximo, nome + 1); // } // } // nome = proximoEspaco(nome); // proximo = proximoEspaco(nome); //} } int main() { char nome[] = "Joaquim Jose da Silva Xavier"; printf("%s -> ", nome); abreviar(nome); printf("%s\n", nome); return 0; }

 

Com índices:



#include <stdio.h> int proximoEspaco(char *nome, int pos) { //enquanto o nome[pos] for diferente de zero while(nome[pos]) //incrementa a posição para o proximo caractere e verifica se ele é um espaço if(nome[++pos] == ' ') //Caso seja retorna um a posição dele return pos; //Alternativamente //while(nome[pos] != '\0') { // pos++; //ou ++pos; //ou pos = pos + 1; //nessa situação não faz diferença // if(nome[pos] == ' ') // return pos; //} //Caso chegue ao final da string returna 0 que embora seja uma posição valida // nunca seria um possível valor visto que 0 é o menor valido para pos // e a função busca o proximo. return 0; } void deslocar(char *nome, int de, int para) { //Copia o valor da posição de na posição para, compara o valor da posição para com 0 e incrementa ambas as posições // Ex: Jet Von Li que este ponto seria //Passo1: Jet V.n Li // 0123456789 // ^^ // parade <- Obs: quero indicar as variaveis para e de e não a palavra parade //Passo2: Jet V. Li // 0123456789 // ^^ // parade //Passo3: Jet V. LLi // 0123456789 // ^^ // parade //Passo4: Jet V. Lii // 0123456789 // ^^ // parade //Result: Jet V. Li while(nome[para++] = nome[de++]); //Alternativamente //while(nome[para] != '\0') { // nome[para] = nome[de]; // de++; // para++; //} } void abreviar(char *nome) { int atual = 0, proximo = 0; //Procura um espaço a partir da posição atual e caso encontre // procura um proximo espaço a patir da posição retornada //Caso encontre ambos continua while( (atual = proximoEspaco(nome, atual)) && (proximo = proximoEspaco(nome, atual)) ) //Se a quantidade de caracteres entre eles for igual ou superior a 3 // Pois por mais que seja improvável, caso exista menos de dois caracteres // alem do espaço não existe local nem motivo para colocar o ponto // Ex: Jon A Long // 0123456789 // atual no primeiro espaço 3, proximo no segundo espaço 5 // 5 - 3 = 2 //Avança a posição atual e verifica se nome[atual] está entre A e Z if(proximo - atual >= 3 && nome[++atual] >= 'A' && nome[atual] <= 'Z') { //Avança a posição atual e armazena o ponto em nome[atual] nome[++atual] = '.'; //Desloca o texto do proximo espaço até a posição seguinte ao ponto(atual + 1) deslocar(nome, proximo, atual + 1); } //Alternativamente //atual = proximoEspaco(nome, atual); //proximo = proximoEspaco(nome, atual); //while(atual != 0 && proximo != 0) { // if(proximo - atual >= 3) { // atual++; //ou ++atual; //ou atual = atual + 1; //Não faz diferença // if(nome[atual] >= 'A' && nome[atual] <= 'Z') { // atual++; //ou ++atual; //ou atual = atual + 1; //Não faz diferença // nome[atual] = '.'; // deslocar(nome, proximo, atual + 1); // } // } // nome = proximoEspaco(nome, atual); // proximo = proximoEspaco(nome, atual); //} } int main() { char nome[] = "Joaquim Jose da Silva Xavier"; printf("%s -> ", nome); abreviar(nome); printf("%s\n", nome); return 0; }

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