Для начала позвольте мне рассказать кое-что о хранилище и строках.
Существует 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;
}