Parcial de práctica — Introducción a la Computación
Temas: semanas 1 a 7 · Duración: 2 horas
Este es un examen de práctica con el formato del parcial. Sirve para medir
cuánto tiempo les toma cada tipo de pregunta: resuélvanlo en papel, con el reloj
corriendo y sin computadora, y recién después comprueben sus respuestas
compilando en el entorno del curso. El formato general está en
exams/README.md.
Dos horas no alcanzan para todos los temas: el examen real puede preguntar los que aquí
no aparecen, como diagramas de flujo o Git.
Indicaciones
- Los errores menores de sintaxis no importan si la idea es correcta.
- En las preguntas de “qué escribe”, justifiquen con una tabla de variables o una explicación: la salida sola no basta.
- Todo el código compila sin advertencias con
gcc -Wall -Wextra -std=c17, salvo el de la pregunta 8, que tiene errores a propósito. - Supongan el entorno del curso: un
inttiene 32 bits, undoubletiene 64 bits, el texto está en UTF-8, y en ASCII'0'vale 48,'A'vale 65 y'a'vale 97. - Los montos van en céntimos, como enteros, igual que en el curso.
- El pseudocódigo va en el formato del curso:
←,mientras,si,div,mod. - Si les piden una función, no hace falta escribir los
#include.
| Parte | Preguntas |
|---|---|
| A. Representación de datos | 1–3 |
| B. Seguir programas a mano | 4–7 |
| C. Encontrar el bug | 8–9 |
| D. Pseudocódigo y C | 10–11 |
| E. Preguntas cortas | 12–17 |
Parte A — Representación de datos
Pregunta 1 — Bases y complemento a dos
a) Conviertan 173 a binario de 8 bits, mostrando las divisiones, y después a hexadecimal.
b) Escriban -58 en complemento a dos con 8 bits, invirtiendo y sumando 1. Comprueben su resultado sumando los pesos de los bits.
c) ¿Qué número representa el patrón 10110100 sin signo? ¿Y en
complemento a dos con 8 bits? ¿Qué decide cuál de los dos es?
Pregunta 2 — Sumas y overflow
a) Sumen en binario, con 8 bits en complemento a dos,
01011010 + 01000111. Escriban los dos números y el resultado en decimal. ¿Hay
overflow? ¿Cómo se nota en los bits?
b) Sumen 01011010 + 11000110 de la misma forma. Sobra un acarreo a
la izquierda. ¿Eso es overflow? ¿Por qué?
c) Un programa lee 2147483647 con scanf en un int n, y calcula
n + 1. Un compañero dice: “Siempre escribe -2147483648, porque da la vuelta”.
¿Tiene razón? Después, sin ejecutarlo, ¿qué escribe este fragmento, y por qué aquí
sí se puede responder con un número?
unsigned char c = 200;
c = c + 100;
printf("%d\n", c);
Pregunta 3 — Decimales y texto
a) Dupliquen el número y anoten la parte entera en cada paso, como en
fraccion_a_binario, para sacar los primeros 6 bits de la parte fraccionaria de
0.4375 y de 0.7. ¿Cuál de los dos se guarda exactamente en un double? ¿Cómo lo
saben?
b) La letra griega Ω es el código U+03A9. Con la tabla de abajo,
digan cuántos bytes ocupa en UTF-8 y calculen esos bytes en hexadecimal.
| Rango de códigos | Bytes | Patrón de bits |
|---|---|---|
U+0000 a U+007F |
1 | 0xxxxxxx |
U+0080 a U+07FF |
2 | 110xxxxx 10xxxxxx |
U+0800 a U+FFFF |
3 | 1110xxxx 10xxxxxx 10xxxxxx |
c) ¿Cuántos caracteres y cuántos bytes tiene la palabra cañón en
UTF-8?
Parte B — Seguir programas a mano
Pregunta 4 — Expresiones y decisiones
#include <stdio.h>
int main(void) {
int a = 17;
int b = 5;
double c = a / b;
double d = (double) a / b;
int e = a % b * 3 + 2;
int f = -a / b;
int cents = 3 * 1990;
char letter = 'a' + 2;
printf("%.2f %.2f\n", c, d);
printf("%d %d\n", e, f);
printf("S/ %d.%02d\n", cents / 100, cents % 100);
printf("%c %d\n", letter - 32, '7' - '0');
if (b == 0 || a / b > 3) {
printf("P\n");
} else if (a > 10 && !(b > 10)) {
printf("Q\n");
} else {
printf("R\n");
}
return 0;
}
a) ¿Qué escribe? Muestren el orden de las operaciones de e y por qué
c y d son distintos.
b) Escriban !(a > 10 && b <= 5) sin un ! delante del paréntesis.
Aparte: si la primera condición se escribiera a / b > 3 || b == 0, ¿qué pasaría
con b igual a 0? ¿Qué evita el orden original?
Pregunta 5 — Ciclos
#include <stdio.h>
int main(void) {
int i;
int s = 0;
for (i = 20; i > 3; i -= 6) {
s += i;
}
printf("%d %d\n", i, s);
int k = 10;
do {
printf("%d ", k);
k += 5;
} while (k < 10);
printf("%d\n", k);
int n = 2704;
int reversed = 0;
int zeros = 0;
while (n > 0) {
int d = n % 10;
if (d == 0) {
zeros++;
}
reversed = reversed * 10 + d;
n = n / 10;
}
printf("%d %d\n", reversed, zeros);
return 0;
}
a) ¿Qué escribe? Hagan una tabla de variables para el último ciclo.
b) Si n empezara en 1200, ¿qué escribiría la última línea? ¿Por qué
el resultado no tiene cuatro cifras?
c) Si n empezara en 0, ¿cuántas vueltas daría el ciclo? ¿Qué
escribiría la última línea? ¿Es correcto ese conteo de ceros?
d) Reescriban el primer for con while, sin cambiar lo que escribe.
Pregunta 6 — Ciclos anidados
#include <stdio.h>
int main(void) {
int count = 0;
for (int row = 1; row <= 4; row++) {
for (int col = row; col <= 4; col++) {
if ((row + col) % 2 == 0) {
printf("*");
count++;
} else {
printf(".");
}
}
printf("\n");
}
printf("%d\n", count);
return 0;
}
a) ¿Qué escribe?
b) Si se cambian los dos 4 por n, ¿cuántas veces corre el if, en
función de n? ¿Cuántas con n igual a 8 y con n igual a 16? Si n se duplica,
¿el trabajo se duplica? ¿Qué le pasa?
Pregunta 7 — Funciones y la pila
#include <stdio.h>
int twist(int a, int b) {
a = a + b;
b = a - b;
return a * b;
}
int shift(int x) {
int y = twist(x, 2);
x = x + 1;
return y + x;
}
int main(void) {
int x = 3;
int y = shift(x);
printf("%d %d\n", x, y);
printf("%d\n", twist(x, x));
return 0;
}
a) ¿Qué escribe?
b) Dibujen la pila de llamadas en la primera llamada a twist, justo
antes de su return, con el valor de cada variable. Indiquen las que todavía no
tienen valor.
c) shift hace x = x + 1. ¿Por qué la primera línea de la salida
no muestra ese cambio? Si quisieran que el x de main terminara cambiado, ¿cómo lo
harían, con lo que vimos hasta la semana 7?
Parte C — Encontrar el bug
Pregunta 8 — Tres fragmentos
Cada fragmento va dentro del main de un programa con #include <stdio.h>, y
compila con advertencias. Para cada uno, digan qué hace en realidad (si se puede
saber), expliquen el error y corríjanlo.
a) Debe escribir Justo solo si la nota es 11, y la nota no debe
cambiar.
int grade = 8;
if (grade = 11) {
printf("Justo\n");
}
printf("%d\n", grade);
b) El tamaño 1 cuesta 500 céntimos y el tamaño 2 cuesta 800.
int size = 1;
int price = 0;
switch (size) {
case 1:
price = 500;
case 2:
price = 800;
break;
default:
price = 0;
}
printf("%d\n", price);
c) Debe escribir el promedio con dos decimales.
int sum = 47;
int count = 3;
printf("Promedio: %.2f\n", sum / count);
Pregunta 9 — Una función con pruebas
// Devuelve 1 si n es primo y 0 si no. Recibe n >= 0.
int is_prime(int n) {
for (int d = 2; d < n; d++) {
if (n % d == 0) {
return 0;
} else {
return 1;
}
}
return 1;
}
a) Sigan is_prime(9) y is_prime(1). ¿Qué devuelve cada una, y qué
debería devolver? La función responde bien con 2, 3, 4 y 7. ¿Por qué eso no alcanza
para confiar en ella?
b) Corrijan la función. Hay dos errores distintos.
c) Escriban cuatro pruebas con assert. Para cada una, digan qué error
o qué borde revisa.
Parte D — Pseudocódigo y C
Pregunta 10 — Ahorrar para una laptop
Rosa ahorra para una laptop. El primer mes guarda first céntimos, y cada mes
siguiente guarda 100 céntimos más que el mes anterior. Queremos saber cuántos meses
tarda en llegar a goal céntimos o pasarse. Supongan que first es mayor que 0,
que goal no es negativo, y que todas las sumas caben en un int.
a) Escriban el algoritmo meses_para_meta(primero, meta) en
pseudocódigo.
b) Síganlo a mano con primero = 500 y meta = 2000, en una tabla.
c) Tradúzcanlo a la función int months_to_goal(int first, int goal).
d) Escriban dos pruebas con assert para los bordes: que la suma llegue
exactamente a la meta, y que la meta sea 0. Calculen el valor esperado a mano.
Pregunta 11 — Un programa completo
Escriban un programa completo en C. Lee un entero n, y después n notas de 0 a 20.
Escribe cuántas notas son aprobatorias (11 o más) y cuál es la mayor. Si scanf falla,
si n es menor que 1, o si una nota está fuera de rango, escribe un aviso y termina con
return 1. Con la entrada 4 14 9 17 11 debe escribir:
Aprobados: 3
Mayor: 17
Parte E — Preguntas cortas
Respondan cada una en dos o tres líneas.
Pregunta 12 — ¿Es un algoritmo?
algoritmo bajar()
x ← 10
mientras x ≠ 0 hacer
x ← x - 3
fin mientras
escribir x
fin algoritmo
¿Qué condición de un algoritmo no cumple? ¿Qué cambiarían para que la cumpla?
Pregunta 13 — El método de la moneda más grande
Un país tiene monedas de 1, 4 y 6. Sigan el método de “la más grande que cabe” para un vuelto de 8. ¿Da la menor cantidad de monedas? ¿Qué concluyen?
Pregunta 14 — Terminal
Están en /home/rosa/lab03/src. ¿En qué carpeta quedan después de cd ../../lab04?
Pregunta 15 — Tipos de error
Digan cuándo aparece cada problema: al compilar, al ejecutar, o nunca da ningún aviso.
(i) Falta un ;. (ii) Quieren 3.5 y escribieron double x = 7 / 2;. (iii) El programa,
compilado con -fsanitize=undefined, lee un 0 con scanf en b y calcula a / b entre dos int.
Pregunta 16 — Números aleatorios
Escriban una expresión con rand que dé un entero de -2 a 4, con todos los valores
posibles. ¿Para qué sirve fijar la semilla con srand en una simulación?
Pregunta 17 — assert
¿Por qué está mal escribir assert(scanf("%d", &n) == 1); en un programa? Den dos
razones.