Динамическое добавление элементов в массив C - PullRequest
0 голосов
/ 26 февраля 2020

Я пытаюсь создать функцию, которая принимает строку символов и предоставляет список этих символов, разделенных токеном.

Это то, что у меня есть:

char * decode_args(char arguments[]){
  char* token = strtok(arguments, "00");
  while (token != NULL){
    printf("%s\n", token);
    token = strtok(NULL, "00");
  }
  return 0;
}

Эта функция печатает нужные значения, которые я ищу. Например:

>decode_args("77900289008764")
779
289
8764

Следующим шагом является создание массива, который можно использовать в команде execv. Аргументы должны быть массивом. Пример здесь . Я новичок, поэтому я даже не знаю, правильное ли слово «массив». Какой тип данных должен быть построен и как я могу это сделать, чтобы я мог вызвать execv с аргументами, которые в данный момент выводятся в списке?

Ответы [ 2 ]

3 голосов
/ 26 февраля 2020

Для начала позвольте мне рассказать кое-что о хранилище и строках.

Существует 3 основных c типа хранения. Автомат c, динами c, стат c. И stati c один обычно делится на две части: только чтение и чтение-запись. Скоро вам пригодятся динамические c и stati c.

Automati c переменные - это параметры функции и локальные переменные. Когда вы вызываете функцию, они помещаются в стек, а когда функция возвращается, они раскручиваются.

Dynami c Один - это тот, который вы выделяете во время выполнения с семейством malloc. Вот как мы создаем динамический массив c. И вам нужно вернуть этот источник, когда вы закончите с free. Если вы этого не сделаете, это называется утечкой памяти, и вы можете проверить утечки памяти с помощью инструмента valgrind рядом с другими ошибками памяти. Это довольно полезно для системного программирования класса.

И stati c - это те, которые остаются там на всю жизнь программы. Если вы определите глобальную переменную или static int i = 42, она создаст переменную чтения-записи stati c, чтобы вы могли ее изменить. Теперь вот трюк.

void foo() {
   char *string1 = "hello, world" //static read-only
   char string2[] = "hello, world" //automatic
}

Так что, если вы попытаетесь изменить string1, вы получите ошибку сегментации, но все равно можно изменить string2. Я не знаю, почему вы не получаете ошибку сегментации при выполнении decode_args("77900289008764"), но я вхожу в мою машину. : D

Теперь C -строки. Они заканчиваются нулем, что означает, что в каждой строке есть символьный конец (char) 0, который говорит, что это конец строки. strtok в основном заменяет шаблон на символ NULL, поэтому вместо одной вы получаете несколько подстрок. Таким образом, из вашего примера он преобразует "77900289008764 NULL" в "779 NULL 289 NULL 8764 NULL"

Так что на вашем месте я бы посчитал число "00" в строке и выделил бы столько символьного указателя. Что-то вроде:

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

char ** decode_args(char *arguments, char *delim) {
    int num_substrings = 1; // Note that C don't initialize with 0 like java etc.
    int len_delim = strlen(delim);

    for (int i = 0;
            arguments[i] != '\0' && arguments[i + 1] != '\0'; // Any of last 2 chars are terminator?
            ++i)
        if (strncmp(arguments + i /* same as &arguments[i] */, delim, len_delim) == 0)
            ++num_substrings;

    char **result = (char **) malloc(sizeof(char *) * (num_substrings + 1));
    int i = 0;
    char* token = strtok(arguments, delim);

    while (token != NULL){
        result[i] = token;
        ++i;
        token = strtok(NULL, delim);
    }

    result[i] = NULL; //End of results. execv wants this as I remember

    return result;
}
int main(int argc, char *argv[])
{
    char str[] = "foo00bar00baz";
    char **results = decode_args(str, "00");

    for (int i = 0; results[i] != NULL; ++i) {
        char *result = results[i];
        puts(result);
    }

    free(results);

    return 0;
}
0 голосов
/ 26 февраля 2020

Попробуйте что-то вроде этого:

#define MAX_ARGUMENTS 10

int decode_args(char arguments[], char ** pcListeArgs)
{
    int iNumElet = 0;
    char* token = strtok(arguments, "00");

    while ((token != NULL) && (iNumElet < MAX_ARGUMENTS -1)) 
    {
        size_t len = strlen(token);

        pcListeArgs [iNumElet] = (char*) calloc (len+1, sizeof (char));
        memset(pcListeArgs [iNumElet], 0, len+1); // reset content
        memcpy(pcListeArgs [iNumElet], token, len); // copy data

        token = strtok(NULL, "00");
        iNumElet++;
    }

    if ( iNumElet >= MAX_ARGUMENTS)
        return -1;

    return iNumElet;
}

И в основном:

int main() {

    char *pListArgs[MAX_ARGUMENTS];

    char args[] = "77900289008764";

    int iNbArgs = decode_args (args, pListArgs);

    if ( iNbArgs > 0)
    {
        for ( int i=0; i<iNbArgs; i++)
            printf ("Argument number %d = %s\n", i, pListArgs[i]);

        for ( int i=0; i<iNbArgs; i++)
            free (pListArgs[i]);
    }

    return 0;
}

Вывод:

enter image description here

...