C динамически выделяемый указатель на основную функцию

Я не могу понять, как заставить мой указатель argv сохранять свою память, которую я динамически выделяю в другой функции, называемой parseCommand. Мне нужно вызвать parseCommand, выделить необходимую память для проанализированных строк, а затем вернуться в main и распечатать строки, на которые указывает мой указатель. Я бы просто попросил parseCommand вернуть указатель, но мне нужно вернуть количество найденных аргументов. Я действительно не очень много работал с указателями c, поэтому они доставляют мне некоторые проблемы. Итак, как мне сделать так, чтобы мой указатель сохранял свою память между функциями?

Главное:

int main()
{
    char **argv, str[] = "ls -l -s -r -h file";
    int argc;

    argc = parseCommand(str, &argv); 

    int i;
    printf("Arguments in argv: \n");
    for (i = 0; i < argc; i++)       //I want to output the arguments
        printf("%s \n", argv[i]);    //stored in pointer argv

    return 0;
}

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

Команда разбора:

int parseCommand(char *str, char ***args)
{
    int i = -1, prevPos = 0, argc = 0, argl = 0, argCount = 0;
    argCount = getArgCount(str); //Returns 6

    args = malloc(sizeof(char*) * (argCount + 1));                  /*Allocates memory for args in amount of arguments str holds*/
    if (!args){printf("Allocation failed");}                        /*Checks if there was a problem with memory allocation*/

    do
    {
        i++;
        if (str[i] == ' ' || str[i] == '\n' || str[i] == '\0')
        {
            argl = (i + 1) - prevPos;                                /*argl holds the length of the argument*/
            args[argc] = malloc(sizeof(char) * argl);                /*Allocates memory for args in the size of the argument*/
            if (!args[argc]){printf("Allocation failed");}           /*Checks if there was a problem with memory allocation*/

            memcpy(args[argc], str + prevPos, argl);                 /*Copys the argument of the string into args*/
            args[argc][argl - 1] = '\0';                             /*Assigns \0 at the end of the string*/

            argc++;
            prevPos = i + 1;
        }
    } while (str[i] != '\0');

    args[argc] = malloc(sizeof(char));                               /*Allocates one last piece of memory for args*/
    args[argc][0] = (char *)NULL;                                    /*Sets this new piece of memory to NULL*/

    printf("Arguments in args: \n");
    for (i = 0; i < argc; i++)
         printf("%s \n", args[i]);

    return argCount;
}

person brec9824    schedule 29.09.2015    source источник
comment
Вероятно, вы имеете в виду использовать (*args) везде, где вы используете args в parseCommand...   -  person user253751    schedule 29.09.2015
comment
теперь вы стали «трехзвездочным программистом» Google «threestarprogrammer». настоятельно рекомендуем передавать адрес переменной int (argc), а не адрес переменной char** (argv) и возвращать указатель argv, а не указатель argc   -  person user3629249    schedule 30.09.2015
comment
относительно этого блока кода: if (!args){printf("Allocation failed");} Поскольку выделение не удалось, нет абсолютно никаких причин пытаться получить доступ к этому выделению. Если код действительно попытается получить доступ к этому неудачному выделению, он фактически будет обращаться к адресу 0, что при использовании любой ОС приведет к событию сбоя сегмента. т.е. отправьте информацию об ошибке в stderr, затем освободите все предыдущие выделения, затем выйдите   -  person user3629249    schedule 30.09.2015
comment
разбор строки на аргументы для размещенного кода завершится ошибкой, если между аргументами в строке будет более одного пробела.   -  person user3629249    schedule 30.09.2015


Ответы (1)


В parseCommand() args это char ***, но вы обращаетесь с ним как с char **. Вам нужно разыменовать его один раз, чтобы получить char **, который у вас будет в main(). Например, это:

args = malloc(sizeof(char*) * (argCount + 1));

..должно быть:

*args = malloc(sizeof(char*) * (argCount + 1));

И это:

args[argc] = malloc(sizeof(char) * argl);

..должно быть:

(*args)[argc] = malloc(sizeof(char) * argl);

и эти строки:

memcpy(args[argc], str + prevPos, argl);
args[argc][argl - 1] = '\0';

..должно быть:

memcpy((*args)[argc], str + prevPos, argl);
(*args)[argc][argl - 1] = '\0';

и т.п.

args из parseCommand() не указывает на массив char * для строк аргументов — он указывает на argv из main(), а это указывает на массив char * для строк аргументов... поэтому вам нужно разыменуйте args один раз перед его использованием.

person Dmitri    schedule 29.09.2015
comment
Исправил это в моем коде, и теперь он отлично работает. Также спасибо за объяснение, теперь оно имеет больше смысла. - person brec9824; 29.09.2015