Разбить массив символов по разделителю, а затем сохранить результат?

Мне нужно иметь возможность анализировать следующие две строки в моей программе:

cat myfile || sort
more myfile || grep DeKalb

Строка сохраняется в буфере символов [1024]. В итоге мне нужно указать указатель на массив символов для левой стороны и указатель на массив символов для правой стороны, чтобы я мог использовать их для вызова следующего для каждой стороны:

int execvp(const char *file, char *const argv[]);

У любого есть идеи, как мне получить правильные аргументы для команды execvp, если две вышеупомянутые строки сохранены в символьном буфере символьный буфер [1024]; ?

Мне нужно, чтобы char * left содержал первое слово левой стороны, затем char * const leftArgv [] для хранения обоих слов слева. Тогда мне нужно то же самое для права. Я уже два часа бездельничаю со strtok, и я бью стену. У кого-нибудь есть идеи?

1

Решение

Я рекомендую вам узнать больше о регулярные выражения. И чтобы решить вашу проблему безболезненно, вы можете использовать библиотека Boost.regex библиотека, которая обеспечивает мощный механизм регулярных выражений. Решением будет всего несколько строк кода, но я призываю вас сделать это самостоятельно — это было бы хорошим упражнением. Если у вас все еще есть проблемы, вернитесь с некоторыми результатами и четко укажите, где вы застряли.

1

Другие решения

Вы можете использовать std :: getline (stream, stringToReadInto, delimeter).

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

StringList Seperate(const std::string &str, char divider, SeperationFlags seperationFlags, CharValidatorFunc whitespaceFunc)
{
return Seperate(str, CV_IS(divider), seperationFlags, whitespaceFunc);
}

StringList Seperate(const std::string &str, CharValidatorFunc isDividerFunc, SeperationFlags seperationFlags, CharValidatorFunc whitespaceFunc)
{
bool keepEmptySegments     = (seperationFlags & String::KeepEmptySegments);
bool keepWhitespacePadding = (seperationFlags & String::KeepWhitespacePadding);

StringList stringList;

size_t startOfSegment = 0;
for(size_t pos = 0; pos < str.size(); pos++)
{
if(isDividerFunc(str[pos]))
{
//Grab the past segment.
std::string segment = str.substr(startOfSegment, (pos - startOfSegment));
if(!keepWhitespacePadding)
{
segment = String::RemovePadding(segment);
}

if(keepEmptySegments || !segment.empty())
{
stringList.push_back(segment);
}

//If we aren't keeping empty segments, speedily check for multiple seperators in a row.
if(!keepEmptySegments)
{
//Keep looping until we don't find a divider.
do
{
//Increment and mark this as the (potential) beginning of a new segment.
startOfSegment = ++pos;

//Check if we've reached the end of the string.
if(pos >= str.size())
{
break;
}
}
while(isDividerFunc(str[pos]));
}
else
{
//Mark the beginning of a new segment.
startOfSegment = (pos + 1);
}
}
}

//The final segment.
std::string lastSegment = str.substr(startOfSegment, (str.size() - startOfSegment));
if(keepEmptySegments || !lastSegment.empty())
{
stringList.push_back(lastSegment);
}

return stringList;
}

Где ‘StringList’ является typedef станд :: вектор, и CharValidatorFunc — указатель на функцию (фактически, std :: function, чтобы разрешить поддержку функтора и лямбды) для функции, принимающей один символ и возвращающей логическое значение. это можно использовать так:

StringList results = String::Seperate(" Meow meow , Green, \t\t\nblue\n   \n, Kitties!", ',' /* delimeter */, DefaultFlags, is_whitespace);

И вернул бы результаты:
{«Мяу мяу», «Зеленый», «синий», «Котята!»}

Сохранение внутреннего пробела «Мяу мяу», но удаление пробелов, вкладок и новых строк, окружающих переменные, и разделение запятыми.

(CV_IS является объектом функтора для сопоставления определенного символа или определенной коллекции символов, взятых как строковый литерал. У меня также есть CV_AND и CV_OR для объединения функций валидатора символов)

Для строкового литерала я бы просто бросил его в std :: string () и затем передал бы его функции, если не требуется экстремальная производительность. Взломать разделители довольно легко, так как эту функцию настраивают в соответствии с типичным использованием и требованиями моих проектов, но вы можете изменить ее и заявить о себе.

1

В случае, если это доставит кому-то еще горе, я решил проблему следующим образом:

//variables for the input and arguments
char *command[2];
char *ptr;
char *LeftArg[3];
char *RightArg[3];

char buf[1024]; //input buffer

//parse left and right of the ||
number = 0;
command[0] = strtok(buf, "||");

//split left and right
while((ptr=strtok(NULL, "||")) != NULL)
{
number++;
command[number]=ptr;
}

//parse the spaces out of the left side
number = 0;
LeftArg[0] = strtok(command[0], " ");

//split the arguments
while((ptr=strtok(NULL, " ")) != NULL)
{
number++;
LeftArg[number]=ptr;
}

//put null at the end of the array
number++;
LeftArg[number] = NULL;

//parse the spaces out of the right side
number = 0;
RightArg[0] = strtok(command[1], " ");

//split the arguments
while((ptr=strtok(NULL, " ")) != NULL)
{
number++;
RightArg[number]=ptr;
}

//put null at the end of the array
number++;
RightArg[number] = NULL;

Теперь вы можете использовать LeftArg и RightArg в команде, после того как вы правильно настроили трубопровод

execvp(LeftArg[0], LeftArg);//execute left side of the command

Затем направьте трубку к правой стороне команды и выполните команду

execvp(RightArg[0], RightArg);//execute right side of command
0
По вопросам рекламы [email protected]