Ejercicios Resueltos de Programación en C: Funciones, Punteros y Estructuras
Enviado por Programa Chuletas y clasificado en Informática y Telecomunicaciones
Escrito el en español con un tamaño de 21,53 KB
Función Par/Impar
Escribe una función que tome un número como parámetro y retorne el propio número si es par, y 0 si no lo es.
#include <stdio.h>
int fun(int a) {
// Si el residuo de dividir por 2 es 0, es par
if (a % 2 == 0) {
return a;
} else {
return 0;
}
// Alternativa concisa:
// return (a % 2 == 0) ? a : 0;
}
Función Volumen Esfera
Escribe una función para calcular el volumen de una esfera (V = 4/3 * pi * R³).
#include <stdio.h>
#define PI 3.14159
float vol(float r) {
// Asegurar división flotante usando 4.0 y 3.0
return (4.0 / 3.0 * PI * r * r * r);
}
Convertir If a Switch
Escribe una sentencia switch
que sea equivalente a un bloque if
/else if
/else
dado (Nota: El bloque 'if' original estaba incompleto/confuso, se presenta la corrección del 'switch' proporcionado).
Código original (con errores): If(K==2)K=1; K=5; If(K==)K=2; else K=2;
Corrección del switch
proporcionado:
#include <stdio.h>
void ejemplo_switch(int k) {
switch (k) {
case 2:
k = 1;
// ¡Atención! Falta break, se ejecutará case 1 también (fallthrough)
// Si la intención era k=5 después de k=1, debería ser:
// k = 1;
// k = 5;
// break;
// Si la intención era solo k=1 para case 2:
// k = 1;
// break;
case 1:
k = 2;
break;
default:
k = 2;
break;
}
// El valor final de k depende del valor inicial y del fallthrough
printf("Valor final de k: %d\n", k);
}
Convertir Switch a If
Convierte la siguiente sentencia switch
a instrucciones if
/else if
/else
:
Sentencia switch
original (con errores tipográficos): Switch (K){ Case 2:K=0;break; Case 1K=3;break; Default:K=5; }
switch
corregido:
switch (k) {
case 2:
k = 0;
break;
case 1:
k = 3;
break;
default:
k = 5;
break;
}
Equivalente en if
/else if
/else
:
if (k == 2) {
k = 0;
} else if (k == 1) {
k = 3;
} else {
k = 5;
}
Función Raíz Cuadrada del Mayor
Escribe una función que devuelva la raíz cuadrada del mayor de dos números.
#include <math.h> // Necesario para sqrt()
#include <stdio.h>
double raiz_mayor(double a, double b) {
if (a > b) {
return sqrt(a);
} else {
return sqrt(b);
}
// Alternativa:
// return sqrt((a > b) ? a : b);
}
Definición de Estructura y Variable desde Scanf (Variable)
Si para leer desde teclado los campos de una variable `pedro` de tipo `struct pe` se utiliza el código scanf("%d", &pedro.tf); scanf("%s", pedro.nombre);
, escribe la definición de la estructura y la declaración de la variable.
Código original (con errores): Struct pe{ Int tf; Char nombre [20]; } Struct Ag Pedro,*p; Scanf (%d,&Pedro.tf); Scanf(%s,&Pedro.nombre[0]);
Definición y declaración corregidas:
#include <stdio.h>
// Definición de la estructura
struct pe {
int tf;
char nombre[20]; // Suficiente espacio para scanf %s
};
int main() {
// Declaración de la variable
struct pe pedro;
// Código de lectura (ejemplo)
printf("Introduce tf: ");
scanf("%d", &pedro.tf);
printf("Introduce nombre: ");
// Leer directamente en el array (sin &)
// Asegurarse que la entrada no exceda 19 caracteres + nulo
scanf("%19s", pedro.nombre);
printf("Leído: tf=%d, nombre=%s\n", pedro.tf, pedro.nombre);
return 0;
}
Lectura en Campo de Estructura en Array
Utilizando la siguiente definición de estructura y array: struct Barco { int manga; char *nom; } a[20];
Escribe las instrucciones necesarias para poder leer mediante scanf
una cadena en el campo nom
del cuarto elemento del array a
(índice 3).
#include <stdio.h>
#include <stdlib.h> // Necesario para malloc()
struct Barco {
int manga;
char *nom;
};
int main() {
struct Barco a[20];
int buffer_size = 50; // Tamaño para el nombre
// 1. Asignar memoria para el campo 'nom' del cuarto elemento (a[3])
a[3].nom = (char *)malloc(buffer_size * sizeof(char));
// Verificar si malloc tuvo éxito
if (a[3].nom == NULL) {
perror("Error al asignar memoria");
return 1;
}
// 2. Leer la cadena usando scanf
printf("Introduce el nombre del barco para a[3]: ");
// Usar %49s para prevenir desbordamiento (buffer_size - 1)
scanf("%49s", a[3].nom);
printf("Nombre leído para a[3]: %s\n", a[3].nom);
// Liberar memoria asignada cuando ya no se necesite
free(a[3].nom);
return 0;
}
Lectura en Campo de Estructura en Array (usando Puntero Auxiliar)
Realiza la misma operación anterior, pero utilizando un puntero a carácter denominado p
.
#include <stdio.h>
#include <stdlib.h>
struct Barco {
int manga;
char *nom;
};
int main() {
struct Barco a[20];
int buffer_size = 50;
char *p; // Puntero auxiliar
// Asignar memoria para el campo 'nom' del cuarto elemento (a[3])
a[3].nom = (char *)malloc(buffer_size * sizeof(char));
if (a[3].nom == NULL) {
perror("Error al asignar memoria");
return 1;
}
// Hacer que p apunte a la memoria asignada para a[3].nom
p = a[3].nom;
// Leer la cadena usando scanf con el puntero p
printf("Introduce el nombre del barco para a[3] (vía p): ");
scanf("%49s", p);
printf("Nombre leído (vía p): %s\n", p);
printf("Nombre leído (directo): %s\n", a[3].nom);
// Liberar memoria
free(a[3].nom); // O free(p), ya que apuntan a lo mismo
return 0;
}
Función Comprobar si es Primo (v1)
Escribe una función que devuelva 0 si un número es primo y 1 si no lo es (es compuesto).
#include <stdio.h>
// Devuelve 0 si p es primo, 1 si es compuesto
int es_compuesto(int p) {
// Casos base: 0, 1 y negativos no son primos
if (p <= 1) {
return 1; // No es primo (es compuesto o caso especial)
}
// Comprobar divisibilidad desde 2 hasta p/2 (optimización)
// Se puede optimizar más hasta sqrt(p)
for (int div = 2; div <= p / 2; div++) {
if (p % div == 0) {
return 1; // Encontró un divisor, no es primo
}
}
// Si no encontró divisores, es primo
return 0;
}
Función Superficie Esfera
Escribe una función para calcular la superficie de una esfera (S = 4 * pi * R²).
#include <stdio.h>
#define PI 3.14159
float sup(float r) {
return 4.0 * PI * r * r;
}
Puntero para Almacenar Caracteres
Define y asigna memoria a un puntero para poder almacenar (indexar) 20 caracteres.
#include <stdlib.h>
char *p = (char *)malloc(20 * sizeof(char));
// Es buena práctica verificar si p es NULL después de malloc
if (p == NULL) {
// Manejar error de asignación
}
Puntero para Almacenar Enteros
Define y asigna memoria a un puntero para poder almacenar (indexar) 10 enteros.
#include <stdlib.h>
int *p = (int *)malloc(10 * sizeof(int));
// Es buena práctica verificar si p es NULL después de malloc
if (p == NULL) {
// Manejar error de asignación
}
Función Comprobar si es Primo (v2 - `prim`)
Escribe una función denominada prim
con un argumento entero que devuelva 0 si éste es primo y 1 en caso contrario.
#include <stdio.h>
// Devuelve 0 si j es primo, 1 si es compuesto
int prim(int j) {
if (j <= 1) {
return 1; // No es primo
}
// Bucle while para encontrar un divisor
int i = 2;
// Mientras i*i <= j (optimización sqrt) y no se encuentre divisor
while (i * i <= j) {
if (j % i == 0) {
return 1; // Encontró divisor, no es primo
}
i++;
}
// Si el bucle termina sin encontrar divisor, es primo
return 0;
}
Asignación y Lectura en Campo Char de Puntero a Struct
Completa el código necesario para asignar memoria y leer una cadena de hasta 19 caracteres (más el nulo) en el campo ch
de una estructura apuntada por *s
:
#include <stdio.h>
#include <stdlib.h>
// Suponiendo que struct Ag está definida así:
struct Ag {
char *ch;
// otros miembros...
};
int main() {
struct Ag *s;
// 1. Asignar memoria para la estructura
s = (struct Ag *)malloc(sizeof(struct Ag));
if (s == NULL) {
perror("Fallo malloc para struct Ag");
return 1;
}
// 2. Asignar memoria para el campo 'ch' (ej: 20 bytes)
s->ch = (char *)malloc(20 * sizeof(char));
if (s->ch == NULL) {
perror("Fallo malloc para s->ch");
free(s); // Liberar la estructura si falla la asignación del miembro
return 1;
}
// 3. Leer la cadena en s->ch
printf("Introduce la cadena para ch: ");
scanf("%19s", s->ch); // Limitar a 19 caracteres para evitar desbordamiento
printf("Cadena leída: %s\n", s->ch);
// Liberar memoria
free(s->ch);
free(s);
return 0;
}
Definición de Estructura y Variable desde Scanf (Variable)
Si para leer los campos de una variable a
de tipo struct Ag
se utiliza el siguiente código scanf("%s", a.nombre); scanf("%d", &a.tf); scanf("%d", &a.edad);
, escribe la definición de la estructura struct Ag
y la declaración de la variable a
.
#include <stdio.h>
// Definición de la estructura
struct Ag {
char nombre[20]; // Asegurar tamaño suficiente
int tf;
int edad;
};
int main() {
// Declaración de la variable
struct Ag a;
// Código de lectura (ejemplo)
printf("Introduce nombre (max 19 char): ");
scanf("%19s", a.nombre);
printf("Introduce tf: ");
scanf("%d", &a.tf);
printf("Introduce edad: ");
scanf("%d", &a.edad);
printf("Leído: nombre=%s, tf=%d, edad=%d\n", a.nombre, a.tf, a.edad);
return 0;
}
Programa para Leer Cadena con Puntero
Escribe un programa completo para leer una cadena de hasta 19 caracteres (más el nulo) desde la entrada estándar y almacenarla en memoria asignada dinámicamente usando un puntero.
#include <stdio.h>
#include <stdlib.h> // Necesario para malloc y free
int main() {
char *p;
int buffer_size = 20;
// Asignar memoria
p = (char *)malloc(buffer_size * sizeof(char));
if (p == NULL) {
perror("Fallo al asignar memoria");
return 1;
}
// Solicitar y leer la cadena
printf("Introduzca una cadena (max %d caracteres): ", buffer_size - 1);
scanf("%19s", p); // Usar %19s para buffer_size = 20
// Imprimir la cadena leída (opcional)
printf("Cadena leída: %s\n", p);
// Liberar la memoria asignada
free(p);
return 0;
}
Macro Mínimo de Dos Enteros
Escribe una macro que devuelva el mínimo de dos números enteros.
#define minimo(a, b) ((a) < (b) ? (a) : (b))
// Ejemplo de uso:
// int x = 5, y = 10;
// int min_val = minimo(x, y); // min_val será 5
Nota: Es crucial usar paréntesis alrededor de los argumentos y de toda la expresión en las macros para evitar problemas con el orden de operaciones.
Función Máximo de Dos Reales
Escribe una función que devuelva el máximo de dos números reales (flotantes).
#include <stdio.h>
float maximo(float a, float b) {
return (a > b) ? a : b;
}
// Ejemplo de uso:
// float x = 3.14, y = 2.71;
// float max_val = maximo(x, y); // max_val será 3.14
Bucle For para Encontrar Divisor
Suponiendo int div = 2;
y int cp >= 2;
, escribe una única instrucción for
(sin cuerpo, solo la cabecera y el punto y coma final) que incremente div
hasta que sea un divisor de cp
. Si cp
es primo, div
terminará siendo igual a cp
.
// Asumiendo int div = 2; int cp = /* algún valor >= 2 */;
// El bucle incrementa 'div' mientras 'cp % div' sea diferente de 0 (verdadero)
// Se detiene cuando 'cp % div' es 0 (falso), es decir, 'div' es un divisor.
for ( ; cp % div != 0; div++);
// Después del bucle, 'div' contiene el menor divisor de 'cp' (mayor o igual a 2).
// Si cp era primo, entonces div == cp.
Declaración de Estructura y Puntero desde Scanf
Si para leer los campos de una estructura apuntada por p
se utiliza el código scanf("%s", p->nombre); scanf("%d", &p->tf); scanf("%f", &p->estatura);
, declara la estructura agenda
y la variable puntero p
. Asegúrate de que p
apunte a memoria válida y que p->nombre
también lo haga antes de usar scanf
.
#include <stdio.h>
#include <stdlib.h>
// 1. Declaración de la estructura
struct agenda {
int tf;
float estatura;
char *nombre; // Puntero a char, necesita asignación de memoria
};
int main() {
// 2. Declaración del puntero
struct agenda *p;
int nombre_buffer_size = 50; // Tamaño para el nombre
// --- Antes de usar scanf, es IMPRESCINDIBLE asignar memoria ---
// 3. Asignar memoria para la estructura apuntada por p
p = (struct agenda *)malloc(sizeof(struct agenda));
if (p == NULL) {
perror("Fallo malloc para struct agenda");
return 1;
}
// 4. Asignar memoria para el campo nombre dentro de la estructura
p->nombre = (char *)malloc(nombre_buffer_size * sizeof(char));
if (p->nombre == NULL) {
perror("Fallo malloc para p->nombre");
free(p); // Liberar la estructura si falla la asignación del miembro
return 1;
}
// --- Ahora sí se puede usar scanf ---
printf("Introduce nombre (max %d char): ", nombre_buffer_size - 1);
scanf("%49s", p->nombre); // Usar %49s para buffer de 50
printf("Introduce tf: ");
scanf("%d", &p->tf);
printf("Introduce estatura: ");
scanf("%f", &p->estatura);
printf("Leído: nombre=%s, tf=%d, estatura=%.2f\n", p->nombre, p->tf, p->estatura);
// --- Liberar memoria al final ---
free(p->nombre);
free(p);
return 0;
}
Ejemplo Función vs Macro (Mínimo)
Muestra un ejemplo de una macro y una función equivalente que realicen la misma tarea (calcular el mínimo).
#include <stdio.h>
// Macro para calcular el mínimo
#define macro_minimo(a, b) ((a) < (b) ? (a) : (b))
// Función equivalente para calcular el mínimo
float funcion_minimo(float a, float b) {
return (a < b) ? a : b;
}
int main() {
float x = 10.5, y = 5.2;
int i = 10, j = 5;
printf("Mínimo (macro float): %f\n", macro_minimo(x, y));
printf("Mínimo (función float): %f\n", funcion_minimo(x, y));
printf("Mínimo (macro int): %d\n", macro_minimo(i, j));
// printf("Mínimo (función int): %f\n", funcion_minimo(i, j)); // Warning: implicit conversion
// Ejemplo de posible problema con macro si no se usan paréntesis
// #define bad_macro_min(a,b) a < b ? a : b
// printf("%d\n", 10 * bad_macro_min(3,4)); // Expande a 10 * 3 < 4 ? 3 : 4 -> (30 < 4) ? 3 : 4 -> 4 (Incorrecto)
printf("Mínimo (macro segura): %d\n", 10 * macro_minimo(3, 4)); // Expande a 10 * ((3) < (4) ? (3) : (4)) -> 10 * 3 -> 30 (Correcto)
return 0;
}
Lectura en Campo de Struct Array (vía Puntero a Struct)
Dada la siguiente estructura y declaraciones: struct g { int c; float r; char *ch; }; struct g *p, a[20];
Escribe el código necesario para asignar memoria y leer mediante scanf
una cadena de hasta 19 caracteres en el campo ch
del quinto elemento del array a
(índice 4), utilizando el puntero p
para acceder a dicho elemento.
#include <stdio.h>
#include <stdlib.h>
struct g {
int c;
float r;
char *ch;
};
int main() {
struct g a[20];
struct g *p;
int buffer_size = 20;
// 1. Hacer que p apunte al quinto elemento (índice 4) del array a
p = &a[4];
// 2. Asignar memoria para el campo ch del elemento apuntado por p
p->ch = (char *)malloc(buffer_size * sizeof(char));
if (p->ch == NULL) {
perror("Fallo malloc para p->ch");
return 1;
}
// 3. Leer la cadena usando scanf a través del puntero p
printf("Introduce cadena para a[4].ch (vía p): ");
scanf("%19s", p->ch); // Limitar a buffer_size - 1
printf("Cadena leída en a[4].ch (vía p): %s\n", p->ch);
// También accesible directamente como a[4].ch
printf("Cadena leída en a[4].ch (directo): %s\n", a[4].ch);
// Liberar memoria
free(p->ch); // O free(a[4].ch)
return 0;
}
Programa para Indexar Puntero a Entero
Escribe un programa que asigne memoria a un puntero a entero j
para almacenar 3 enteros, y luego asigne los valores 1, 2 y 3 a esos espacios de memoria usando indexación.
#include <stdio.h>
#include <stdlib.h>
int main() {
int *j;
int num_elementos = 3;
// Asignar memoria para 3 enteros
j = (int *)malloc(num_elementos * sizeof(int));
if (j == NULL) {
perror("Fallo al asignar memoria");
return 1;
}
// Asignar valores usando indexación como si fuera un array
j[0] = 1;
j[1] = 2;
j[2] = 3;
// Imprimir los valores para verificar (opcional)
printf("Valores asignados: ");
for (int i = 0; i < num_elementos; i++) {
printf("%d ", j[i]); // Acceso usando indexación
// Alternativa: printf("%d ", *(j + i)); // Acceso usando aritmética de punteros
}
printf("\n");
// Liberar la memoria asignada
free(j);
return 0;
}
Función Primo con While/If (Devuelve 'S'/'N')
Usando un bucle while
y sentencias if
, escribe una función llamada primo
que tome un entero como entrada y devuelva el carácter 'S' si el número es primo, y 'N' en caso contrario.
#include <stdio.h>
char primo(int j) {
// Casos base: 0, 1 y negativos no son primos
if (j <= 1) {
return 'N';
}
int i = 2;
// Bucle while: continuar mientras i*i <= j (optimización)
while (i * i <= j) {
// Sentencia if: comprobar si j es divisible por i
if (j % i == 0) {
return 'N'; // Encontró un divisor, no es primo
}
i++; // Incrementar el posible divisor
}
// Si el bucle termina sin encontrar divisores, es primo
return 'S';
}
// Ejemplo de uso
int main() {
int num = 17;
printf("¿Es %d primo? %c\n", num, primo(num)); // Salida: ¿Es 17 primo? S
num = 18;
printf("¿Es %d primo? %c\n", num, primo(num)); // Salida: ¿Es 18 primo? N
return 0;
}
Asignación de Memoria para Puntero a Struct y su Miembro Char*
Suponiendo que q
es un puntero a struct Barco
(que contiene un miembro char *nombre
), escribe las dos líneas de código necesarias para asignar memoria tanto para la estructura apuntada por q
como para su miembro nombre
(con espacio para 20 caracteres).
#include <stdlib.h>
// Suponiendo:
struct Barco {
char *nombre;
// otros miembros...
};
int main() {
struct Barco *q;
int nombre_buffer_size = 20;
// 1. Asignar memoria para la estructura struct Barco
q = (struct Barco *)malloc(sizeof(struct Barco));
if (q == NULL) {
// Manejar error
return 1;
}
// 2. Asignar memoria para el campo nombre dentro de la estructura
q->nombre = (char *)malloc(nombre_buffer_size * sizeof(char));
if (q->nombre == NULL) {
// Manejar error (y liberar 'q' si es necesario)
free(q);
return 1;
}
// Ahora q y q->nombre apuntan a memoria válida
// ... usar q y q->nombre ...
// Liberar memoria al final (en orden inverso a la asignación)
free(q->nombre);
free(q);
return 0;
}
Macro y Función para Volumen de Esfera
Escribe una macro para calcular el volumen de una esfera (V = 4/3 * pi * R³). Incluye también la versión como función.
#include <stdio.h>
#define PI 3.14159
// Macro para el volumen de la esfera
// Asegurar división flotante (4.0/3.0) y paréntesis para seguridad
#define vol_macro(r) ( (4.0 / 3.0) * PI * (r) * (r) * (r) )
// Función para el volumen de la esfera
float vol_funcion(float r) {
return (4.0 / 3.0) * PI * r * r * r;
}
int main() {
float radio = 2.5;
printf("Volumen (macro): %f\n", vol_macro(radio));
printf("Volumen (función): %f\n", vol_funcion(radio));
return 0;
}