Возвращение информации об ошибке и результата функции

Последнее обновление: 08.09.2023

Если в процессе выполнения функции может произойти некоторая ошибка, то вполне возможно мы захотим возвратить информацию об ошибке вызывающей стороне, чтобы вызывающий код мог узнать, что произошла ошибка, и как-то отреагировать на нее. В качестве решения можно было бы возратить из функции статусный код ошибки. Однако вполне возможно функция уже возвращает некоторый результат. В самом простом случае решение состоит в том, чтобы для статуса ошибки использовать одно из значений возвращаемого типа.

Например, встроенная функция getchar() считывает один символ и возвращает его в виде значения типа int. Если же при считывании произошла ошибка, функция возвращает значение EOF, в качестве которого обычно используется число -1. Это число укладывается в значения типа int и в то же время не пересекается с возвращаемыми числовыми кодами символов.

Рассмотрим простейший пример:

#include <stdio.h>
#include <string.h>
#include <assert.h>

#define USERS_NUMBER 5      // количество объектов в массиве

// структура условной базы данных
typedef struct
{
    char* users[USERS_NUMBER];
} database;


int find(database* db, char*);

int main(void){
    
    // база данных
    database db = {.users = {"Tom", "Sam", "Bob", "Alice", "Kate"}};

    // имя для поиска в базе данных
    char* user = "Alice";
    int index = find(&db, user);
    if(index > -1)
    {
        printf("User index: %d\n", index);
    }
    else
    {
        printf("User not found\n");
    }
}      

// условная функция поиска в базе данных
int find(database* db, char* user)
{
    assert(db!=NULL && "Database is invalid");
    assert(user!=NULL && "User is undefined");

    for(size_t i =0; i < USERS_NUMBER; i++)
    {
        // если нашли имя, возвращаем индекс в массиве
        if(strcmp(db->users[i], user)==0)
        {
            return i;
        }
    }
    return -1;  // если не нашли, возвращаем -1
}

Здесь определена структура database, которая представляет условную базу данных и хранит данные в массиве строк users. Допустим, это будут имена пользователей.

Для поиска в этой базе данных определенного пользователя определена функция find. Она принимает объект базы данных и искомое имя. Функция find проходит по строкам в массиве users и с помощью функции strcmp сравнивает имя user с каждым элементом в массиве users. Если переданный пользователь есть в массиве, то возвращается его индекс. Если указанный пользователь не найден, возвращается -1. Вызывающий код (в примере выше функция main), получив результат функции, может идентицировать, что строка найдена или, наоборот, не найдена в базе данных.

В то же время подобный подход не всегда может использоваться. Например, если функция возвращает температуру в градусах, где валидные значения могут быть как положительными, так и отрицательными, и потенциально могут охватывать весь диапазон значений типа int, то возникнет вопрос, какое именно значение использовать в качестве статуса ошибки.

Если функция возвращает указатель, то здесь все проще - в качестве показателя ошибки или неуспешного выполнения можно возвращать значение NULL. Например:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define USERS_NUMBER 5      // количество объектов в массиве

// структура условной базы данных
typedef struct
{
    char* users[USERS_NUMBER];
} database;


int find(database* db, char*);

database* create_db(char*);

int main(void){
    
    // база данных
    database* db = create_db("Tom");
    if(db == NULL) 
    {
        printf("Unable to create database\n");
        return -1;
    }

    // проверяем инициализацию базы данных
    for(size_t i =0; i < USERS_NUMBER; i++)
    {
        printf("%s\n", db->users[i]);
    }
    // освобождаем память
    free(db);
}      
// создание базы данных, инициализированной значением value
database* create_db(char* value)
{
    database* db = 0;
    // если значение value передано и память выделена
     if(value && (db = malloc(sizeof(database))))
    {
        // инициализация массива users начальным значением value
        for(size_t i =0; i < USERS_NUMBER; i++)
        {
            db->users[i] = value;
        }
    }
    return db;
}

Здесь определена функция create_db, которая создает объект database и возвращает указатель на него. В качестве параметра функция принимает строку value, которой инициализируются все элементы в массиве users в базе данных. Если параметр value равен NULL или не удалось выделить память для структуры database, то возвращается NULL. Иначе возвращается указатель на объект database.

Значение NULL здесь позволяет легко идентифицировать, что произошла ошибка в процессе создания объекта database.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850