Error handling with return codes · Manejo de errores con códigos de retorno
C no tiene try/except
- Algunos lenguajes lanzan excepciones cuando algo sale mal. C no tiene excepciones.
- En su lugar, una función de C informa problemas a través de su valor de retorno, es decir, un código de estado.
- El llamador verifica ese código después de cada llamada y decide qué hacer.
Devolver un código de estado
- Una regla común: devolver
0para indicar éxito y un número negativo como-1para indicar fallo. - Por lo tanto,
int do_thing(...)devuelve0cuando funciona y-1cuando no puede. - La "respuesta" real se devuelve entonces de otra manera (ver el siguiente paso).
Informar la respuesta mediante un puntero de salida
- Si el valor de retorno es un código de estado, ¿dónde va el resultado real? A través de un puntero de salida.
- El llamador pasa la dirección de una variable; la función escribe la respuesta usando
*. - En caso de fallo, la función devuelve
-1y simplemente deja esa variable sin tocar.
Sentinelas para "sin valor"
- Un sentinela es un valor especial que significa "nada aquí":
-1para un índice,NULLpara un puntero. - Las funciones usan sentinelas para que el llamador pueda distinguir el éxito del fallo con una comprobación sencilla.
- Siempre comprueba si hay un sentinela antes de confiar en el resultado.
#include <stdio.h>
int safe_div(int a, int b, int *result) {
if (b == 0) return -1; // failure: cannot divide by zero
*result = a / b; // success: hand back the answer
return 0;
}
int main(void) {
int r;
if (safe_div(10, 2, &r) == 0) {
printf("%d\n", r); // 5
}
return 0;
}
Errores comunes
- Devuelve un código distinto de cero desde
mainpara señalizar un error. - Comprueba el valor de retorno de cualquier función que pueda fallar.
Ahora te toca a ti
- Devuelve
0en caso de éxito y-1en caso de fallo, y escribe la respuesta real a través del puntero de salida. - En caso de fallo, no toques el puntero de salida. No escribas un
main; el verificador proporciona uno.
Complete int safe_div(int a, int b, int *result): if b is 0, return -1 and leave *result alone. Otherwise store a / b in · hacia adentro *result and return 0. Do not · no write a main. · Completa int safe_div(int a, int b, int *result): si b es 0, retorna -1 y deja *result sin cambios. De lo contrario, almacena a / b en *result y retorna 0. No escribas un main.
Click Run to see the output here. · Haz clic en Ejecutar para ver la salida aquí.
Complete int parse_int(const char *s, int *out): if s is a valid integer (digits, with an optional leading -), store its value in *out and return 0; otherwise return -1. Do not · no write a main. · Completa int parse_int(const char *s, int *out): si s es un entero válido (dígitos, con un opcional - inicial), almacena su valor en *out y retorna 0; de lo contrario retorna -1. No escribas un main.
Click Run to see the output here. · Haz clic en Ejecutar para ver la salida aquí.
Complete int withdraw(int balance, int amount, int *new_balance): if amount is more than balance, return -1. Otherwise set *new_balance to · hasta balance - amount and return 0. Do not · no write a main. · Completa int withdraw(int balance, int amount, int *new_balance): si amount es mayor que balance, retorna -1. De lo contrario, establece *new_balance como balance - amount y retorna 0. No escribas un main.
Click Run to see the output here. · Haz clic en Ejecutar para ver la salida aquí.