Объясните код в C

53
9

Я хочу понять этот код специально parse_args. Этот код является простой оболочкой для запуска базовой команды linux в качестве pwd cat и так далее. Я хочу понять, как работает parse_args.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#define BUFFER_SIZE 1<<16
#define ARR_SIZE 1<<16

void parse_args(char *buffer, char** args,
size_t args_size, size_t *nargs)
{
char *buf_args[args_size]; /* You need C99 */
char **cp;
char *wbuf;
size_t i, j;

wbuf=buffer;
buf_args[0]=buffer;
args[0] =buffer;

for(cp=buf_args; (*cp=strsep(&wbuf, " \n\t")) != NULL ;){
if ((*cp != '\0') && (++cp >= &buf_args[args_size]))
break;
}

for (j=i=0; buf_args[i]!=NULL; i++){
if(strlen(buf_args[i])>0)
args[j++]=buf_args[i];
}

*nargs=j;
args[j]=NULL;
}

int main(int argc, char *argv[], char *envp[]){
char buffer[BUFFER_SIZE];
char *args[ARR_SIZE];

int *ret_status;
size_t nargs;
pid_t pid;

while(1){
printf("$ ");
fgets(buffer, BUFFER_SIZE, stdin);
parse_args(buffer, args, ARR_SIZE, &nargs);

if (nargs==0) continue;
if (!strcmp(args[0], "exit" )) exit(0);
pid = fork();
if (pid){
printf("Waiting for child (%d)\n", pid);
pid = wait(ret_status);
printf("Child (%d) finished\n", pid);
} else {
if( execvp(args[0], args)) {
puts(strerror(errno));
exit(127);
}
}
}
return 0;
}

спросил(а) 2020-03-25T20:05:42+03:00 1 неделя, 4 дня назад
1
Решение
82

Это весело. Функция разделяет буфер на массив строк, где он попадает в разделитель белого пробела.

void parse_args(char *buffer, char** args, 
size_t args_size, size_t *nargs)
{
char *buf_args[args_size]; /* You need C99 */
char **cp;
char *wbuf;
size_t i, j;

Код инициализации...

    wbuf=buffer;
buf_args[0]=buffer;
args[0] =buffer;

Установите все указатели на начало буфера

    for(cp=buf_args; (*cp=strsep(&wbuf, " \n\t")) != NULL ;){

Установите указатель записи cp чтобы указать на первый элемент в массиве buf_args.

Установите * cp в следующий экземпляр маркера не-whitespace в буфере и wbuf в его конечную позицию

    if ((*cp != '\0') && (++cp >= &buf_args[args_size]))
break;

Остановитесь, когда strsep вернул NULL или когда он указывает на конец буфера или когда он указывает за конец buf_args []

    }

for (j=i=0; buf_args[i]!=NULL; i++){
if(strlen(buf_args[i])>0)
args[j++]=buf_args[i];
}

Этот цикл создает сжатую копию массива buf_args []: он копирует только аргументы, которые не являются пустыми. Я предполагаю, что это может произойти, если в исходном буфере есть серия последовательных символов пробела.

    *nargs=j;
args[j]=NULL;
}

Поместите NULL в конец выходного массива и задайте выходной аргумент nargs.

ответил(а) 2020-03-25T20:21:07.852011+03:00 1 неделя, 4 дня назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема