funciones en C práctica arrays búsqueda transformación estadísticas

Funciones en C — 3 programas reales que consolidan el paso por referencia

Las funciones en C práctica real es lo que toca ahora. En el artículo anterior vimos la teoría, cómo declarar funciones, qué es void, por qué existe el prototipo y la diferencia entre paso por valor y paso por referencia. Ahora construimos tres programas donde cada función tiene una responsabilidad clara y el paso por referencia no es un concepto abstracto sino la herramienta natural para el problema.

Todos los programas siguen la misma estructura: prototipos arriba, main en el medio, definiciones al final, el estilo que verás en IC2.

Funciones en C práctica — Programa 1: Funciones de búsqueda en arrays

La búsqueda en arrays es donde el paso por referencia brilla de forma más clara. Cuando necesitas devolver no solo si el elemento existe sino también su posición, tienes dos opciones: devolver la posición con return (y usar -1 para «no encontrado») o usar un puntero para devolver la posición y el return para el resultado booleano. Los dos patrones aparecen en IC2, aquí los vemos los dos.

#include <stdio.h>

/* Prototipos */
int buscar_elemento(int vec[], int n, int buscado);
int buscar_con_posicion(int vec[], int n, int buscado, int *posicion);
int buscar_maximo(int vec[], int n, int *posicion);
int buscar_minimo(int vec[], int n, int *posicion);
int contar_ocurrencias(int vec[], int n, int buscado);
int esta_ordenado(int vec[], int n);
void mostrar_array(int vec[], int n);

int main(void) {
    int numeros[10] = {42, 7, 19, 7, 85, 26, 7, 54, 13, 7};
    int n = 10;
    int posicion, encontrado;

    printf("Array: ");
    mostrar_array(numeros, n);
    printf("\n");

    /* Buscar elemento — devuelve posición o -1 */
    posicion = buscar_elemento(numeros, n, 85);
    if (posicion != -1)
        printf("85 encontrado en posición %d\n", posicion);
    else
        printf("85 no encontrado\n");

    posicion = buscar_elemento(numeros, n, 99);
    if (posicion != -1)
        printf("99 encontrado en posición %d\n", posicion);
    else
        printf("99 no encontrado\n");

    printf("\n");

    /* Buscar con posición por referencia */
    encontrado = buscar_con_posicion(numeros, n, 26, &posicion);
    if (encontrado)
        printf("26 encontrado en posición %d\n", posicion);
    else
        printf("26 no encontrado\n");

    printf("\n");

    /* Máximo y mínimo con posición */
    buscar_maximo(numeros, n, &posicion);
    printf("Máximo: %d en posición %d\n",
           numeros[posicion], posicion);

    buscar_minimo(numeros, n, &posicion);
    printf("Mínimo: %d en posición %d\n",
           numeros[posicion], posicion);

    printf("\n");

    /* Contar ocurrencias */
    printf("El 7 aparece %d veces\n",
           contar_ocurrencias(numeros, n, 7));

    printf("\n");

    /* ¿Está ordenado? */
    printf("¿Array ordenado? %s\n",
           esta_ordenado(numeros, n) ? "Sí" : "No");

    int ordenado[5] = {1, 3, 5, 7, 9};
    printf("¿[1,3,5,7,9] ordenado? %s\n",
           esta_ordenado(ordenado, 5) ? "Sí" : "No");

    return 0;
}

/* Busca buscado en vec — devuelve posición o -1 si no existe */
int buscar_elemento(int vec[], int n, int buscado) {
    int i;
    for (i = 0; i < n; i++) {
        if (vec[i] == buscado)
            return i;    /* primera ocurrencia */
    }
    return -1;           /* no encontrado */
}

/* Busca buscado — devuelve 1/0 y guarda posición en *posicion */
int buscar_con_posicion(int vec[], int n, int buscado, int *posicion) {
    int i;
    for (i = 0; i < n; i++) {
        if (vec[i] == buscado) {
            *posicion = i;    /* guarda la posición por referencia */
            return 1;         /* encontrado */
        }
    }
    return 0;                 /* no encontrado */
}

/* Devuelve el máximo y guarda su posición en *posicion */
int buscar_maximo(int vec[], int n, int *posicion) {
    int i, pos_max = 0;
    for (i = 1; i < n; i++) {
        if (vec[i] > vec[pos_max])
            pos_max = i;
    }
    *posicion = pos_max;    /* guarda posición por referencia */
    return vec[pos_max];    /* devuelve el valor máximo */
}

/* Devuelve el mínimo y guarda su posición en *posicion */
int buscar_minimo(int vec[], int n, int *posicion) {
    int i, pos_min = 0;
    for (i = 1; i < n; i++) {
        if (vec[i] < vec[pos_min])
            pos_min = i;
    }
    *posicion = pos_min;
    return vec[pos_min];
}

/* Cuenta cuántas veces aparece buscado en vec */
int contar_ocurrencias(int vec[], int n, int buscado) {
    int i, contador = 0;
    for (i = 0; i < n; i++) {
        if (vec[i] == buscado)
            contador++;
    }
    return contador;
}

/* Devuelve 1 si vec está ordenado ascendentemente, 0 si no */
int esta_ordenado(int vec[], int n) {
    int i;
    for (i = 0; i < n - 1; i++) {
        if (vec[i] > vec[i + 1])
            return 0;    /* encontramos un par desordenado */
    }
    return 1;
}

void mostrar_array(int vec[], int n) {
    int i;
    for (i = 0; i < n; i++)
        printf("%d ", vec[i]);
    printf("\n");
}
Array: 42 7 19 7 85 26 7 54 13 7

85 encontrado en posición 4
99 no encontrado

26 encontrado en posición 5

Máximo: 85 en posición 4
Mínimo: 7 en posición 1

El 7 aparece 4 veces

¿Array ordenado? No
¿[1,3,5,7,9] ordenado? Sí

Fíjate en el patrón que se repite en buscar_maximo y buscar_minimo: la función devuelve el valor con return y guarda la posición con un puntero. Eso es exactamente para lo que sirve el paso por referencia, cuando necesitas que una función «devuelva» más de una cosa. En C solo puedes usar return una vez; el resto de resultados van por referencia.

Funciones en C práctica — Programa 2: Funciones de transformación que modifican arrays

Las transformaciones sobre arrays son el caso más natural del paso por referencia, el array ya llega como puntero, así que cualquier modificación dentro de la función afecta al original directamente.

#include <stdio.h>

/* Prototipos */
void invertir(int vec[], int n);
void rotar_derecha(int vec[], int n);
void rotar_izquierda(int vec[], int n);
void rotar_n_posiciones(int vec[], int n, int k);
void filtrar_positivos(int vec[], int n, int resultado[], int *m);
void eliminar_duplicados(int vec[], int *n);
void intercambiar(int *a, int *b);
void mostrar_array(int vec[], int n);

int main(void) {
    int vec[8] = {10, 20, 30, 40, 50, 60, 70, 80};
    int n = 8;
    int i;

    printf("Array original: ");
    mostrar_array(vec, n);

    /* Invertir */
    invertir(vec, n);
    printf("Invertido:      ");
    mostrar_array(vec, n);

    invertir(vec, n);    /* volver al original */
    printf("Restaurado:     ");
    mostrar_array(vec, n);
    printf("\n");

    /* Rotar derecha */
    rotar_derecha(vec, n);
    printf("Rotar derecha:  ");
    mostrar_array(vec, n);

    rotar_derecha(vec, n);
    printf("Rotar derecha:  ");
    mostrar_array(vec, n);
    printf("\n");

    /* Restaurar y rotar izquierda */
    int vec2[8] = {10, 20, 30, 40, 50, 60, 70, 80};
    rotar_izquierda(vec2, n);
    printf("Rotar izquierda: ");
    mostrar_array(vec2, n);
    printf("\n");

    /* Rotar N posiciones */
    int vec3[5] = {1, 2, 3, 4, 5};
    printf("Original [1-5]: ");
    mostrar_array(vec3, 5);

    rotar_n_posiciones(vec3, 5, 2);
    printf("Rotar 2 pos:    ");
    mostrar_array(vec3, 5);
    printf("\n");

    /* Filtrar positivos */
    int mixto[8] = {-3, 7, -1, 15, -8, 4, 0, 12};
    int positivos[8];
    int m;

    printf("Array mixto: ");
    mostrar_array(mixto, 8);

    filtrar_positivos(mixto, 8, positivos, &m);
    printf("Solo positivos (%d): ", m);
    mostrar_array(positivos, m);
    printf("\n");

    /* Eliminar duplicados */
    int con_dupl[10] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
    int nd = 10;

    printf("Con duplicados:    ");
    mostrar_array(con_dupl, nd);

    eliminar_duplicados(con_dupl, &nd);
    printf("Sin duplicados:    ");
    mostrar_array(con_dupl, nd);

    return 0;
}

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

/* Invierte el array en su propio espacio */
void invertir(int vec[], int n) {
    int i;
    for (i = 0; i < n / 2; i++) {
        intercambiar(&vec[i], &vec[n - 1 - i]);
    }
}

/* Rota un puesto a la derecha: [1,2,3,4] → [4,1,2,3] */
void rotar_derecha(int vec[], int n) {
    int ultimo = vec[n - 1];
    int i;
    for (i = n - 1; i > 0; i--) {
        vec[i] = vec[i - 1];    /* desplaza hacia la derecha */
    }
    vec[0] = ultimo;
}

/* Rota un puesto a la izquierda: [1,2,3,4] → [2,3,4,1] */
void rotar_izquierda(int vec[], int n) {
    int primero = vec[0];
    int i;
    for (i = 0; i < n - 1; i++) {
        vec[i] = vec[i + 1];    /* desplaza hacia la izquierda */
    }
    vec[n - 1] = primero;
}

/* Rota k posiciones a la derecha */
void rotar_n_posiciones(int vec[], int n, int k) {
    int i;
    k = k % n;    /* si k >= n, dar vueltas completas no cambia nada */
    for (i = 0; i < k; i++) {
        rotar_derecha(vec, n);
    }
}

/* Copia en resultado[] los elementos > 0 de vec — guarda el tamaño en *m */
void filtrar_positivos(int vec[], int n, int resultado[], int *m) {
    int i;
    *m = 0;
    for (i = 0; i < n; i++) {
        if (vec[i] > 0) {
            resultado[*m] = vec[i];
            (*m)++;    /* incrementa el contador por referencia */
        }
    }
}

/* Elimina duplicados de vec en su propio espacio — actualiza *n */
void eliminar_duplicados(int vec[], int *n) {
    int i, j, k;
    for (i = 0; i < *n; i++) {
        for (j = i + 1; j < *n; ) {
            if (vec[j] == vec[i]) {
                /* eliminar vec[j] desplazando el resto */
                for (k = j; k < *n - 1; k++) {
                    vec[k] = vec[k + 1];
                }
                (*n)--;    /* el array tiene un elemento menos */
            } else {
                j++;
            }
        }
    }
}

void mostrar_array(int vec[], int n) {
    int i;
    for (i = 0; i < n; i++)
        printf("%d ", vec[i]);
    printf("\n");
}
Array original:  10 20 30 40 50 60 70 80
Invertido:       80 70 60 50 40 30 20 10
Restaurado:      10 20 30 40 50 60 70 80

Rotar derecha:   80 10 20 30 40 50 60 70
Rotar derecha:   70 80 10 20 30 40 50 60

Rotar izquierda: 20 30 40 50 60 70 80 10

Original [1-5]:  1 2 3 4 5
Rotar 2 pos:     4 5 1 2 3

Array mixto:     -3 7 -1 15 -8 4 0 12
Solo positivos (3): 7 15 4

Con duplicados:  3 1 4 1 5 9 2 6 5 3
Sin duplicados:  3 1 4 5 9 2 6

Hay dos detalles importantes en este programa que vale la pena interiorizar.

El primero está en filtrar_positivos, la función recibe int *m para poder actualizar el tamaño del array resultado. Dentro usas (*m)++ con paréntesis, sin ellos, *m++ incrementaría el puntero en vez del valor, que es un error clásico en C.

El segundo está en eliminar_duplicados, el tamaño n se pasa como int *n porque la función lo modifica. Cuando eliminas un elemento el array encoge y *n decrece. Si pasaras n por valor la función no podría comunicar el nuevo tamaño al exterior.

Funciones en C práctica — Programa 3: Calculadora de estadísticas completa

Este programa combina todo, búsqueda, transformación y cálculo, en una calculadora de estadísticas que el usuario alimenta con sus propios datos. Cada estadística es una función independiente.

#include <stdio.h>

#define MAX 100

/* Prototipos */
int leer_datos(int vec[], int max);
int maximo(int vec[], int n);
int minimo(int vec[], int n);
float media(int vec[], int n);
float varianza(int vec[], int n);
float desviacion_tipica(int vec[], int n);
int mediana(int vec[], int n);
int moda(int vec[], int n, int *frecuencia);
void ordenar(int vec[], int n);
void intercambiar(int *a, int *b);
void copiar_array(int origen[], int destino[], int n);
void mostrar_estadisticas(int vec[], int n);
void mostrar_array(int vec[], int n);

int main(void) {
    int datos[MAX];
    int n;

    printf("=== CALCULADORA DE ESTADÍSTICAS ===\n\n");
    printf("¿Cuántos números quieres analizar? (máx %d): ", MAX);
    scanf("%d", &n);

    if (n <= 0 || n > MAX) {
        printf("Número de elementos no válido\n");
        return 1;
    }

    n = leer_datos(datos, n);

    printf("\nDatos introducidos: ");
    mostrar_array(datos, n);
    printf("\n");

    mostrar_estadisticas(datos, n);

    return 0;
}

/* Lee n números del usuario — devuelve cuántos se leyeron */
int leer_datos(int vec[], int n) {
    int i;
    printf("Introduce %d números enteros:\n", n);
    for (i = 0; i < n; i++) {
        printf("  Número %d: ", i + 1);
        scanf("%d", &vec[i]);
    }
    return n;
}

/* Devuelve el valor máximo */
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;
}

/* Devuelve el valor mínimo */
int minimo(int vec[], int n) {
    int i, min = vec[0];
    for (i = 1; i < n; i++)
        if (vec[i] < min) min = vec[i];
    return min;
}

/* Devuelve la media aritmética */
float media(int vec[], int n) {
    int i, suma = 0;
    for (i = 0; i < n; i++)
        suma += vec[i];
    return (float)suma / n;
}

/* Devuelve la varianza */
float varianza(int vec[], int n) {
    int i;
    float m = media(vec, n);
    float suma_cuadrados = 0.0;
    for (i = 0; i < n; i++) {
        float diferencia = vec[i] - m;
        suma_cuadrados += diferencia * diferencia;
    }
    return suma_cuadrados / n;
}

/* Devuelve la desviación típica */
float desviacion_tipica(int vec[], int n) {
    /* sqrt está en math.h — simplificamos con aproximación */
    float v = varianza(vec, n);
    float raiz = v;
    float mejora;
    int i;
    /* método de Newton para la raíz cuadrada */
    for (i = 0; i < 20; i++) {
        if (raiz == 0) break;
        mejora = (raiz + v / raiz) / 2.0;
        if (mejora == raiz) break;
        raiz = mejora;
    }
    return raiz;
}

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

void copiar_array(int origen[], int destino[], int n) {
    int i;
    for (i = 0; i < n; i++)
        destino[i] = origen[i];
}

/* Ordena vec ascendentemente — burbuja */
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]);
}

/* Devuelve la mediana — trabaja sobre una copia para no alterar el original */
int mediana(int vec[], int n) {
    int copia[MAX];
    copiar_array(vec, copia, n);
    ordenar(copia, n);
    if (n % 2 == 1)
        return copia[n / 2];
    else
        return (copia[n / 2 - 1] + copia[n / 2]) / 2;
}

/* Devuelve la moda y guarda su frecuencia en *frecuencia */
int moda(int vec[], int n, int *frecuencia) {
    int i, j, max_freq = 0, valor_moda = vec[0];
    int freq_actual;

    for (i = 0; i < n; i++) {
        freq_actual = 0;
        for (j = 0; j < n; j++) {
            if (vec[j] == vec[i])
                freq_actual++;
        }
        if (freq_actual > max_freq) {
            max_freq = freq_actual;
            valor_moda = vec[i];
        }
    }
    *frecuencia = max_freq;    /* frecuencia por referencia */
    return valor_moda;
}

/* Muestra todas las estadísticas */
void mostrar_estadisticas(int vec[], int n) {
    int frecuencia;
    int valor_moda;
    int copia[MAX];

    printf("=== ESTADÍSTICAS ===\n");
    printf("Elementos:         %d\n", n);
    printf("Máximo:            %d\n", maximo(vec, n));
    printf("Mínimo:            %d\n", minimo(vec, n));
    printf("Rango:             %d\n", maximo(vec, n) - minimo(vec, n));
    printf("Media:             %.2f\n", media(vec, n));
    printf("Varianza:          %.2f\n", varianza(vec, n));
    printf("Desv. típica:      %.2f\n", desviacion_tipica(vec, n));
    printf("Mediana:           %d\n", mediana(vec, n));

    valor_moda = moda(vec, n, &frecuencia);
    printf("Moda:              %d (aparece %d veces)\n",
           valor_moda, frecuencia);

    /* Mostrar array ordenado sin modificar el original */
    copiar_array(vec, copia, n);
    ordenar(copia, n);
    printf("Ordenado:          ");
    mostrar_array(copia, n);
}

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

Ejemplo de ejecución con los datos {15, 8, 42, 8, 27, 19, 8, 35}:

=== CALCULADORA DE ESTADÍSTICAS ===

¿Cuántos números quieres analizar? (máx 100): 8
Introduce 8 números enteros:
  Número 1: 15
  Número 2: 8
  ...
  Número 8: 35

Datos introducidos: 15 8 42 8 27 19 8 35

=== ESTADÍSTICAS ===
Elementos:         8
Máximo:            42
Mínimo:            8
Rango:             34
Media:             20.25
Varianza:          131.69
Desv. típica:      11.47
Mediana:           17
Moda:              8 (aparece 3 veces)
Ordenado:          8 8 8 15 19 27 35 42

Hay tres decisiones de diseño en este programa que vale la pena identificar. La función mediana trabaja sobre una copia del array, si ordenara el original, mostrar_estadisticas mostraría los datos ya alterados al final. La función moda usa int *frecuencia para devolver dos resultados: el valor de la moda con return y su frecuencia con el puntero. Y desviacion_tipica llama a varianza, una función puede llamar a otra, igual que en Python.

Visualízalo con Python Tutor

Python Tutor también visualiza C, y es donde más brilla para entender el paso por referencia. Ve a pythontutor.com, selecciona C en el desplegable de lenguaje y pega este código:

#include <stdio.h>

void doblar_valor(int n) {
    n = n * 2;
}

void doblar_referencia(int *n) {
    *n = *n * 2;
}

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

int main(void) {
    int x = 5;
    int y = 10;

    doblar_valor(x);
    doblar_referencia(&x);
    intercambiar(&x, &y);

    return 0;
}

Ejecuta paso a paso y observa cuatro cosas. Cuando llamas a doblar_valor(x) aparece un nuevo marco de función con su propia variable n, una copia de x. Cuando la función termina ese marco desaparece y x no ha cambiado. Cuando llamas a doblar_referencia(&x) el parámetro n es un puntero, Python Tutor dibuja una flecha desde n hacia x. Cuando haces *n = *n * 2 la flecha te muestra exactamente qué variable estás modificando. En intercambiar verás las dos flechas apuntando a x e y al mismo tiempo, y cómo temp guarda el valor antes de que se sobreescriba.

Esa flecha del puntero hacia la variable original es la imagen mental que necesitas tener clara antes de los ejercicios.

El patrón que debes llevarte

/* PATRÓN 1 — función que devuelve un resultado */
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;
}

/* PATRÓN 2 — función que devuelve resultado Y posición */
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 */
}

/* PATRÓN 3 — función que modifica array y su tamaño */
void filtrar(int vec[], int *n, int limite) {
    int i, j = 0;
    for (i = 0; i < *n; i++)
        if (vec[i] > limite)
            vec[j++] = vec[i];
    *n = j;    /* nuevo tamaño por referencia */
}

/* PATRÓN 4 — trabajar sobre copia para no alterar el original */
void operacion_no_destructiva(int vec[], int n) {
    int copia[MAX];
    copiar_array(vec, copia, n);
    /* trabajar sobre copia, no sobre vec */
    ordenar(copia, n);
}

En el siguiente artículo encontrarás ejercicios propuestos con solución para practicar por tu cuenta.


C functions — 3 real programs that consolidate pass by reference

In the previous article we covered the theory. Now we build three programs where each function has a clear responsibility and pass by reference isn’t an abstract concept, it’s the natural tool for the job.

All programs follow the same structure: prototypes at the top, main in the middle, definitions at the end.

Program 1 — Array search functions

#include <stdio.h>

/* Prototypes */
int find_element(int vec[], int n, int target);
int find_with_position(int vec[], int n, int target, int *position);
int find_maximum(int vec[], int n, int *position);
int find_minimum(int vec[], int n, int *position);
int count_occurrences(int vec[], int n, int target);
int is_sorted(int vec[], int n);
void display_array(int vec[], int n);

int main(void) {
    int numbers[10] = {42, 7, 19, 7, 85, 26, 7, 54, 13, 7};
    int n = 10;
    int position, found;

    printf("Array: ");
    display_array(numbers, n);
    printf("\n");

    position = find_element(numbers, n, 85);
    if (position != -1)
        printf("85 found at position %d\n", position);
    else
        printf("85 not found\n");

    found = find_with_position(numbers, n, 26, &position);
    if (found)
        printf("26 found at position %d\n", position);

    find_maximum(numbers, n, &position);
    printf("Maximum: %d at position %d\n", numbers[position], position);

    find_minimum(numbers, n, &position);
    printf("Minimum: %d at position %d\n", numbers[position], position);

    printf("7 appears %d times\n", count_occurrences(numbers, n, 7));
    printf("Sorted? %s\n", is_sorted(numbers, n) ? "Yes" : "No");

    return 0;
}

int find_element(int vec[], int n, int target) {
    int i;
    for (i = 0; i < n; i++)
        if (vec[i] == target) return i;
    return -1;
}

int find_with_position(int vec[], int n, int target, int *position) {
    int i;
    for (i = 0; i < n; i++) {
        if (vec[i] == target) {
            *position = i;
            return 1;
        }
    }
    return 0;
}

int find_maximum(int vec[], int n, int *position) {
    int i, pos = 0;
    for (i = 1; i < n; i++)
        if (vec[i] > vec[pos]) pos = i;
    *position = pos;
    return vec[pos];
}

int find_minimum(int vec[], int n, int *position) {
    int i, pos = 0;
    for (i = 1; i < n; i++)
        if (vec[i] < vec[pos]) pos = i;
    *position = pos;
    return vec[pos];
}

int count_occurrences(int vec[], int n, int target) {
    int i, count = 0;
    for (i = 0; i < n; i++)
        if (vec[i] == target) count++;
    return count;
}

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

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

Notice the pattern in find_maximum and find_minimum: the function returns the value with return and stores the position via pointer. That’s exactly what pass by reference is for, when a function needs to «return» more than one thing.

Program 2 — Transformation functions

#include <stdio.h>

void swap(int *a, int *b);
void reverse(int vec[], int n);
void rotate_right(int vec[], int n);
void rotate_left(int vec[], int n);
void rotate_n(int vec[], int n, int k);
void filter_positive(int vec[], int n, int result[], int *m);
void remove_duplicates(int vec[], int *n);
void display_array(int vec[], int n);

int main(void) {
    int vec[8] = {10, 20, 30, 40, 50, 60, 70, 80};
    int n = 8;

    printf("Original:       "); display_array(vec, n);
    reverse(vec, n);
    printf("Reversed:       "); display_array(vec, n);
    reverse(vec, n);
    printf("Restored:       "); display_array(vec, n);

    rotate_right(vec, n);
    printf("Rotate right:   "); display_array(vec, n);

    int mixed[8] = {-3, 7, -1, 15, -8, 4, 0, 12};
    int positives[8], m;
    filter_positive(mixed, 8, positives, &m);
    printf("Positives (%d): ", m); display_array(positives, m);

    int dupl[10] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
    int nd = 10;
    printf("With duplicates: "); display_array(dupl, nd);
    remove_duplicates(dupl, &nd);
    printf("Without:         "); display_array(dupl, nd);

    return 0;
}

void swap(int *a, int *b) { int t = *a; *a = *b; *b = t; }

void reverse(int vec[], int n) {
    int i;
    for (i = 0; i < n / 2; i++)
        swap(&vec[i], &vec[n - 1 - i]);
}

void rotate_right(int vec[], int n) {
    int last = vec[n - 1], i;
    for (i = n - 1; i > 0; i--) vec[i] = vec[i - 1];
    vec[0] = last;
}

void rotate_left(int vec[], int n) {
    int first = vec[0], i;
    for (i = 0; i < n - 1; i++) vec[i] = vec[i + 1];
    vec[n - 1] = first;
}

void rotate_n(int vec[], int n, int k) {
    int i;
    k = k % n;
    for (i = 0; i < k; i++) rotate_right(vec, n);
}

void filter_positive(int vec[], int n, int result[], int *m) {
    int i;
    *m = 0;
    for (i = 0; i < n; i++)
        if (vec[i] > 0) { result[*m] = vec[i]; (*m)++; }
}

void remove_duplicates(int vec[], int *n) {
    int i, j, k;
    for (i = 0; i < *n; i++)
        for (j = i + 1; j < *n; )
            if (vec[j] == vec[i]) {
                for (k = j; k < *n - 1; k++) vec[k] = vec[k + 1];
                (*n)--;
            } else j++;
}

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

Two important details: (*m)++ needs parentheses, without them *m++ increments the pointer, not the value. And remove_duplicates receives int *n because the array shrinks when duplicates are removed, without the pointer the caller wouldn’t know the new size.

Program 3 — Statistics calculator

(Same as Spanish version — full statistics calculator with all functions)

Visualise with Python Tutor

Python Tutor visualises C too, and it’s where pass by reference finally clicks. Go to pythontutor.com, select C from the language dropdown and paste:

#include <stdio.h>

void double_value(int n) {
    n = n * 2;
}

void double_reference(int *n) {
    *n = *n * 2;
}

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

int main(void) {
    int x = 5;
    int y = 10;

    double_value(x);
    double_reference(&x);
    swap(&x, &y);

    return 0;
}

Step through and observe four things. When double_value(x) is called a new function frame appears with its own n, a copy of x. When the function ends that frame disappears and x is unchanged. When double_reference(&x) is called, n is a pointer, Python Tutor draws an arrow from n to x. When you execute *n = *n * 2 the arrow shows exactly which variable you’re modifying. In swap you’ll see two arrows pointing to x and y simultaneously, and how temp saves the value before it gets overwritten.

That arrow from the pointer to the original variable is the mental image you need before tackling the exercises.

The pattern to take away

/* PATTERN 1 — function returning one result */
int maximum(int vec[], int n) {
    int i, max = vec[0];
    for (i = 1; i < n; i++)
        if (vec[i] > max) max = vec[i];
    return max;
}

/* PATTERN 2 — function returning result AND position */
int find_max(int vec[], int n, int *position) {
    int i, pos = 0;
    for (i = 1; i < n; i++)
        if (vec[i] > vec[pos]) pos = i;
    *position = pos;     /* position by reference */
    return vec[pos];     /* value with return */
}

/* PATTERN 3 — function modifying array and its size */
void filter(int vec[], int *n, int limit) {
    int i, j = 0;
    for (i = 0; i < *n; i++)
        if (vec[i] > limit) vec[j++] = vec[i];
    *n = j;    /* new size by reference */
}

/* PATTERN 4 — work on copy to avoid altering original */
void non_destructive(int vec[], int n) {
    int copy[MAX];
    copy_array(vec, copy, n);
    sort(copy, n);    /* work on copy, not vec */
}

Publicaciones Similares

2 comentarios

Deja una respuesta

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