Ir ao conteúdo
  • Cadastre-se
Josesousa

C Funcao que troca Nome CHAR Ponteiro

Recommended Posts

Boa tarde. Como vão?

 

Estou aprendendo ponteiros mas me deparei com umm dificuldade (estranha, já que fiz processo similliar com inteiros) em troca nomes por referencia.

 

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

main(){
    setlocale(LC_ALL,"Portuguese");
    char nome1[100], nome2[100];
    printf("Digite o primeiro nome: ");
    scanf("%s", nome1);
    printf("Digite o segundo nome: ");
    scanf("%s", nome2);

void troca_nome(char *nome1[100], char *nome2[100]);
troca_nome(&nome1, &nome2);

    printf("O nome 1 é o %s.\n", nome1);
    printf("O nome 2 é o %s.\n", nome2);
}
void troca_nome(char *nome1[100], char *nome2[100]){
    setlocale(LC_ALL,"Portuguese");
    char aux[100];
    int i, tam;
    tam=100;
    for(i=0;i<tam;i++){
        aux[i]=*nome1[i];
    }
    for(i=0;i<tam;i++){
        *nome1[i]=*nome2[i];
    }
    for(i=0;i<tam;i++){
        *nome2[i]=aux[i];
    }
  /*strcpy(aux, nome1);
    strcpy(nome1, nome2);
    strcpy(nome2, aux);*/

    printf("O primeiro nome  e o %s.\n", *nome1);
    printf("O segundo nome  e o %s.\n", *nome2);

}

Alguem tem ideia do que possa ser?

 

Desde de já, agradecido.

Compartilhar este post


Link para o post
Compartilhar em outros sites
49 minutos atrás, Josesousa disse:

char nome1[100], nome2[100];

Então, aqui acima nos temos a declaração de dois vetores, sabemos disso principalmente por conta da sintaxe

tipo-objeto nome-objeto[ quantidade ];

 

A parte interessante aqui é o nome-objeto, pois ele é um ponteiro, porém diferente dos ponteiros comuns esse ponteiro não pode ser modificado, ou seja não podemos fazer algo do tipo: nome1 = nome2; Fora essa limitação todas a demais propriedades de ponteiros são aplicáveis.

 

Disso vem:

void troca_nome(char *nome1[100], char *nome2[100]);    //# Os parâmetros estão errados

void troca_nome(char nome1[], char nome2[], int tamanho);
//# Agora sim, representação por meio de ponteiros notação de vetores
/**[!]
 * Isso já é o bastantes para se identificar um vetor ou matriz 
 * unidimensional do tipo char no parâmetro */

/* OU TAMBÉM */
void troca_nome(char *nome1, char *nome2, int tamanho); 
//# Agora sim, representação por meio de ponteiros notação de ponteiros
/**[!]
 * Isso já é o bastantes para se identificar um vetor ou matriz 
 * unidimensional do tipo char no parâmetro */

 

Contudo, se além de orientar os vetores nos parâmetros quisesse eu indicar que são matrizes literalmente faria assim:

void troca_nome(int tamanho, char nome1[tamanho], char nome2[tamanho]);  
// +1 notação de parâmetros com vetores ..

.

 

 

 

Entendeu?

adicionado 5 minutos depois
void troca_nome(char *nome1[100], char *nome2[100]);

Observação: Essa notação não está errada, só não está correta para o tipo de variável pela qual estais a passar. Porque essa notação é para vetores de ponteiros do tipo char, e não para vetores do tipo char. Percebe a diferença?

  • Amei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Alguns exemplos:

char var; // 1 variável do tipo char
char vars[100]; //vetor de char com comprimento 100 = 100 variáveis do tipo char
int n = 100;
char vars2[n]; //vetor de comprimento variável (o comprimento depende do valor de n quando o vetor é criado)
char vars3[] //vetor de comprimento flexível

char *pont;  //1 ponteiro do tipo char
char *pont2[100];  //100 ponteiros do tipo char

var = 'A'; 
pont = &var; //pont aponta para o endereço de memória de var
*pont == var; //'A' == 'A' logo é verdadeiro

strcpy(vars, "ABCDEF");
pont = vars; //pont aponta para o endereço de memória da primeira posição do vetor vars
*pont == vars[0]; // 'A' == 'A', logo é verdadeiro
*(pont + 1) == vars[1]; // 'B' == 'B', logo é verdadeiro
pont[1] == *(pont + 1); // verdadeiro pois indexação de vetores usa aritmética de ponteiros
pont[1] == vars[1]; //verdadeiro pois é a combinação dos 2 anteriores

 

Logo podemos fazer:

#include <stdio.h>

void func(char *pont){
    printf("%c\n", pont[0]);
    printf("%c\n", pont[1]);
}

int main(){
    char vet[3] = "AB";
    
    func(vet);
    
    return 0;
}

 

  • Obrigado 1
  • Amei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@AnsiCAte que entendi.

 

Eu mudei aqui os codigos na hora de chamar a funcao e na propria funcao, mas nao deu certo não.

 

Fiz da mesma forma aí. Eu estava tentando trocar (sugestivo)  as palalvras. Dessa forma a primeira ia para a segunda e vice versa. Como se tratar de um vetor de caracter, acho que deve ter que pegar posicao por posicao do vetor e guardar num vetor temporario. Mas nao sei o que.....

 

Vou continuar tentando aqui. Se conseguir mando o codigo. :thumbsup:

Compartilhar este post


Link para o post
Compartilhar em outros sites
11 minutos atrás, Josesousa disse:

@AnsiCAte que entendi.

 

Eu mudei aqui os codigos na hora de chamar a funcao e na propria funcao, mas nao deu certo não.

 

Fiz da mesma forma aí. Eu estava tentando trocar (sugestivo)  as palalvras. Dessa forma a primeira ia para a segunda e vice versa. Como se tratar de um vetor de caracter, acho que deve ter que pegar posicao por posicao do vetor e guardar num vetor temporario. Mas nao sei o que.....

 

Vou continuar tentando aqui. Se conseguir mando o codigo. :thumbsup:

Poste para avaliação apenas o que do primeiro código-fonte você mudou, daí nos orientamos se acertou ou se está próximo.

  • Confuso 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Aqui esta a funcao

void troca_nome(char *nome1, char *nome2){
    setlocale(LC_ALL,"Portuguese");
    char aux[100];
    int i, tam;
    tam=100;
    /*for(i=0;i<tam;i++){
        aux[i]=*nome1[i];
    }
    for(i=0;i<tam;i++){
        *nome1[i]=*nome2[i];
    }
    for(i=0;i<tam;i++){
        *nome2[i]=aux[i];
    }*/
    strcpy(aux, nome1);
    strcpy(nome1, nome2);
    strcpy(nome2, aux);

    printf("O primeiro nome  e o %s.\n", *nome1);
    printf("O segundo nome  e o %s.\n", *nome2);

}

 

adicionado 13 minutos depois

Acabei de refazer aqui, mas invés de mudar por referencia, mudei por valor. Deu certo!!!!

 

Entretanto, eu queria passar o ponteiro do vetor de caracteres para quando eu mudar ele na funcao, tambem ser mudado no corpo principal. Alguma ideia?

Compartilhar este post


Link para o post
Compartilhar em outros sites
void troca_nome(char *nome1, char *nome2){
  setlocale(LC_ALL,"Portuguese");
  
  char aux[100];
  
  strcpy(aux, nome1);
  strcpy(nome1, nome2);
  strcpy(nome2, aux);

  printf("O primeiro nome  e o %s.\n", nome1); /* -- Atenção aqui (%s) esse string
  de formatação precisa de um ponterio para char, sem colocar asterisco antes no 
  identificador no argumento. O correto é semelhante aos argumentos na função 
  strcpy.                                                                       *-*/
  printf("O segundo nome  e o %s.\n", nome2);  /* -- Mesma ocorrência que acima ^-*/
}

 

1 hora atrás, Josesousa disse:

Entretanto, eu queria passar o ponteiro do vetor de caracteres para quando eu mudar ele na funcao, tambem ser mudado no corpo principal. Alguma ideia?

Saiba que tantos os vetores que foram passados por argumento nos parâmetros quanto os da principal são os mesmos, e foram modificados. Experimente imprimi-los antes e depois da chamada da  função.

 

ATUALIZADO:

1 hora atrás, Josesousa disse:

Acabei de refazer aqui, mas invés de mudar por referencia, mudei por valor. Deu certo!!!!

Em C, todas as passagens são por valor, esse conceito de valor e referência pertence ao C++. Acho melhor não pensar nisso por enquanto.

  • Confuso 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@isrnick  então para eu conseguir mudar o vetor de char eu teria que pegar a primeira posicao ? E ir pegando as proximas posições.

 

void mudar(char *nome1, char *nome2){
    char aux[100];
    int i=0;
    /*strcpy(aux, *nome1);
    strcpy(*nome1, *nome2);
    strcpy(*nome2, aux);*/
    while(nome1[100]!='\0'){
        aux[i]=*nome1[i];
        i++;
    }
    aux[i]='\0';
    i=0;
    while(nome2!='\0'){
        *nome1[i]=*nome2[i];
        i++;
    }
    nome1[i]='\0';
    i=0;
    while(aux!='\0'){
        *nome2[i]=aux[i];
        i++;
    }
    nome2[i]='\0';

    for(i=0;i<100;i++)
    printf("O nome 1 é o %s.\n", *nome1[i]);
    for(i=0;i<100;i++)
    printf("O nome 2 é o %s.\n", *nome2[i]);

}

@AnsiC To entendendo nada do que você esta tentando passar. Nada que você fala esta funcionando aqui. (possivelmente estou errando em algo) mas mesmo assim, você esta falndo que esta errado, eu mudo e nao da certo.

  • Haha 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
2 horas atrás, Josesousa disse:

To entendendo nada do que você esta tentando passar. Nada que você fala esta funcionando aqui. (possivelmente estou errando em algo) mas mesmo assim, você esta falndo que esta errado, eu mudo e nao da certo.

Cara! Temos que prestar atenção em duas:

  1. Não existe passagem por referência em C.
  2. Quando declaramos um vetor, acessamos o seu item pela sintaxe de vetores. É uma questão de consistência ou se perde em entendimento:
    /* Declarando um Vetor de caracteres e Acessando um caractere          */
    
    /* Variáveis do Programa */
    char meu_nome[47];  /* --reservei um conjunto de tipos char x47 itens  */
    char letra;         /* --reservei um tipo char                         */
    
    /* Copiar AnsiC --> vetor: meu_nome                                    */
    strcpy(meu_nome, "AnsiC");
    
    /* Copiar a primeria letra/item no vetor: meu_nome                     */
    letra = meu_nome[0];  /* --atribui a primeria letra do vetor a variável*/
    
    if (meu_nome[0] == letra) {
      printf("%s","Sim iguais\n"); /* --a resposta é sim                   */
    }
    else {
      printf("%s","Nao iguais\n");
    }
    

    Você está insistindo no erro:

     

    2 horas atrás, Josesousa disse:

    for(i=0;i<100;i++)

      printf("O nome 1 é o %s.\n", *nome1[i]);

    for(i=0;i<100;i++)

      printf("O nome 2 é o %s.\n", *nome2[i]);

    Está colando asteriscos (sintaxe de ponteiros), mesmo depois de ter referenciado com sintaxe de vetor [], então você deve escolher uma com as duas "vira a maior bagunça". Nesses termos temos então: 

    printf("O nome 1 é o %c.\n", *(nome1 + i)); 

    ou assim:

    printf("O nome 1 é o %c.\n", nome1[i]);

    São duas maneiras para a mesma coisa, porém certa. É difícil aprender isso? Outra coisa quando desejar imprimir um caractere, use  %c, para imprimir todo um vetor/string use %s. No caso acima, você errou. "Em outros palavras, você não aprendeu a usar o printf, e quer entender ponteiros que é bem mais avançado que isso".

Boa Sorte!

***Até

 

Meu último ato é: Recomendar essa pagina de estudos >>> https://www.cprogressivo.net/

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não sei se conseguir se claro. Ma era isso que eu estava tentando. So que com nomes.

 

#include <stdio.h>

main (){
    int x, y;
    printf("Informe o valor 1.:\n");
    scanf("%d", &x);
    printf("Informe o valor 2.:\n");
    scanf("%d", &y);

    void troca(int *a, int *b);
    troca(&x,&y);
    printf("\n\n");
    printf("o valor de x e %d.\n", x);
    printf("O valor de y e %d.\n", y);

}
void troca(int *a, int *b){
    int aux;
    aux = *b;
    *b = *a;
    *a = aux;
    printf("o valor de x e %d.\n", *a);
    printf("O valor de y e %d.\n", *b);
}

Com nome e com vetores tambem.

  • Obrigado 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu tentei, mais não tenho jeito para coisa! Melhor é mesmo deixar a didática para os professores e exemplificar por código-fonte que é muito melhor +1000 palavras :3

#include <stdio.h>
void troca(int tamanho, char *stra, char *strb){
    char aux;
  
    for (int i = 0; i < tamanho; i++) {
      aux = *(stra + i);
      *(stra + i) = *(strb + i);
      *(strb + i) = aux;
    }/*
    printf("o valor de strx e %s.\n", strx);
    printf("O valor de stry e %s.\n", stry); */
}

int main(void)
{
  char nome1[100];
  char nome2[100];
  
  printf("%s","Entre com dois nomes? ");
  scanf(" %s%s", nome1,nome2 );
  
  printf("%s","Antes da troca\n\n");
  printf("1-%s\n2-%s\n", nome1,nome2);
  //
  troca(100, nome1, nome2);
  //
  printf("%s","Depois da troca\n");
  printf("1-%s\n2-%s\n", nome1,nome2);
  return 0;
}
  
  

Ou Assim:

#include <stdio.h>
void troca(int tamanho, char stra[tamanho], char strb[tamanho]){
    char aux;
  
    for (int i = 0; i < tamanho; i++) {
      aux = stra[i];
      stra[i] = strb[i];
      strb[i] = aux;
    }/*
    printf("o valor de strx e %s.\n", strx);
    printf("O valor de stry e %s.\n", stry); */
}

int main(void)
{
  char nome1[100];
  char nome2[100];
  
  printf("%s","Entre com dois nomes? ");
  scanf(" %s%s", nome1,nome2 );
  
  printf("%s","Antes da troca\n");
  printf("1-%s\n2-%s\n\n", nome1,nome2);
  //
  troca(100, nome1, nome2);
  //
  printf("%s","Depois da troca\n");
  printf("1-%s\n2-%s\n", nome1,nome2);
  return 0;
}
  
  

Então aí, 2/1000 maneiras de fazer um troca de strings.

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sobre:

3 horas atrás, AnsiC disse:

Não existe passagem por referência em C.

Não entendi... se não é por referência, então como a mudança persistiu?

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Minha maior duvida nesse exercicio era em relação a semelhanca a outro que ja tinha feito. 

Pois a funcao apenas cria uma copia que receberá os mesmos valores da funcao principal.

Para eu mudar os valores das variaveis da funcao principal na funcao troca, eu teria que ter o endereco de memoria para saber onde ela foi guardada. Ai dessa forma pode fazer as mudancas na funcao troca e mudar , consequentemente, os valores das variaveis da funcao principal.

 

Mas voce @AnsiC  fez sem usar ponteiros em 1 dos 2 modos que voce fez. (dos 1000 possiveis) So nao entendo porque funcionou dessa forma, mas com inteiros não.

 

  • Amei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Josesousa  Veja esse terceiro (dos mil modos hahaha) que usa ponteiros mas com a notação de vetores:

 

#include <stdio.h>
void troca(int tamanho, char *stra, char *strb){
    char aux;
  
    for (int i = 0; i < tamanho; i++) {
      aux = stra[i];
      stra[i] = strb[i];
      strb[i] = aux;
    }
}

int main(void)
{
  char nome1[100];
  char nome2[100];
  
  printf("%s","Entre com dois nomes? ");
  scanf(" %s%s", nome1,nome2 );
  
  printf("%s","Antes da troca\n\n");
  printf("1-%s\n2-%s\n", nome1,nome2);
  //
  troca(100, nome1, nome2);
  //
  printf("%s","Depois da troca\n");
  printf("1-%s\n2-%s\n", nome1,nome2);
  return 0;
}

 

Talvez te ajude a entender?

O problema todo é a notação usada de para ponteiros, não é intuitiva. Sua confusão é normal.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Obrigado @isrnick . E a todos ai.

 

Acho que entendi agora (um pouco).

No exemplo que enviei de troca de inteiros, usa o ' * '  para fazer com que as mudancas seja feitas diretamente no corpo principal tambem. Ai achei que deveria fazer o mesmo com o char, mas parece que funciona sem.

Normalmente quando mudamos algo na funcao, o corpo principal mantem ainda com os mesmo valores. 

 

Acho que to pegando a ideia.... 

adicionado 1 minuto depois

@Simon Viegas

54 minutos atrás, Simon Viegas disse:

Sobre:

Não entendi... se não é por referência, então como a mudança persistiu?

Pois é, para mim era por referencia tambem. (tava vendo um video no youtube, para aprender ahaha)

Compartilhar este post


Link para o post
Compartilhar em outros sites
18 minutos atrás, Josesousa disse:

Obrigado @isrnick . E a todos ai.

 

Acho que entendi agora (um pouco).

No exemplo que enviei de troca de inteiros, usa o ' * '  para fazer com que as mudancas seja feitas diretamente no corpo principal tambem. Ai achei que deveria fazer o mesmo com o char, mas parece que funciona sem.

Normalmente quando mudamos algo na funcao, o corpo principal mantem ainda com os mesmo valores. 

 

Acho que to pegando a ideia.... 

 

Não é por que é char, mas sim por que está passando um vetor (ao invés de uma variável).

Funcionaria igual, sem o asterisco *, se fosse um vetor de qualquer outro tipo (int, float, double, ...), se você conseguir entender porque já vai ter resolvido a maior parte do seu problema.

 

 

  • Curtir 1
  • Obrigado 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@isrnick É 1000 mais didático que eu.

 

 

Certo, o que é passagem por referencia e passagem por valor?

6 horas atrás, Simon Viegas disse:

Não entendi... se não é por referência, então como a mudança persistiu?

Na passagem por valor, uma cópia é feita do o argumento para  parâmetro. Exatamente o que acontece quando passamos um ponteiro, a variável no parâmetro faz uma copia da variável do argumento. Essa copia possui; local na memória e todas as funções de ponteiro. Porque é o que ele é, um ponteiro com valor de outro ponteiro. Já a passagem por referência é como apelidos da variável argumentada, compartilham tudo com ela inclusive o mesmo local na memória.

C tem referencias porém não em seus argumentos, mas sim espalhados por todo o programa por exemplo: Os identificadores de um vetor são todos referência (iguais a ponteiros e restringidos), constantes numéricas, strings literais e ...

 

Isso fica mais claro quando se aprofundar C++, pois é de lá que vem esse conceito. Em C tudo é por valor; Quando se copiar o local da memória entre ponteiros, existe aí então uma passagem de valor. .

  • Curtir 1
  • Amei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fiz outro exemplo, agora usando as notações de ponteiros e de vetores, demonstrando que ambas são válidas para todos os casos:

#include <stdio.h>

int main()
{
    /* Para variaveis: */
    
    int d = 10; //variavel
    printf("d = %d\n", d         ); //normal
    printf("d = %d\n", *(&d)     ); //notacao de ponteiros
    printf("d = %d\n", *(&d + 0) ); //notacao de aritmetica de ponteiros
    printf("d = %d\n", (&d)[0]   ); //notacao de vetores
    printf("\n");
    
    
    int *p; //ponteiro
    
    p = &d; //guarda uma copia da referencia de d no ponteiro p
    printf("*p = %d\n", *p       ); //notacao de ponteiros
    printf("*p = %d\n", *(p + 0) ); //notacao de aritmetica de ponteiros
    printf("*p = %d\n", p[0]     ); //notacao de vetores
    *p = 20; //atribuicao de valor
    printf("*p = %d --- d = %d\n", *p, d); //alterou o valor de d
    printf("\n");
    
    
    /* Para vetores: */
    
    int vet[2]; //vetor
    
    vet[0] = 5; //atribuicao com notacao de vetores
    *(vet + 1) = 7; //atribuicao com notacao de ponteiros
    printf("vet[0] = %d | vet[1] = %d\n", *vet       , *(vet + 1) ); //notacao de ponteiros
    printf("vet[0] = %d | vet[1] = %d\n", *(vet + 0) , *(vet + 1) ); //notacao de aritmetica de ponteiros
    printf("vet[0] = %d | vet[1] = %d\n", vet[0]     , vet[1]     ); //notacao de vetores
    printf("\n");
    
    
    int *pv; //ponteiro
    
    pv = vet; //guarda uma copia da referencia de vet no ponteiro pv
    printf("pv[0] = %d | pv[1] = %d\n", *pv       , *(pv + 1) ); //notacao de ponteiros
    printf("pv[0] = %d | pv[1] = %d\n", *(pv + 0) , *(pv + 1) ); //notacao de aritmetica de ponteiros
    printf("pv[0] = %d | pv[1] = %d\n", pv[0]     , pv[1]     ); //notacao de vetores
    pv[0] = 6; //atribuicao com notacao de vetores
    *(pv + 1) = 8; //atribuicao com notacao de ponteiros
    printf("pv[0] = %d | pv[1] = %d --- vet[0] = %d | vet[1] = %d\n",
                *pv, *(pv + 1), vet[0], vet[1]); //alterou  vet[0] e vet[1]
    printf("\n");
    
    
    return 0;
}

 

Execute o código aqui: https://onlinegdb.com/ry8NUZoMQ

 

Note que o código usa as diferentes notações para fazer as mesmas coisas várias vezes, de maneiras diferentes.

 

Claro, algumas dessas notações não são convenientes de usar, mas isso foi só pra fazer uma demonstração de que são válidas, e tentar passar a ideia de como são obtidas e passadas/copiadas as referências/endereços de memória de variáveis ou de vetores para ponteiros. Funciona do mesmo modo quando fazemos essa passagem para ponteiros nos parâmetros de funções.

  • Amei 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Interessante como voce alterou o valor de 'd'. ( 'p' aponta para 'd', ai mudando um, muda o outro)

Muito bom mesmo. 

Gradecido pela ajuda....

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
29 minutos atrás, isrnick disse:

pv = vet; //guarda uma copia da referencia de vet no ponteiro pv

Observem que, nesta caso não existe ampersand (&) e nem adianta colocar, se colocasse o resultado não seria outro.

 

Guardou-se então o valor de vet, e não sua referência pelo simples fato de ser todo nome de vetor uma referência.

Em 03/07/2018 às 14:20, AnsiC disse:

A parte interessante aqui é o nome-objeto, pois ele é um ponteiro, porém diferente dos ponteiros comuns esse ponteiro não pode ser modificado

 

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro 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 publicações 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

×