Error Handling Techniques
Introduction to Error Handling
Error handling is a critical aspect of robust C programming, especially when dealing with input operations. Proper error management prevents program crashes and provides meaningful feedback.
Error Handling Strategies
Error Detection Methods
graph TD
A[Input Received] --> B{Error Detection}
B -->|Type Check| C{Validate Input Type}
B -->|Range Check| D{Check Value Range}
B -->|Boundary Check| E{Buffer Overflow Prevention}
C -->|Invalid| F[Handle Error]
D -->|Out of Range| F
E -->|Overflow Detected| F
Common Error Types
Error Type |
Description |
Handling Strategy |
Input Type Mismatch |
Incorrect input type |
Reject and request retry |
Buffer Overflow |
Exceeding buffer capacity |
Truncate or reject input |
Conversion Errors |
Failed numeric conversion |
Provide clear error message |
Comprehensive Error Handling Example
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
typedef enum {
INPUT_SUCCESS,
INPUT_ERROR_EMPTY,
INPUT_ERROR_CONVERSION,
INPUT_ERROR_RANGE
} InputResult;
InputResult safe_integer_input(const char* input, int* result) {
// Check for empty input
if (input == NULL || *input == '\0') {
return INPUT_ERROR_EMPTY;
}
// Reset errno before conversion
errno = 0;
// Use strtol for robust conversion
char* endptr;
long long_value = strtol(input, &endptr, 10);
// Check for conversion errors
if (endptr == input) {
return INPUT_ERROR_CONVERSION;
}
// Check for trailing characters
if (*endptr != '\0') {
return INPUT_ERROR_CONVERSION;
}
// Check for overflow/underflow
if ((long_value == LONG_MIN || long_value == LONG_MAX) && errno == ERANGE) {
return INPUT_ERROR_RANGE;
}
// Check if value is within int range
if (long_value < INT_MIN || long_value > INT_MAX) {
return INPUT_ERROR_RANGE;
}
// Store result
*result = (int)long_value;
return INPUT_SUCCESS;
}
void print_error_message(InputResult result) {
switch(result) {
case INPUT_ERROR_EMPTY:
fprintf(stderr, "Error: Empty input\n");
break;
case INPUT_ERROR_CONVERSION:
fprintf(stderr, "Error: Invalid number format\n");
break;
case INPUT_ERROR_RANGE:
fprintf(stderr, "Error: Number out of valid range\n");
break;
default:
break;
}
}
int main() {
char input[100];
int result;
printf("Enter an integer: ");
if (fgets(input, sizeof(input), stdin) == NULL) {
fprintf(stderr, "Input reading failed\n");
return EXIT_FAILURE;
}
// Remove newline
input[strcspn(input, "\n")] = 0;
// Attempt to convert input
InputResult conversion_result = safe_integer_input(input, &result);
// Handle potential errors
if (conversion_result != INPUT_SUCCESS) {
print_error_message(conversion_result);
return EXIT_FAILURE;
}
printf("Valid input: %d\n", result);
return EXIT_SUCCESS;
}
Advanced Error Handling Techniques
Error Logging
void log_input_error(const char* input, InputResult error) {
FILE* log_file = fopen("input_errors.log", "a");
if (log_file != NULL) {
fprintf(log_file, "Input: %s, Error Code: %d\n", input, error);
fclose(log_file);
}
}
Best Practices for LabEx Learners
- Always validate inputs before processing
- Use descriptive error messages
- Implement comprehensive error checking
- Log errors for debugging
- Provide user-friendly error feedback
Error Handling Flow
graph LR
A[Input Received] --> B{Validate Input}
B -->|Valid| C[Process Input]
B -->|Invalid| D[Handle Error]
D --> E[Log Error]
D --> F[Notify User]
D --> G[Request Retry]
Conclusion
Effective error handling transforms potential program failures into manageable, predictable outcomes, enhancing overall software reliability and user experience.