funciones en C ejercicios resueltos chuletario paso referencia

Funciones en C — ejercicios para dominar el paso por referencia

Las funciones en C ejercicios con solución cierran este bloque. Ya viste la teoría y practicaste con programas reales. Ahora toca resolver por tu cuenta en gedit y compilar con gcc en Fedora. Tres ejercicios en tres niveles con especial atención a los dos errores que más destrozan una implementación de funciones en C: olvidar & al pasar una variable que se va a modificar, y olvidar pasar el tamaño n junto con el array.

Como siempre: intenta resolverlo, usa la pista si llevas más de 10 minutos atascado, compara con la solución comentada al final y copia el código en pythontutor.com para la ver la ejecución de manera más detallada.


Funciones en C ejercicios — Nivel Básico

Ejercicio 1 — Función que busca el segundo máximo

Escribe un programa con estas tres funciones:

  • int maximo(int vec[], int n) — devuelve el valor máximo del array
  • int segundo_maximo(int vec[], int n) — devuelve el segundo valor más grande (distinto del máximo)
  • void mostrar_array(int vec[], int n) — muestra el array en pantalla

La salida debe ser:

Array: 42 7 19 85 26 85 54 13

Máximo:         85
Segundo máximo: 54

Array: 10 10 10 10
Máximo:         10
Segundo máximo: no existe (todos los elementos son iguales)

Array: 5 3
Máximo:         5
Segundo máximo: 3

Requisitos importantes:

  • Si todos los elementos son iguales no hay segundo máximo — muestra el mensaje correspondiente
  • El segundo máximo debe ser un valor distinto del máximo — si el máximo aparece varias veces no cuenta como segundo máximo
  • El array puede tener elementos repetidos

💡 Pista — el error de olvidar &:

/* MAL — intentar devolver el segundo máximo por referencia sin & */
int segundo;
buscar_segundo_maximo(vec, n, segundo);   /* segundo no cambia */

/* BIEN — si usas puntero, pasa la dirección */
int segundo;
buscar_segundo_maximo(vec, n, &segundo);  /* segundo sí cambia */

En este ejercicio no necesitas paso por referencia para el segundo máximo — puedes devolver -1 como señal de «no existe» y usar return. Pero si quisieras devolver también la posición del segundo máximo, necesitarías int *posicion y &posicion al llamar.

Para encontrar el segundo máximo sin ordenar el array: recorre una vez para encontrar el máximo, luego recorre otra vez buscando el mayor valor que sea estrictamente menor que el máximo.


Funciones en C ejercicios — Nivel Intermedio

Ejercicio 2 — Función que elimina un elemento en una posición dada

Escribe un programa con estas funciones:

  • int eliminar_posicion(int vec[], int *n, int posicion) — elimina el elemento en posicion, desplaza el resto hacia la izquierda y actualiza *n. Devuelve el valor eliminado. Si la posición no es válida devuelve -1 y no modifica nada.
  • void insertar_posicion(int vec[], int *n, int posicion, int valor) — inserta valor en posicion, desplaza el resto hacia la derecha y actualiza *n. Si la posición no es válida no hace nada.
  • void mostrar_array(int vec[], int n) — muestra el array

La salida debe ser:

Array inicial: 10 20 30 40 50
Longitud: 5

Eliminando posición 2 (valor 30):
Array: 10 20 40 50
Longitud: 4

Eliminando posición 0 (valor 10):
Array: 20 40 50
Longitud: 3

Insertando 99 en posición 1:
Array: 20 99 40 50
Longitud: 4

Eliminando posición inválida (5):
Posición 5 fuera de rango — array no modificado
Array: 20 99 40 50
Longitud: 4

💡 Pistas — los dos errores:

/* ERROR 1 — olvidar & al pasar n para que la función lo modifique */
int n = 5;
eliminar_posicion(vec, n, 2);    /* MAL — n no cambia fuera */
eliminar_posicion(vec, &n, 2);   /* BIEN — n se actualiza */

/* ERROR 2 — olvidar validar la posición antes de acceder */
/* Si posicion >= *n o posicion < 0 → acceso fuera del array */
if (posicion < 0 || posicion >= *n) {
    printf("Posición %d fuera de rango\n", posicion);
    return -1;    /* salir sin modificar nada */
}

Para eliminar un elemento en la posición p: desplaza todos los elementos desde p+1 hasta n-1 una posición hacia la izquierda, luego decrementa *n. Para insertar: desplaza todos los elementos desde n-1 hasta p una posición hacia la derecha, luego coloca el valor en p e incrementa *n. El orden del desplazamiento importa — si empiezas por el lado equivocado sobrescribes datos.


Funciones en C ejercicios — Desafío Final

Ejercicio 3 — Fusionar dos arrays ordenados en uno ordenado

Escribe un programa con estas funciones:

  • void fusionar(int a[], int na, int b[], int nb, int resultado[], int *nr) — fusiona los arrays a y b (ambos ya ordenados ascendentemente) en resultado[], que también queda ordenado. Guarda el tamaño del resultado en *nr.
  • void ordenar(int vec[], int n) — ordena un array ascendentemente (puedes usar burbuja)
  • void mostrar_array(int vec[], int n) — muestra el array

La salida debe ser:

Array A (ordenado): 3 7 11 15 22
Array B (ordenado): 1 5 9 12 18 25 30

Fusionados: 1 3 5 7 9 11 12 15 18 22 25 30
Longitud resultado: 12

Caso con repetidos:
Array A: 2 4 6 8
Array B: 3 4 7 8 9

Fusionados: 2 3 4 4 6 7 8 8 9
Longitud resultado: 9

Caso vacío:
Array A: 1 3 5
Array B: (vacío)

Fusionados: 1 3 5
Longitud resultado: 3

💡 Pistas:

La fusión eficiente de dos arrays ordenados no necesita ordenar el resultado al final — puedes construirlo ordenado directamente usando dos índices:

/* Idea del algoritmo */
int i = 0, j = 0, k = 0;
while (i < na && j < nb) {
    if (a[i] <= b[j]) {
        resultado[k++] = a[i++];    /* toma de A */
    } else {
        resultado[k++] = b[j++];    /* toma de B */
    }
}
/* cuando uno se agota, copia el resto del otro */

El error de olvidar & aparece con *nr, si llamas a fusionar sin &nr el tamaño del resultado nunca llega al exterior. El error de olvidar el tamaño aparece si intentas hacer la fusión sin pasar na y nb, la función no tiene forma de saber hasta dónde llegan los arrays.

Los casos especiales que tienes que probar: un array vacío (na=0 o nb=0), arrays con elementos repetidos entre sí, y arrays de distinto tamaño.


Soluciones Comentadas

Solución Ejercicio 1:

#include <stdio.h>

/* Prototipos */
int maximo(int vec[], int n);
int segundo_maximo(int vec[], int n);
void mostrar_array(int vec[], int n);

int main(void) {
    int a[8] = {42, 7, 19, 85, 26, 85, 54, 13};
    int b[4] = {10, 10, 10, 10};
    int c[2] = {5, 3};
    int segundo;

    /* Array A */
    printf("Array: "); mostrar_array(a, 8);
    printf("Máximo:         %d\n", maximo(a, 8));
    segundo = segundo_maximo(a, 8);
    if (segundo == -1)
        printf("Segundo máximo: no existe\n\n");
    else
        printf("Segundo máximo: %d\n\n", segundo);

    /* Array B — todos iguales */
    printf("Array: "); mostrar_array(b, 4);
    printf("Máximo:         %d\n", maximo(b, 4));
    segundo = segundo_maximo(b, 4);
    if (segundo == -1)
        printf("Segundo máximo: no existe (todos los elementos son iguales)\n\n");
    else
        printf("Segundo máximo: %d\n\n", segundo);

    /* Array C — dos elementos */
    printf("Array: "); mostrar_array(c, 2);
    printf("Máximo:         %d\n", maximo(c, 2));
    segundo = segundo_maximo(c, 2);
    if (segundo == -1)
        printf("Segundo máximo: no existe\n\n");
    else
        printf("Segundo máximo: %d\n\n", segundo);

    return 0;
}

int maximo(int vec[], int n) {
    int i, max = vec[0];
    for (i = 1; i < n; i++)
        if (vec[i] > max) max = vec[i];
    return max;
}

int segundo_maximo(int vec[], int n) {
    int i;
    int max = maximo(vec, n);    /* primero encontramos el máximo */
    int segundo = -1;            /* -1 = no encontrado todavía */

    /* buscamos el mayor valor estrictamente menor que max */
    for (i = 0; i < n; i++) {
        if (vec[i] < max) {      /* solo valores distintos del máximo */
            if (segundo == -1 || vec[i] > segundo)
                segundo = vec[i];
        }
    }
    return segundo;    /* -1 si no existe segundo máximo */
}

void mostrar_array(int vec[], int n) {
    int i;
    for (i = 0; i < n; i++) printf("%d ", vec[i]);
    printf("\n");
}

Solución Ejercicio 2:

#include <stdio.h>

#define MAX 100

/* Prototipos */
int eliminar_posicion(int vec[], int *n, int posicion);
void insertar_posicion(int vec[], int *n, int posicion, int valor);
void mostrar_estado(int vec[], int n);
void mostrar_array(int vec[], int n);

int main(void) {
    int vec[MAX] = {10, 20, 30, 40, 50};
    int n = 5;
    int eliminado;

    printf("Array inicial: "); mostrar_array(vec, n);
    printf("Longitud: %d\n\n", n);

    /* Eliminar posición 2 */
    eliminado = eliminar_posicion(vec, &n, 2);
    printf("Eliminando posición 2 (valor %d):\n", eliminado);
    mostrar_estado(vec, n);

    /* Eliminar posición 0 */
    eliminado = eliminar_posicion(vec, &n, 0);
    printf("Eliminando posición 0 (valor %d):\n", eliminado);
    mostrar_estado(vec, n);

    /* Insertar 99 en posición 1 */
    insertar_posicion(vec, &n, 1, 99);
    printf("Insertando 99 en posición 1:\n");
    mostrar_estado(vec, n);

    /* Posición inválida */
    printf("Eliminando posición inválida (5):\n");
    eliminado = eliminar_posicion(vec, &n, 5);
    if (eliminado == -1)
        printf("Posición 5 fuera de rango — array no modificado\n");
    mostrar_estado(vec, n);

    return 0;
}

int eliminar_posicion(int vec[], int *n, int posicion) {
    int i, valor;

    /* Validar posición */
    if (posicion < 0 || posicion >= *n)
        return -1;    /* posición inválida — no modifica nada */

    valor = vec[posicion];    /* guardar el valor antes de eliminarlo */

    /* Desplazar hacia la izquierda desde posicion+1 */
    for (i = posicion; i < *n - 1; i++)
        vec[i] = vec[i + 1];

    (*n)--;    /* el array tiene un elemento menos */
    return valor;
}

void insertar_posicion(int vec[], int *n, int posicion, int valor) {
    int i;

    /* Validar posición — puede insertar al final (posicion == *n) */
    if (posicion < 0 || posicion > *n)
        return;

    /* Desplazar hacia la derecha desde el final hasta posicion */
    /* IMPORTANTE: empezar desde el final para no sobrescribir */
    for (i = *n; i > posicion; i--)
        vec[i] = vec[i - 1];

    vec[posicion] = valor;    /* colocar el nuevo elemento */
    (*n)++;                   /* el array tiene un elemento más */
}

void mostrar_estado(int vec[], int n) {
    printf("Array: "); mostrar_array(vec, n);
    printf("Longitud: %d\n\n", n);
}

void mostrar_array(int vec[], int n) {
    int i;
    for (i = 0; i < n; i++) printf("%d ", vec[i]);
    printf("\n");
}

Solución Ejercicio 3:

#include <stdio.h>

#define MAX 200

/* Prototipos */
void fusionar(int a[], int na, int b[], int nb,
              int resultado[], int *nr);
void ordenar(int vec[], int n);
void intercambiar(int *a, int *b);
void mostrar_array(int vec[], int n);

int main(void) {
    int a[5] = {3, 7, 11, 15, 22};
    int b[7] = {1, 5, 9, 12, 18, 25, 30};
    int resultado[MAX];
    int nr;

    /* Caso normal */
    printf("Array A (ordenado): "); mostrar_array(a, 5);
    printf("Array B (ordenado): "); mostrar_array(b, 7);
    fusionar(a, 5, b, 7, resultado, &nr);
    printf("Fusionados: "); mostrar_array(resultado, nr);
    printf("Longitud resultado: %d\n\n", nr);

    /* Caso con repetidos */
    int c[4] = {2, 4, 6, 8};
    int d[5] = {3, 4, 7, 8, 9};
    printf("Caso con repetidos:\n");
    printf("Array A: "); mostrar_array(c, 4);
    printf("Array B: "); mostrar_array(d, 5);
    fusionar(c, 4, d, 5, resultado, &nr);
    printf("Fusionados: "); mostrar_array(resultado, nr);
    printf("Longitud resultado: %d\n\n", nr);

    /* Caso vacío */
    int e[3] = {1, 3, 5};
    int f[1] = {0};    /* array vacío — na=0 */
    printf("Caso vacío:\n");
    printf("Array A: "); mostrar_array(e, 3);
    printf("Array B: (vacío)\n");
    fusionar(e, 3, f, 0, resultado, &nr);
    printf("Fusionados: "); mostrar_array(resultado, nr);
    printf("Longitud resultado: %d\n", nr);

    return 0;
}

void fusionar(int a[], int na, int b[], int nb,
              int resultado[], int *nr) {
    int i = 0, j = 0, k = 0;

    /* Mientras ambos arrays tengan elementos */
    while (i < na && j < nb) {
        if (a[i] <= b[j]) {
            resultado[k++] = a[i++];    /* toma de A */
        } else {
            resultado[k++] = b[j++];    /* toma de B */
        }
    }

    /* Copiar el resto de A si queda algo */
    while (i < na)
        resultado[k++] = a[i++];

    /* Copiar el resto de B si queda algo */
    while (j < nb)
        resultado[k++] = b[j++];

    *nr = k;    /* tamaño del resultado por referencia */
}

void intercambiar(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

void ordenar(int vec[], int n) {
    int i, j;
    for (i = 0; i < n - 1; i++)
        for (j = 0; j < n - i - 1; j++)
            if (vec[j] > vec[j + 1])
                intercambiar(&vec[j], &vec[j + 1]);
}

void mostrar_array(int vec[], int n) {
    int i;
    for (i = 0; i < n; i++) printf("%d ", vec[i]);
    printf("\n");
}

Chuletario — Funciones en C

/* ============================================
   CHULETARIO — Funciones en C
   Sergio Learns · sergiolearns.com
   ============================================ */

/* ESTRUCTURA BÁSICA */
tipo_retorno nombre(tipo param1, tipo param2) {
    /* cuerpo */
    return valor;    /* si no es void */
}

/* PROTOTIPO — antes de main si la definición va después */
int sumar(int a, int b);           /* con nombres (opcional) */
int sumar(int, int);               /* sin nombres (también válido) */

/* VOID — sin retorno */
void imprimir(int n) {
    printf("%d\n", n);
    /* return; opcional para salir antes */
}

/* VOID — sin parámetros */
int leer(void) {
    int n;
    scanf("%d", &n);
    return n;
}

/* PASO POR VALOR — recibe copia, no modifica original */
void doblar_valor(int n) {
    n = n * 2;    /* solo modifica la copia local */
}
int x = 5;
doblar_valor(x);    /* x sigue siendo 5 */

/* PASO POR REFERENCIA — recibe dirección, modifica original */
void doblar_ref(int *n) {
    *n = *n * 2;    /* modifica el valor en esa dirección */
}
int x = 5;
doblar_ref(&x);     /* x ahora vale 10 — pasamos la dirección */

/* CUÁNDO USAR CADA UNO */
/* ¿La función necesita MODIFICAR la variable? → referencia (*) */
/* ¿La función solo necesita LEER la variable?  → valor */
/* ¿Es un array? → siempre pasa su dirección automáticamente */

/* PASO DE ARRAYS — automáticamente por referencia */
void modificar(int vec[], int n) {
    vec[0] = 99;    /* modifica el array original */
}
int nums[5] = {1, 2, 3, 4, 5};
modificar(nums, 5);    /* sin & — los arrays ya pasan su dirección */

/* int vec[] e int *vec son equivalentes como parámetros */
void f1(int vec[], int n) { ... }
void f2(int *vec, int n) { ... }    /* equivalente */

/* DEVOLVER MÁS DE UN RESULTADO */
/* Usa return para el resultado principal */
/* Usa punteros para los resultados adicionales */
int buscar_maximo(int vec[], int n, int *posicion) {
    int i, pos = 0;
    for (i = 1; i < n; i++)
        if (vec[i] > vec[pos]) pos = i;
    *posicion = pos;     /* posición por referencia */
    return vec[pos];     /* valor con return */
}
int pos;
int max = buscar_maximo(nums, 5, &pos);    /* & obligatorio */

/* MODIFICAR TAMAÑO DE ARRAY */
void eliminar(int vec[], int *n, int pos) {
    int i;
    for (i = pos; i < *n - 1; i++)
        vec[i] = vec[i + 1];
    (*n)--;    /* paréntesis obligatorios — (*n)++ no *n++ */
}
int n = 5;
eliminar(nums, &n, 2);    /* & obligatorio — n cambia */

/* FUNCIÓN QUE LLAMA A OTRA */
float desviacion(int vec[], int n) {
    float v = varianza(vec, n);    /* puede llamar a otra función */
    return raiz_cuadrada(v);
}

/* COPIA PARA NO ALTERAR ORIGINAL */
#define MAX 100
void no_destructivo(int vec[], int n) {
    int copia[MAX];
    int i;
    for (i = 0; i < n; i++) copia[i] = vec[i];
    ordenar(copia, n);    /* trabajar sobre copia */
}

/* PATRÓN INTERCAMBIAR — base de muchos algoritmos */
void intercambiar(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}
intercambiar(&vec[i], &vec[j]);    /* & sobre elementos de array */

/* RETORNAR -1 COMO SEÑAL DE ERROR O "NO ENCONTRADO" */
int buscar(int vec[], int n, int buscado) {
    int i;
    for (i = 0; i < n; i++)
        if (vec[i] == buscado) return i;
    return -1;    /* convenio: -1 = no encontrado */
}

/* ERRORES TÍPICOS */

/* 1. Olvidar & al pasar variable que se modifica */
int n = 5;
eliminar(vec, n, 2);     /* MAL — n no cambia fuera */
eliminar(vec, &n, 2);    /* BIEN */

/* 2. Olvidar pasar el tamaño n junto con el array */
void f(int vec[]) { ... }          /* MAL — no sabe cuántos hay */
void f(int vec[], int n) { ... }   /* BIEN */

/* 3. (*n)++ sin paréntesis */
*n++;       /* MAL — incrementa el puntero, no el valor */
(*n)++;     /* BIEN — incrementa el valor apuntado */

/* 4. Olvidar el prototipo */
int main(void) {
    sumar(3, 4);    /* error si sumar va después y no hay prototipo */
}
int sumar(int a, int b) { return a + b; }
/* SOLUCIÓN: añadir int sumar(int a, int b); antes de main */

/* 5. Devolver valor en función void */
void imprimir(int n) {
    printf("%d\n", n);
    return 5;    /* error de compilación */
}

/* 6. Modificar array pensando que es copia */
void f(int vec[], int n) {
    vec[0] = 99;    /* modifica el original — NO es una copia */
}
/* SOLUCIÓN: copiar el array dentro de la función si no quieres modificarlo */

/* 7. Desplazamiento en orden incorrecto al insertar */
/* Al insertar en posición p, desplazar de DERECHA a IZQUIERDA */
for (i = *n; i > p; i--)
    vec[i] = vec[i - 1];    /* bien — no sobrescribe */
/* Al eliminar en posición p, desplazar de IZQUIERDA a DERECHA */
for (i = p; i < *n - 1; i++)
    vec[i] = vec[i + 1];    /* bien — no sobrescribe */

Publicaciones Similares

Un comentario

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *