C - Alocação Dinâmica - Estrutura de Dados - Dúvidas

WickerSanD

Active Member
Registrado
Boa noite pessoal!!

Estou "overclockando" os meus neuronios, para fazer dois exercícios para a facul. Um deles parece ser simples, segue o enunciado:

"(1.5) Escreva uma função de protótipo:
void strinv (char s[]);
que inverta os caracteres de uma string. Por exemplo: se a string for “ABCDEF”, deve ser
convertida para “FEDCBA”."

Comentários do professor:

A idéia aqui é implementar a função "strinv". Note que o parâmetro deve ser "char s[]" (vc não deve dimensionar o tamanho de s).

Essa função deve fazer o seguinte:
1. Como a função não tem como saber o tamanho do vetor passado em s, ela deve percorrer esse vetor até encontrar '\0' (fim de string). Assim, calculamos o tamanho da string.
2. Alocar dinamicamente um novo vetor "auxVet" com o tamanho apropriado para a string.
3. Usamos "auxVet" para inverter a string de s (percorremos s de trás para frente e armazenamos os caracteres em auxVet)
4. Depois percorremos auxVet e sobrescrevemos o vetor s, com a sequencia invertida (note que a operação precisa ser feita em s, pois a função strinv não retorna valores.
5. Depois de copiar a string invertida para s, devemos liberar a memória de auxVet.

OBSERVACAO: é possível realizar a inversao da string "sem alocar outro vetor". Bastaria percorrer s com dois indices: um partido de 0 e outro partindo de n - 1 (n é o tamanho da string). Bastaria ir trocando os caracteres. Mas o meu interesse aqui, é que usemos as funções de alocação dinâmica.
Já pesquisei bastante, mas muitas pessoas fazem utilizando dois vetores e talz, fiz um aqui mas não consigo entender como fazer. Na verdade estou com dúvidas de como usar a lógica e os comando corre


C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define size 256

void strinv(char s[size]) {
      int i; 
      char auxVet[size];
                 
      for(i= 0; s[size] != '\0'; i++)
      {
         
      }
           
}     
    
int main(int argc, char *argv[])
{
    int i=0;
    char palavra[256];
  
    printf("Digite uma palavra:\n");
    scanf("%s", palavra);
    printf("O texto informado eh: %s\n", palavra);
    
    
    
    strinv(palavra);
    printf("O texto invertido eh: %s\n", palavra);
  
    system("PAUSE");    
    return 0;
}

Alguém poderia me ajudar, explicar o que eu posso fazer, utilizando alocação dinâmica???

Obrigado pela ajuda pessoal!
 
É bem fácil
Vamos por partes

Algumas correções na sua função atual

C:
void strinv(char s[])
{
    int size;
    int i;
}

Vamos começar assim

Aí você deve declarar o ponteiro do vetor que será alocado dinâmicamente

C:
char *auxVet;

Você pode usar um laço for pra calcular o tamanho do vetor

C:
for(size = 0; s[size] != '\0'; size++)
Só isso mesmo... O valor de size será o tamanho do vetor

Agora alocar dinamicamente é assim, você deve usar a funcão malloc

C:
auxVet = (char*) malloc(size * sizeof(char));

O ponteiro auxVet irá receber o endereço inicial de um array (posição [0]),
(char *) é o casting que você deve fazer para converter para um array de char

malloc(size * sizeof(char)) estamos chamando malloc e pedindo pra ele alocar um vetor do tamanho SIZE (tamanho do vetor) multiplicado pelo tamanho de um CHAR (1 byte) essa multiplicação é desnecessária aqui, mas se fosse um vetor de inteiros você iria precisar, então para fins educativos...

Agora você precisa inverter,

só fazer o inicio de um vetor receber o final do outro e assim vai
Eu tenho a solução aqui, fiz rapidinho
Não vou passar pra você pq vc temq pensar, mas se você não tiver conseguindo mesmo eu posso passar e explicar o que eu fiz
boa sorte

Edit: ah sim, esqueci de mencionar, você precisa liberar a memória no final... quando termianr de passar o auxString pra s
apenas de um

C:
free(auxString);
 
Última edição:
Olá Luxw!!
Muito obrigado por explicar. Mas ainda tenho dúvidas de como pegar o vetor, inverter e colocar no outro. Estou tentando mas nada até agora.
Estou com muitas dificuldades nesta máteria (Estrutura de Dados).

Olá o que eu fiz até o momento, após a sua explicação:
C:
void strinv(char s[]) 
{
      int i;
      int size; 
      char *auxVet;
      auxVet = (char*) malloc(size * sizeof(char));
                 
      for(size = 0; s[size] != '\0'; size++)
      {
          for(size = i-1; size <= 0; --size)
          {
               if(auxVet[size] == s return size;
               return -1;
          }    
      }
           
}

Obrigado pela ajuda!
A parte de alocação dinamica me ajudou bastante!!!!
 
C:
void strinv(char s[]) 
{
      int i;
      int size; 
      //Aqui você está declarando o ponteiro pro vetor
      char *auxVet;
               
      //Esse laço for serve apenas para calcular a variável o tamanho do vetor e gravar na variável size, não vai nada dentro dele
      for(size = 0; s[size] != '\0'; size++){}

      //Aqui você está alocando dinâmicamente o vetor, a partir desse ponto usar o vetor dinâmico é idêntico a usar um vetor estático 
      auxVet = (char*) malloc(size * sizeof(char));

      //Agora você irá fazer um laço for que irá de percorrer o vetor gravando invertido, dica
      for(i = 0; i < size; i++)
      {
           auxVetor[i] = _________ ; //Complete aqui
      }

     //Agora outro laço for que irá jogar a string de auxVetor devolta em s
     for(i = 0; i < size; i++)
     {
        _____________________ ; //Complete aqui
     }

     //Desaloca memória
     free(auxVetor);

     //Lembre-se que a função é tem o tipo de retorno void, ou seja, ela não retorna nenhum valor 
  
           
}

Siga esse caminho, que você irá conseguir
 
Última edição:
Código:
void strinv(char s[]) 
{
      int i;
      int size; 
      //Aqui você está declarando o ponteiro pro vetor
      char *auxVet;
               
      //Esse laço for serve apenas para calcular a variável o tamanho do vetor e gravar na variável size, não vai nada dentro dele
      for(size = 0; s[size] != '\0'; size++){}

      //Aqui você está alocando dinâmicamente o vetor, a partir desse ponto usar o vetor dinâmico é idêntico a usar um vetor estático 
      auxVet = (char*) malloc(size * sizeof(char));

      //Agora você irá fazer um laço for que irá de percorrer o vetor gravando invertido, dica
      for(i = 0; i < size; i++)
      {
           auxVetor[i] = _________ ; //Complete aqui
      }

     //Agora outro laço for que irá jogar a string de auxVetor devolta em s
     for(i = 0; i < size; i++)
     {
        _____________________ ; //Complete aqui
     }

     //Desaloca memória
     free(auxVetor);

     //Lembre-se que a função é tem o tipo de retorno void, ou seja, ela não retorna nenhum valor 
  
           
}

Siga esse caminho, que você irá conseguir

Luxw, na parte que faz a inversão que estou com dúvidas de como fazer. Agora pouco na Facul, perguntei para o professor, e disse que há outras maneiras e talz, mas ele falou que não pode usar strlen e outras formas de fazer.
Enfim,
Não estou sabendo como lidar com os vetores, e como fazer correr o vetor de traz para frente e adicionar em outro.
Estou até com vergonha de perguntar e talz, mas estou me esforçando o máximo para ententer.

Além do mais agradeço pela sua ajuda, que realmente está melhor que a do próprio professor!

Obrigado novamente.

Abraços!
 
Ok, vou completar o código e explicar pra você

C:
void strinv(char s[]) 
{
      int i;
      int size; 
      //Aqui você está declarando o ponteiro pro vetor
      char *auxVet;
               
      //Esse laço for serve apenas para calcular a variável o tamanho do vetor e gravar na variável size, não vai nada dentro dele
      for(size = 0; s[size] != '\0'; size++);

      //Aqui você está alocando dinâmicamente o vetor, a partir desse ponto usar o vetor dinâmico é idêntico a usar um vetor estático 
      auxVet = (char*) malloc(size * sizeof(char));

      //Agora você irá fazer um laço for que irá de percorrer o vetor gravando invertido, dica
      for(i = 0; i < size; i++)
      {
           /* Você mesmo disse: "Bastaria percorrer s com dois indices: um partido de 0 e outro partindo de n - 1" - é basicamente o que eu estou fazendo, veja bem
           se você pensar eu estou colocando o índice 4 do s no índice 0 do auxVetor, 3 do s no 1 do auxVetor e assim vai
           Um deles parte de 0, que é o auxVetor, o outro está partindo de n - 1, porém eu quero diminuir o índice dele, então eu faço n - 1 - i
           Dessa forma, eu copio cada caractere de s em auxVetor, porém na ordem invertida */

           auxVetor[i] =  s[size - i - 1]; 
      }

     //Agora outro laço for que irá jogar a string de auxVetor devolta em s 
     for(i = 0; i < size; i++)
     {
        s[i] = auxVetor[i] ; //Aqui é simples, 0 pra 0, 1 pra 1, 2 pra 2... só estou copiando os valores
     }

     //Desaloca memória
     free(auxVetor);

     //Lembre-se que a função é tem o tipo de retorno void, ou seja, ela não retorna nenhum valor 
           
}

Veja, pra calcular o tamanho do vetor eu não estou usando strlen(), apenas uso aquele primeiro laço for
Ele não faz nada além de modificar a variável size, cada iteração do laço size é incrementado de 1, no final do laço size terá o valor do tamanho do vetor ;)

Esse é o código pronto da função, pode compilar e testar que vai funcionar

Não hesite em perguntar caso você não esteja entendendo algo, eu posso tentar explicar
 
Última edição:
Luxw,
Obrigado pelas dicas!

Vou repassar abaixo como eu entendi as suas explicações:

--> Usando alocação dinânima, é necessário declarar uma variável ponteiro:
Código:
char *auxVet;

--> Para ler o conteúdo do vetor alocado na memória devemos declarar uma variável do vetor e ler o conteúdo até achar '\0':
Código:
int size;
for(size = 0; s[size] != '\0'; size++){};


--> Para alocar dinâmicamente usar a função "malloc" (conhecida como função malloqueira), setando uma variável auxiliar "auxVet", apontando para char*, setando a variável declarada dentro de malloc:
Código:
auxVet = (char*) malloc(size * sizeof(char));

--> Após alocar o vetor auxiliar na memória, usar o 'FOR' para correr o vetor [size] de 0 à 4 e adicionar o conteúdo em "auxVet", por exemplo. Para inverter devemos pegar o conteúdo de "auxVet" e adicionar em "s", mas correndo de trás para frente, 4 à 0.
Código:
for(i = 0; i < size; i++)
      {
          auxVet[i] =  s[size - i - 1];
      }

--> Para adicionar a String invertida no vetor principal "s[size]":
Código:
s[i] = auxVet[i] ;


--> Caso a função "malloqueira" trabalhar certinho, você libera era setando o vetor auxiliar:
Código:
free(auxVet);


Segue o novo código funcional:
Código:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void strinv(char s[]) 
{
      int i;
      int size; 
      char *auxVet;
               
      for(size = 0; s[size] != '\0'; size++){};
      auxVet = (char*) malloc(size * sizeof(char));

      for(i = 0; i < size; i++)
      {
          auxVet[i] =  s[size - i - 1]; 
      }                                     

      for(i = 0; i < size; i++)
      {
        s[i] = auxVet[i] ;
      }

      free(auxVet);

}
    

int main(int argc, char *argv[])
{
    char palavra[256];
  
    printf("Digite uma String:\n");
    scanf("%s", palavra);
    printf("String digitado: -> %s\n", palavra);
    strinv(palavra);
    printf("String invertida: -> %s\n", palavra);
    system("PAUSE>NULL");	
    return 0;
}

Obrigado pela ajuda Tuxw, se quiser, por favor, adicione no msn wickerbad@hotmail.com.

Pelo jeito irei precisar de suas dicas durante a minha formação!!!!

Abraços!
 
Última edição:
Luxw,
Obrigado pelas dicas!

Vou repassar abaixo como eu entendi as suas explicações:

--> Usando alocação dinânima, é necessário declarar uma variável ponteiro:
C:
char *auxVet;

--> Para ler o conteúdo do vetor alocado na memória devemos declarar uma variável do vetor e ler o conteúdo até achar '\0':
C:
int size;
for(size = 0; s[size] != '\0'; size++){};


--> Para alocar dinâmicamente usar a função "malloc" (conhecida como função malloqueira), setando uma variável auxiliar "auxVet", apontando para char*, setando a variável declarada dentro de malloc:
Código:
auxVet = (char*) malloc(size * sizeof(char));

Vou repassar algumas explicações

Um ponteiro

C:
int *pInt;
char *pChar;
float *pFloat;
...

Independente do tipo atribuído, um ponteiro nada mais é que um inteiro de 32bits, que contém um endereço de memória
Esse endereço de memória aponta para uma variável do tipo específicado.

vamos supor o seguinte programa

C:
int main()
{
    int *pInt;
    int n = 100;

    pInt = &n; //Aqui você está fazendo pInt receber o endereço de n, dessa forma pInt irá apontar para n

    printf(Endereco: 0x%x  Valor: %d  \n", pInt, *pInt);

    return 0;
}

A saída do programa será o endereço da variável n e o valor dela.
Dessa forma você pode acessar a variável n sem precisar necessáriamente chamar n
É útil pois você pode fazer um ponteiro para uma estrutura de dado inteira, sem precisar TODA a estrutura de dado para uma função por exemplo

No caso você está criando uma variável ponteiro que irá apontar para o endereço do primeiro elemento de um vetor ;)

--> Para ler o conteúdo do vetor alocado na memória devemos declarar uma variável do vetor e ler o conteúdo até achar '\0':
C:
int size;
for(size = 0; s[size] != '\0'; size++);

Aqui é assim, a gente declarou uma variável size e fizemos um laço for que incrementa size até achar um \0 no vetor, o que indica o final desse vetor de char.
No final size terá o tamanho da string ;)


Sobre o malloc, num é que ela aponta para um (char*), mas é estamos convertendo o resultado da função malloc para um char*

Quando se coloca (int), (float), (char) antes de uma expressão, estamos convertendo o resultado dela para o tipo específicado, chamamos isso de Type Casting

Por exemplo

C:
float a = 100.99;
int b;

b = (int) a;

b estará com o valor 100 ;)

usamos a variável size para fazer o vetor allocado ter o tamanho certinho que queremos

malloc(size * sizeof(char));

Se eu colocar tipo malloc(100 * sizeof(int)); será um vetor de 100 ints

E por aí vai


Espero que tenha ficado tudo claro ;)
Qualquer dúvida não hesite em perguntar
 
Última edição:
Tuwx, muito obrigado!
Aquela nuvem negra já passou, ficou mais simples com as suas explicações!

Pode deixar, vou pergutar sim.... tenho mais uma lista de exercicios (prova mensal prática), que está tensa!!!!
Tenho que usar TAD, para cadastrar, consultar, remover e inserir um novo aluno com nome, RA e idade.
Vou fazer ele ai.. e posto em outro tópico para facilitar a consulta!

Tks!
 

Users who are viewing this thread

Voltar
Topo