Создание arglist для программы Unix - PullRequest
1 голос
/ 26 октября 2011

Чтобы выполнить программу несколько раз на основе пользовательского ввода, мне нужно изменить массив arglist, отправляемый в функцию выполнения.По большей части у меня это работает, за исключением установки конечного флага, чтобы указать, какую функцию разделения использовать из коэффициента получения информации, первого индекса и коэффициента Джини

Эта программа имеет три различные функции разделения для создания дерева решенийна основе набора данных для обучения и тестирования.Я настроил arglist для имитации традиционного ввода CLI, поэтому это допустимые входные данные:

./decision voting 5

./decision -train voting-train-1 -test voting-test-1 -out voting.out -[i, s, g]

То, что делает первая команда, выполняет все трифункции разделения для всех голосующих файлов - - от 1 до 5, тогда как вторая делает это с единичным набором данных.

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

//flag pointers
char *igFlag= "-i";
char *faFlag= "-s";
char *giFlag= "-g";

//copy temp array to specific arglist
igInput= cli;
faInput= cli;
giInput= cli;

//set information gain flag and null
igInput[7]= igFlag;
igInput[8]= '\0';

//set first attribute flag and null
faInput[7]= faFlag;
faInput[8]= '\0';

//set gini coefficient and null
giInput[7]= giFlag;
giInput[8]= '\0';   

Проблема здесь в том, что когда faInput[7]= faFlag выполняется, он меняет igInput[7] на соответствие, а затем, когда giInput[7]= giFlagвыполняется, все три массива имеют совпадающие указатели [7].

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

решено

В ответ на запрос AusCBloke, чтобы узнать, как я решил эту проблему, вот так.

Во-первых, я решил, что мне не нужно несколько входных строк, только та, где должен быть изменен последний слот.Поэтому я вырезал две строки xxInput и использовал только одну.

В итоге мне понадобилось больше флагов в конце, и вместо того, чтобы получить дублирующийся код, я создал char flag[5], содержащий флаги, которые должны бытьиспользуемый.Затем они были вызваны из цикла for, где используемым флагом было текущее значение индекса.

В целом, этот подход закончил тем, что удалил около 30 строк ненужного кода.

Ответы [ 3 ]

3 голосов
/ 26 октября 2011

Проблема в том, что когда faInput[7]= faFlag выполняется, он меняется igInput[7] для сопоставления, а затем при выполнении giInput[7]= giFlag, все три массива имеют соответствующие [7] указатели.

//copy temp array to specific arglist
igInput= cli;
faInput= cli;
giInput= cli;

Вы не копируете cli, каждый из этих параметров char * указывает на cli. Поэтому igInput[7] == faInput[7] == giInput[7] == cli[7]

Выделите в них память для ig/fa/gaInput и memcpy cli, если вы не воспользуетесь предложением Мегар о getopt.

РЕДАКТИРОВАТЬ: Ой, подождите, вы пытаетесь передать эти аргументы чему-то другому, а не читать их? И является ли cli чем-то вроде argv? Если это действительно так и cli является char ** тогда вы можете просто сохранить его так, как он есть, то есть:

cli[8] = NULL;

cli[7] = igFlag;
execv(cli[0], cli);

cli[7] = faFlag;
execv(cli[0], cli);

cli[7] = giFlag;
execv(cli[0], cli);
2 голосов
/ 26 октября 2011

Ты превращаешь что-то тривиальное в кошмар.Насколько я понимаю, вы хотите выполнить команду 3 раза, с -i, -s или -g в зависимости от итерации.Так что сделайте это:

char opt[] = "-i", *cmd[] = {
    "decision", "-train", "voting-train-1", "-test", "voting-test-1",
    "-out", "voting.out", opt, 0
};
/* use first command line */
opt[1] = 's';
/* use second command line */
ops[1] = 'g';
/* use third command line */
2 голосов
/ 26 октября 2011

Ваш код не копирует массив cli в различные входные переменные. Он устанавливает все три входных указателя для указания на массив cli. Поскольку igInput, faInput и giInput все указывают на одно и то же место, изменение faInput[7], по-видимому, также изменяет giInput[7], поскольку они оба указывают на одни и те же базовые данные. Вам нужно использовать memcpy для копирования данных массива. Но вы действительно должны использовать getopt для обработки ваших аргументов, как подсказывает @meagar.

//copy temp array to specific arglist
igInput= cli;
faInput= cli;
giInput= cli;
...