Написание простой функции puts()

/* original function prototype */
int puts(const char *s);

Функция puts() позволяет записывать строку (строки) в стандартный вывод (stdout). Эта функция проще, чем функция printf(), поскольку она не учитывает другие данные. сложности. Это только для печати строк.

Когда вы пишете свою собственную функцию, вы укрепляете свое понимание концепций программирования.

Для этой задачи нам понадобится библиотека C с именем unistd.h. В этой библиотеке есть функция, которая нам понадобится для записивывода в любой поток ввода-вывода, который мы предпочитаем. Раз уж мы упомянули поток ввода-вывода, давайте кратко объясним, что это такое. Поток ввода-вывода — это просто абстракция, позволяющая манипулировать операциями ввода и вывода с последовательностью символов, например со строкой или файлом. Нас интересуют три потока: stdin, stdout и stderr. Давайте разберем их.

стандартный ввод (stdin) — это поток, который позволяет передавать на компьютер информацию; наиболее заметные операции – ввод с клавиатуры или чтение из файла. Он имеет уникальный номер, называемый номером файлового дескриптора (FDN). Номер дескриптора файла для стандартного ввода равен нулю (0).

Стандартный вывод (stdout) — это поток, который позволяет отправлять результаты на экран компьютера или даже в файл. Думайте об этом как о своем источнике вывода. Номер его файлового дескриптора равен 1.

Наконец, стандартная ошибка (stderr) — это место, куда отправляются все, как вы уже догадались, ошибки. Обычно вы видите ошибки на том же экране, что и ваш обычный вывод, но они используют разные потоки. Номер дескриптора файла stderr равен 2.

Теперь, когда мы понимаем, что такое потоки ввода-вывода, давайте перейдем к объяснению процесса написания нашей пользовательской функции puts()function. Помните, мы пытаемся что-то показать пользователю, поэтому у нас есть два варианта. Либо отправьте его в stdout, либо в stderr, здесь мы рассмотрим оба варианта. Мы вызовем функцию, которая записывает в стандартный вывод echo() и echo_err() для той, которая записывает в стандартный вывод. Он примет строку в качестве аргумента и выведет ее в поток ввода-вывода в зависимости от того, какая функция вызывается.

Как говорилось ранее, нам нужна определенная функция в библиотеке unistd.hlibrary. Эта функция удачно названа просто write(). Ему требуются три аргумента: дескриптор файла, указатель на буфер и общее количество записываемых байтов. У нас уже есть правильные номера файловых дескрипторов, и буфер будет содержать строку, которую мы хотим напечатать. Общее количество байтов будет соответствовать количеству символов в строке, которую мы печатаем. Для этого мы будем использовать специальную функцию с именем _len(), чтобы получить длину строки.

Наши прототипы функций будут следующими:

#include <unistd.>

/* our prototypes */
int echo(const char *s); /* to standard out */
int echo_err(const char *s); /* to standard error */
int _len(const char *s); /* get length of string */

/* the write function's prototype */
ssize_t write(int fd, const void *buf, size_t count);

Реализация echo() функции

/* filename: echo.c */

#include <unistd.h>
#include "main.h"

/**
 * echo - write string to stdout
 * @s: string
 * Return: number of characters printed
 */
int echo(const char *s)
{
    int i = _len(s);

    write(1, s, i);
    write(1, "\n", 1);
    
    return (i);
}

Реализация echo_err() функции

/* filename: echo_err.c */

#include <unistd.h>
#include "main.h"

/**
 * echo_err - write string to stderr
 * @s: string
 * Return: number of characters printed
 */
int echo(const char *s)
{
    int i = _len(s);

    write(2, s, i);
    write(2, "\n", 1);
    
    return (i);
}

Реализация функции _len()

/* filename: _len.c */

/**
 * _len - get length of string
 * @s: string
 * Return: string length
 */
int _len(const char *s)
{
    int i = 0;
    for (; *s; s++, i++)
        ;
    return (i);
}

Код драйвера для проверки нашего кода

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

/* filename: main.c */

#include "main.h" /* our function prototypes file */

/**
 * main - driver code to test functions
 * Return: 0
 */
int main(void)
{
    echo("Hello, world!");
    echo_err("Oops, an error!");

    return (0);
}

Теперь, когда все готово, мы можем скомпилировать и запустить наш код. Хотя метод компиляции может отличаться, я использовал Makefile (номер 2).

Вывод, показанный на изображении выше, показывает, что функция работает правильно при первоначальном выполнении (номер 3). Ожидаемые результаты выводятся на экран, и хотя может показаться, что использовался только стандартный вывод, на самом деле функция использовала разные потоки ввода-вывода. При перенаправлении стандартного вывода (номер 4) появляется текст «К сожалению, ошибка!» отображается. Этот текст был включен в вызов echo_err()функции. С другой стороны, когда stderr перенаправляется (номер 5), отображается текст «Hello, World», который был текстом, заданным при вызове функции echo(). Цифры 6 и 7 показывают содержимое после перенаправления.

Надеюсь, это помогло вам понять некоторые концепции и то, как их можно объединить. Исходный код доступен в моей учетной записи GitHub. Доступ к нему по этой ссылке.