Eliminar elemento en un vector con C

Si eres principiante y tienes alguna consulta entra en este foro.
Responder
Mensaje
Autor
Zhyur
Mensajes: 2
Registrado: 03/12/2019 10:25 am

Eliminar elemento en un vector con C

#1 Mensaje por Zhyur » 03/12/2019 10:29 am

Buenas tardes,

necesito crear una función donde, dado un vector de, por ejemplo, 10 valores, elimine el valor que está en una posición que yo indique, y luego mueva hacia la izquierda los elementos situados después del valor eliminado (para cubrir el "hueco" dejado por el valor eliminado).

¿Cómo podría ser esta función? Lo que tengo creado ahora es lo siguiente, pero no funciona:

Código: Seleccionar todo

void elim_elem(int num[], int pos, int *num_elem)
{
   int i;

   for(i = pos; i < *num_elem - 1; i++)
      num[i] = num[i + 1];
   --*num_elem;

}
Un saludo y gracias por adelantado.

mollok
Mensajes: 519
Registrado: 30/01/2018 9:47 am
Ubicación: Mallorca, España

Re: Eliminar elemento en un vector con C

#2 Mensaje por mollok » 03/12/2019 1:29 pm

Pon también un ejemplo de uso.
while(is_alive(yourself)) {
    make_true(yourself, yourdreams);
}

el pare
Mensajes: 6
Registrado: 04/12/2019 5:40 am

Re: Eliminar elemento en un vector con C

#3 Mensaje por el pare » 04/12/2019 5:56 am

Hola Zhyur:
Mirate este código. Creo que te quedará resuelto. Salu2

Código: Seleccionar todo

#include<stdio.h>

int main(){

// Declaracion de variables

  int pos = 0 , *num_elem, numero,  int i;

  printf("Introducir el numero de elementos ");
  scanf("%i",&*num_elem);

  int num[*num_elem];                                             // Fin declaracion de variables

// Llenar el arreglo

  while(pos <= *num_elem - 1)
  {

    printf("entre el elemento %i ",pos+1);
    scanf("%i",&numero);

    num[pos] = numero;

    pos++;

  }                                                                           // fin llenar arreglo

// Eliminar el contenido de la posición y correr las posiciones que quedan

  printf("Entrar la posicion a eliminar ");
  scanf("%i",&pos);

  for(i = pos - 1; i <= *num_elem; i++)
  {

    num[i] = num[i + 1];

  }                                                                            // Fin eliminar el contenido de la posición y correr las posiciones que quedan

  num[*num_elem - 1] = '\0';                                      // Eliminacion del ultimo elemento

// Mostrar el arreglo como queda

  for(i = 0; i <= *num_elem - 1; i++)
  {

    printf("\n%i", num[i]);

  }
 
  return 0;

}
Última edición por mollok el 04/12/2019 1:30 pm, editado 1 vez en total.
Razón: Los códigos deben ir entre etiquetas 'code', botón </>

Zhyur
Mensajes: 2
Registrado: 03/12/2019 10:25 am

Re: Eliminar elemento en un vector con C

#4 Mensaje por Zhyur » 05/12/2019 3:54 am

Muchísimas gracias por tu ayuda.

Un saludo.

Avatar de Usuario
kiko66
Mensajes: 37
Registrado: 11/10/2019 10:51 am

Re: Eliminar elemento en un vector con C

#5 Mensaje por kiko66 » 05/12/2019 2:23 pm

hola zhyur veo que lo has conseguido, esa funcion que tienes es correcta,

• num[] es el vector a reducir
• pos el la posicion a eliminar
• y num_elem es el tamaño del vector

veo que al final decrementas el tamaño del array dejandolo listo para usarse con su nuevo tamaño

quizas no has utilizado correctamente la funcion, abajo te dejo un posible uso de esa funcion (o parecida) ;-)

//------------------------------------------------------------------------------------------------------

hola pare, veo no has compilado el programa, la idea en general es correcta, solo que no creas "la funcion" y
a mi entender yo cambiaria algunas cosas para que pueda funcionar el programa

te comento lo que no acabo de entender:
• porque num_elem lo creas como puntero y no como un int normal ??
• en el scanf siguiente

Código: Seleccionar todo

scanf("%i",&*num_elem);
no funcionara ya que un int* guarda un puntero a un int quizas algo como

Código: Seleccionar todo

 int* num_elem=&i;
si seria valido pero tu no lo inicializas y no tiene sentido crear num_elem como puntero,
asi que cuento que num_elem es un int normal para no liar mas
• en el

Código: Seleccionar todo

 while(pos <= num_elem - 1)
no seria mas sencillo

Código: Seleccionar todo

while(pos < num_elem)
• creas numero solo para esto

Código: Seleccionar todo

scanf("%i",&numero); num[pos] = numero;
cuando

Código: Seleccionar todo

scanf("%d", &num[pos]);
va mas claro y menos redundante
• en el bucle

Código: Seleccionar todo

for(i = pos - 1; i <= num_elem; i++)
cuando i es igual a num_elem se ejecuta

Código: Seleccionar todo

num[i] = num[i + 1];
con lo que "num[ i ]" y "num[i + 1];" estan fuera del array,
en el ciclo anterior a ese, solo "num[i+1]" esta fuera del array. si el for fuese...

Código: Seleccionar todo

for(i = pos - 1, num_elem--; i < num_elem ;i++)
al ejecutar el bucle se copiaria todo correctamente
• desde mi punto de vista

Código: Seleccionar todo

num[num_elem - 1] = '\0';
no hace falta ya que num no es una cadena si no un array y el contenido del ultimo elemento
es indiferente, no deberia visulalizarse y "\0" no elimina nada
• en el for que muestra el array vuelves a colocar <= en vez de < con lo que ves un elemento mas de los que quieres
si en el for anterior fuese

Código: Seleccionar todo

for(i = pos - 1, num_elem--; i < num_elem ;i++)
en el for de muestra array, te quedaria bien algo como

Código: Seleccionar todo

for(i = 0; i < num_elem ; i++)
ya que num_elem ya estaria decrementado con el nuevo tamaño del array

espero te sirva para proximos programas
suerte pare
// --------------------------------------------------------------------------------------------

bueno zhyur, lo prometido es deuda asi que te dejo un programa que usa la funcion que has creado

Código: Seleccionar todo

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

#define RMAX 100 // orquilla de valores a rellenar aleatoriamente

// -----------------------------------------------------------------------------elimina_casilla
void elimina_casilla(int vec[], int pos, int* tamanyo){
               // si tamamyo es por ej 10, ira del 0 al 9
               // el nuevo tamaño es uno menos que el actual y compensa el ++pos
   --*tamanyo;
   while(pos<*tamanyo) vec[pos]=vec[++pos];  
}
// -----------------------------------------------------------------------------muestra_vec
void muestra_vec(const int vec[], int tamanyo){

   for(int i=0; i<tamanyo ;i++){
      if(!(i%10)) puts("");
      printf("%2d-%2d\t",i, vec[i]);
   }
}
// -----------------------------------------------------------------------------rellena_vec
void rellena_vec(int vec[], int tamanyo){ 

   srand(time(NULL));
   for (int i = 0; i < tamanyo; ++i)
      vec[i] = rand() % RMAX;	
}
// -----------------------------------------------------------------------------dame_tam
int dame_tam(void){

   int tamanyo;

   do{
      printf("\nintroduce el numero de casillas del array: ");
      scanf("%d", &tamanyo);
   }while(tamanyo<=0);   

   return tamanyo;
}
// -----------------------------------------------------------------------------dame_pos
int dame_pos(int tamanyo){
   int posicion;

   do{
      printf("\n\nque casilla quieres eliminar(entre 0 y %d): ", tamanyo-1);
      scanf("%d", &posicion);
   }while(posicion<0 || posicion>=tamanyo);

   return posicion;
}
// -----------------------------------------------------------------------------repetir
int repetir(int tamanyo){
   
   int continuar=0;

   if(tamanyo){
      printf("\n\n¿quieres continuar eliminando casillas?"
               "\ncero para salir, otro numero para continuar: ");
      scanf("%d", &continuar);
   }

   return continuar;  
}
// *****************************************************************************main
int main(void){

   int tamanyo=dame_tam();
   int vector[tamanyo]; 

   rellena_vec(vector, tamanyo);

   do{
      muestra_vec(vector, tamanyo); // muestro el vector completo   
      elimina_casilla(vector, dame_pos(tamanyo), &tamanyo);
      muestra_vec(vector, tamanyo); // muestro el vector reducido
   }while(repetir(tamanyo));

   return 0;
}

el pare
Mensajes: 6
Registrado: 04/12/2019 5:40 am

Re: Eliminar elemento en un vector con C

#6 Mensaje por el pare » 06/12/2019 3:20 am

Hola Kiko:

1.- Muchas gracias por la crítica. Me ha sido muy enriquecedora. Espero con impaciencia las próximas. Muchas gracias.

2.- Soy autodidacta y muy novato (2 meses) en este fascinante mundo de la programación, tanto que hasta ahora
solo he llegado a ver las iteracciones, es decir, los bucles y los condicionales, por lo que no tenía ni idea de estar
creando un puntero en vez de una variable entera. Lo hice únicamente para que los nombres coincidieran
con los que Zhyur trabajaba. Sorry. Seguiré aprendiendo.

3.- Comentarios:

Código: Seleccionar todo

    while(pos <= num_elem - 1)                                                  // Totalmente de acuerdo.

    scanf("%d", &num[pos]);                                                       // No sabía que se podía hacer. Lo tendré en cuenta

    for(i = pos - 1, num_elem--; i < num_elem ;i++)                     // ¿Porqué decrementas num_elem?

    num[num_elem - 1] = '\0';                                                     /*  Esta instrucción por lo que veo lo que hace
                                                          			                    es asignar el valor 0 a la última posición. No la borra.
                                                                                                    pero si no la hago me sale un valor inadmisible.
                                                                                                    Trabajo con gcc para Windows y bloc de notas.
			                                                                            Estoy empezando a adentrarme en Vim.
			                                                                            Te mando una fotos con la instrucción y sin ella.
				                                                                    ¿Conoces alguna fórmula para pasar el valor NULL?
                                                                                               */
                                                                                               
Me ha quedado así:

Código: Seleccionar todo

#include<stdio.h>

int main(){

  int pos = 0 , num_elem;

  printf("Introducir el numero de elementos ");
  scanf("%i",&num_elem);

  int num[num_elem];

  while(pos < num_elem)
  {

    printf("entre el elemento %i ",pos+1);
    scanf("%i",&num[pos]);

    pos++;

  }

  printf("Entrar la posicion a eliminar ");
  scanf("%i",&pos);

  int i;

  for(i = pos - 1; i < num_elem; i++)
  {

    num[i] = num[i + 1];

  }

  num[num_elem - 1] = '\x00';

  for(i = 0; i < num_elem; i++)
  {

    printf("\n%i", num[i]);

  }

  return 0;

}
Lo dicho Kiko muchas gracias y hasta la próxima. :D :D :D

P.D. No se como adjuntar una foto. ¿Me puedes ayudar?

[img]C:\Users\W7i5\Documents\NULL[/img]
Última edición por mollok el 06/12/2019 6:11 am, editado 1 vez en total.
Razón: Los códigos deben ir entre etiquetas 'code', botón </>

Avatar de Usuario
kiko66
Mensajes: 37
Registrado: 11/10/2019 10:51 am

Re: Eliminar elemento en un vector con C

#7 Mensaje por kiko66 » 07/12/2019 9:41 am

hola pare, para llevar dos meses vas como un cohete y te veo con muchas ganas

el dicremento de num_elem en

Código: Seleccionar todo

for(i = pos - 1, num_elem--; i < num_elem ;i++) 
tiene dos motivos:

1- num_elem lleva la cuenta de los elementos que contiene el array, por lo que si eliminamos
un elemento y llevamos el hueco al final, al visualizamos el array, ¿que veremos en ese "hueco"?,
lo logico a mi parecer es que si quitamos un elemento del array decrementemos num_elem y asi al
visualizar o operar con los elementos validos y no con la "basura" que haya quedado en el "hueco"
si quieres saber la longitud real puedes guardarla en una variable

2- el punto 1 es el porque decrementar num_elem para poder usar el array una vez eliminado el
elemento, pero poque decrementarlo antes de eliminarlo, bueno pare, puedes ver que en el bucle
se va una posicion mas alla de la posicion de "i" con "num[i + 1]" es decir si llegas al final
del bucle i estara en la ultima posicion y con el i+1 iras mas alla de los limites de array,
al decrementar num_elem hago que la ultima posicion de i sea la penultima del array y el contenido de i+1
(la ultima) se copie en la penultima y es bucle concluye. la ultima posicion tiene "basura" y de ahi lo del punto 1

- por lo que dices de que utilizaste num_elem como puntero y esta mal, cuando zhyur lo hace y esta bien
es por la manera de utilizarlo, el hace una funcion a la que le pasa un puntero al contenido de la
variable num_elem para asi decrementarlo desde la funcion y que num_elem lleve la cuenta de las posiciones
con contenido usable, digamos sin "basura", tu usas el puntero sin inicializar es decir que no se sabe donde
apunta para guardar ahi, en la posicion "basura" el numero de elementos que pides con scanf, zhyur ya tiene
ese dato antes de llamar a la funcion, lo pasa a la funcion para que lo utilice y lo decremente al eliminar el elemento
y lo hace con un puntero para que la funcion decremente la variable de main no solo en la funcion

- si quieres programar es importante aprender git, claro eso quizas un poco mas adelante, pero con git,
(github, gitlab y otros) tienes acceso a mucho codigo como el de tantos programas libres y de codigo abierto
supongo que sabes que las distros de linux usan principalmente software libre ;-)

- NULL es una constante que puedes pasarla siempre que quieras pero, creo que lo que realmente quieres
es anular la casilla del array y eso no se hace con NULL, con que no utilices la ultima casilla es suficiente,
tambien podrias usar memoria dinamica para el array, ahi si puedes eliminar casillas realmente, en c++ la
plantilla vector si te permite ampliar o reducir el tamaño, pero eso ya es otra historia

- para enviar una imagen yo uso el flameshot que te permite entre otras muchas cosas pasar imagenes atraves de
imgur que es como un pastebin de imagenes -- http://i.imgur.com/pQCEfWJ.png --, en esta url hay una imagen ;-)


** respecto al programa que has hecho:
- si esta bien, este si compila ;-)
- lo dificil ya lo has hecho, ahora para que sea lo que piden tienes que crear una funcion que
elimine una casilla del vector es decir que le pases el vector y te lo devuelva con uno menos tal
como dice el enunciado. desde main llama a la funcion y esta te quita el elemento
- como ves poner un cero al final no ayuda a visualizar el array con un elemento menos, hay que hacer que
el ultimo no este disponible, ya sabes decrementar el numero de elementos del vector, asi no se vera el 0
- una idea para que no tengas que usar punteros, es que la funcion te devuelva el nuevo numero de elementos,
algo como...

Código: Seleccionar todo

int elimina_casilla(int nombre_vector[ ], int posicion_a_borrar, int tamanyo_del_vector){
...
tamanyo_del_vector--;
...
return tamanyo_del_vector;
}

y asi llamarla con ...

Código: Seleccionar todo

tamanyo_vec = elimina_casilla(vector, posicion_a_eliminar, tamanyo_vec);
asi tamanyo_vec recoge el nuevo tamaño y puedes visualizar el vector reducido tomando
tamanyo_vec como tamaño del vector

mucha suerte con el programa, ya me diras como te queda
saludos

el pare
Mensajes: 6
Registrado: 04/12/2019 5:40 am

Re: Eliminar elemento en un vector con C

#8 Mensaje por el pare » 09/12/2019 1:01 pm

Hola Kiko:

Como te dije soy muy novato. Eso si me gusta jugar a esto y tengo muchas ganas de aprender.
Teniendo comentarios como los tuyos me hace avanzar más y más rápido, por lo que te estoy muy agradecido.
Para codificar lo que me pedías tuve que estudiar lo relativo a funciones, así que me puse a ello y este es el resultado.

#include<stdio.h>

int Eliminar_Posicion_A_Elegir (int num[] , int num_elem)
{
int pos = 0;

printf("Entrar la posicion a eliminar ");
scanf("%i",&pos);

for(int i = pos - 1; i < num_elem; i++)
{
num = num[i + 1];
}

--num_elem;

return num_elem;
}


int main()
{

int pos = 0 , num_elem;

printf("Introducir el numero de elementos ");
scanf("%i",&num_elem);

int num[num_elem];

while(pos < num_elem)
{
printf("entre el elemento %i ",pos+1);
scanf("%i",&num[pos]);

pos++;
}

num_elem = Eliminar_Posicion_A_Elegir(num, num_elem);

for(int i = 0; i < num_elem; i++)
{
printf("\n%i", num);
}

return 0;
}

Muchas gracias por tu ayuda.

Por cierto, ¿ que te parecería que te añadiera como amigo?

salu2

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: Bing [Bot], Majestic-12 [Bot] y 5 invitados