Ir ao conteúdo

Posts recomendados

Postado

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.

 

Postado

@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é 

Postado

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

Postado

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

Postado

Coloquei alguns espaços nos indices i's para que não fique em itálico, talvez assim facilite um pouco a leitura

Postado

@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()

Postado

Troquei o for por while como você sugeriu, mas ainda continua dando errado, mesmo com os nomes usados como exemplo :(

Postado

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

Postado

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++;
	}
}

 

 

Postado

@PG19 Como deveria ficar a saída para esse nome Carlos de Oliveira Santos Filho?

Postado

@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++;
	}
}

 

Postado

A princípio na função desloca inicialize j com 0 para resolver o 1º nome

Postado

@giu_d agora o primeiro nome fica certo, mas o puts() devolve Carlos de O. S.ntos . Filho.
Ignore a variável desloc e a função apaga(), estava fazendo testes e esqueci de tirar do código

Postado

Rapaz. Não seria nada mal alguém dar uma ajudinha por aqui.

Q nome q resolveram dar para o cidadão também hehe

Postado

@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!:)

Postado

@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!

Postado

@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!

Postado

Abração! Na verdade vejo q o fator perseverança é q vai definir se você vai ter ou não sucesso em algo q se disponha a fazer

Boa noite

Postado

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;
	}

 

 

Postado

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

Postado

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

Postado

@AnsiC  Gostei da explicação com respeito a macro BUFSIZ, estava a ponto de perguntar a respeito disso mas a pergunta q eu iria fazer foi feita antes. Obrigado pela explicação!

Postado

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; }

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