Прокомментировать код вычисления факториала - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Здравствуйте, прокомментируйте пожалуйста пример задачи,если можно конечно, я его совсем не поняла( ну и расскажите алгоритм,умоляю)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
 
int fact(int a);
 
int main(int argv, char *args[])
{
    int n = atoi(args[1]);
    int k = atoi(args[2]);
    int nk = n-k;
    
    char* nc = args[1];
    char* kc = args[2];
    char nkc[10];
    sprintf(nkc, "%i", nk);
    
    char temp1[10], temp2[10], temp3[10];
    
    int p1,p2,p3;
    int *st;
        
    int fd1[2], fd2[2], fd3[2];
    
    pipe(fd1);
    pipe(fd2);
    pipe(fd3);
    
    if(p1=fork())
    {
        if(p2=fork())
        {
            if(p3=fork())
            {
 
                read(fd1[0], temp1, 20);
                read(fd2[0], temp2, 20);
                read(fd3[0], temp3, 20);
                
                n = atoi(temp1);
                k = atoi(temp2);
                nk = atoi(temp3);
                
                int ret = n/(k*nk);
                
                printf("%i\n", ret);
                
                return 0;
                                
            }
            else
            {
                dup2(fd3[1], 1);
                close(fd3[1]);
                execl("fact", "", nkc, NULL);
                            
            }
        }
        else
        {   
            dup2(fd2[1], 1);
            close(fd2[1]);
            execl("fact", "", kc, NULL);
            
        }
    }
    else
    {
        dup2(fd1[1], 1);
        close(fd1[1]);
        
        execl("fact", "", nc, NULL);
        
    }
    
    return 0;   
}

Решение задачи: «Прокомментировать код вычисления факториала»

textual
Листинг программы
#include <stdio.h>
#include <stdlib.h>
/* Программа рабоатет только под линукс, об этом говорят эти два хедера */
#include <sys/types.h> 
#include <sys/wait.h>
 
int fact(int a);
 
int main(int argv, char *args[])
{
    /* 
     * args[1] и args[2] - это параметры, которые передаются программе из командной строки 
     * допустим программа называется FACTORIAL. Если в командной строке вызвать программу
     * так - anon@anon:./FACT 3 5, то
     * args[1] будет равнятся 3, args[2] - 0. Нумерация идет с 0 конечно же, но 0 в нашем случае 
     * это само имя программы (FACTORIAL). args[3] - соответственно четвертый параметр.
     */
 
    /* 
     * args[] - это массив строк (вверху в main можно увидеть char *args[]),
     * точнее указатель на массив символов. То есть передавая значения в программу,
     * способом, который я указал выше, мы передаем символы, а не целочисленные
     * значения. Чтобы присвоить эти символы целому числу, мы применяем к параметрам
     * функцию atoi. Она конвертирует строку в число !
     */
    /*
     * Итак, в n у нас первый параметр, в k второй. 
     * Очевидно что nk - это разность передаваемых параметров :)
     */
    int n = atoi(args[1]);
    int k = atoi(args[2]);
    int nk = n-k;
    /*
     * Далее создаются указатели nc,kc на 1 и 2 параметры
     */
    char* nc = args[1];
    char* kc = args[2];
    char nkc[10];
    /* sprintf - это тоже самое что и printf
     * только вывод делается не в консоль, а в строку
     * В данном случае, в строку nkc запишется разность 
     * передаваемых параметров
     */
    sprintf(nkc, "%i", nk);
    /* Судя по названию, временные массивы*/
    char temp1[10], temp2[10], temp3[10];
    
    int p1,p2,p3;
    int *st;
        
    int fd1[2], fd2[2], fd3[2];
    /*
     * pipe - это функция, которая создает pipe :)
     * Pipe - это механизм межпроцессорного взаимодействия (IPC)
     * гуглите и будет вам чудо 
     * в кратце: pipe позволяет обмениваться данными
     * двум запущенным программам,так же как сокеты
     * позволяют общаться двум компьютерам в сети
     * (они тоже относятся к IPC)
     * функция pipe() создает канал для обмена данными.
     * Ниже в коде, ей передается массив из двух элементов
     * в который по окончанию работы функции, будут записаны
     * два файловых дескриптора. Файловый дескриптор - это
     * идентификатор файла в системе линукс, обычное число.
     * В этой программе, пайпы созданы для того, чтобы 
     * ОБМЕНИВАТЬСЯ ДАННЫМИ С ДОЧЕРНИМИ ПРОЦЕССАМИ
     * далее станет ясно
     */
    pipe(fd1);
    pipe(fd2);
    pipe(fd3);
    /*
     * Весь код выше был подготовкой
     * сама логика программы ниже
     */
 
    /*
     * Функция fork() создает дочерний процесс
     * Тут их создается три. То есть наша программа
     * порождает 3 дополнительных процесса, вложенные друг в друга.
     */
    if(p1=fork())
    {
      /* Породили один процесс*/
        if(p2=fork())
        {
         /* Он породил другой процесс*/
            if(p3=fork())
            {
                  /*второй породил третий процесс*/
                /*
                 * Здесь мы окажемся, если 
                 * успешно созданы все три процесса
                 */
                /*
                 * У пайпа есть два конца. fd1[0] и fd[1] например,
                 * первый конец канала (fd1[0]) относится к стороне с который
                 * СЧИТЫВАЮТ ДАННЫЕ, второй конец (fd1[1]) - КУДА ЗАПИСЫВАЮТСЯ
                 * Во временные массивы записываются данные из первых
                 * концов pipe'а. Ровно 20 элементов.
                 */
                read(fd1[0], temp1, 20);
                read(fd2[0], temp2, 20);
                read(fd3[0], temp3, 20);
                /*
                 * temp - это строки, они конвертируются в числа
                 */
                n = atoi(temp1);
                k = atoi(temp2);
                nk = atoi(temp3);
                /*
                 * ret - это походу конечный результат
                 * 
 
                 */
                int ret = n/(k*nk);
                
                printf("%i\n", ret);
                
                return 0;
                                
            }
            /* В else запускается программа fact с разными паарметрами
             */
            else
            {
                dup2(fd3[1], 1);
                close(fd3[1]);
                execl("fact", "", nkc, NULL);
                            
            }
        }
        else
        {   
            dup2(fd2[1], 1);
            close(fd2[1]);
            execl("fact", "", kc, NULL);
            
        }
    }
    else
    {
        dup2(fd1[1], 1);
        close(fd1[1]);
        
        execl("fact", "", nc, NULL);
        
    }
    
    return 0;   
}

Объяснение кода листинга программы

Код выполняет вычисление факториала с помощью рекурсии.

  1. int fact(int a); - объявление функции fact, которая вычисляет факториал числа a.
  2. int main(int argv, char *args[]) - объявление функции main, которая является точкой входа в программу.
  3. args[1] и args[2] - это параметры, передаваемые программе из командной строки.
  4. int n = atoi(args[1]); и int k = atoi(args[2]); - присваивание значения первого и второго параметров функции main переменным n и k соответственно.
  5. int nk = n-k; - вычисление разности между n и k и присвоение результата переменной nk.
  6. char* nc = args[1]; и char* kc = args[2]; - присваивание адреса первого и второго параметров функции main переменным nc и kc соответственно.
  7. char nkc[10]; - объявление временного массива строкового типа nkc размером 10 символов.
  8. sprintf(nkc,%i, nk); - использование функции sprintf для записи разности n и k в переменную nkc в виде строки.
  9. int p1,p2,p3; - объявление переменных p1, p2 и p3 для хранения результатов fork.
  10. int *st; - объявление указателя st на целочисленный массив.
  11. pipe(fd1); - создание pipe с помощью функции pipe и сохранение его в переменной fd1.
  12. pipe(fd2); - создание pipe с помощью функции pipe и сохранение его в переменной fd2.
  13. pipe(fd3); - создание pipe с помощью функции pipe и сохранение его в переменной fd3.
  14. if(p1=fork()) - вызов функции fork для создания дочернего процесса. Если p1 не равно нулю, это означает, что родительский процесс.
  15. if(p2=fork()) - вызов функции fork для создания дочернего процесса. Если p2 не равно нулю, это означает, что родительский процесс.
  16. if(p3=fork()) - вызов функции fork для создания дочернего процесса. Если p3 не равно нулю, это означает, что родительский процесс.
  17. read(fd1[0], temp1, 20); - чтение данных из первого конца pipe, сохраненного в fd1[0], во временный массив temp1.
  18. read(fd2[0], temp2, 20); - чтение данных из первого конца pipe, сохраненного в fd2[0], во временный массив temp2.
  19. read(fd3[0], temp3, 20); - чтение данных из первого конца pipe, сохраненного в fd3[0], во временный массив temp3.
  20. n = atoi(temp1); - конвертация временного массива temp1 в целое число и присвоение результата переменной n.
  21. k = atoi(temp2); - конвертация временного массива temp2 в целое число и присвоение результата переменной k.
  22. nk = atoi(temp3); - конвертация временного массива temp3 в целое число и присвоение результата переменной nk.
  23. int ret = n/(k*nk); - вычисление результата и присвоение его переменной ret.
  24. printf(%i\n, ret); - вывод результата на консоль.
  25. return 0; - возврат нуля, указывающего на успешное выполнение программы.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

5   голосов , оценка 3.8 из 5