#c
#c
Вопрос:
Я только начал изучать язык C на Ubuntu, я пытался создать простую оболочку, которая работает немного как оболочка. Итак, сразу после того, как я получу командную строку, я думаю, мне, возможно, придется разделить строку разделителем. во-первых, я хочу токенизировать строку с помощью разделителя ‘amp;’, содержащего разделитель, используя «strtok_r ()», но «strcat ()» почему-то не работает с тем, что я хотел
я попытался использовать «strcat ()» после создания токенов. если я использую функцию, вывод первого токена хорошо работает со вторыми токенами, однако они выбрасываются.
вывод просто такой. допустим, у меня есть эти токены.
token1 : abcde
token2 : fghij
и затем, если я использую «strcat (‘amp;’)» с этим, его вывод выглядит так
token1 : abcdeamp;
token2 : amp;
я думаю, это может быть связано с тем, что разделитель, который я пытаюсь поместить в конце «token1», влияет на адрес для «token2».
#include <stdio.h>
#include <string.h>
int main()
{
static const char delim[] = "amp;";
char str[256] = "sleep 5 amp; echo Hello amp; sleep 5; echo Hello";
char *args[50];
char *save;
char *pBuf;
int i = 0;
for(pBuf = strtok_r(str, delim, amp;save);
pBuf;
pBuf = strtok_r(NULL, delim, amp;save)){
printf("%dn", i);
args[i ] = pBuf;
}
/** OUT PUT START*/
i = 0;
while(args[i]){
printf("args[%d] : %sn", i , args[i]);
i ;
}
/**OUT PUT END */
return 0;
}
********OUT PUT
args[0] : sleep 5
args[1] : echo Hello
args[2] : sleep 5; echo Hello
********EXPECTED OUT PUT
args[0] : sleep 5 amp;
args[1] : echo Hello amp;
args[2] : sleep 5; echo Hello
Комментарии:
1. Вы должны внимательно изучить руководства. strtok_r заменяет разделитель нулевым байтом завершения. Он не «удаляет начальные пробелы» или «возвращает копии строки». Он работает с
str
памятью, никакая другая память не используется. Для ввода строки нет памятиamp;
. Вам нужно выделить память для ваших нужд, вручную удалить начальные пробелы, добавить разделитель в конец и не забыть освободить выделенную память.2. Также
char *args[50];
не инициализируется, поэтому он имеет «неопределенные» значения, а не NULL. Ваша часть «OUT PUT» имеет неопределенное поведение —while(args[i])
может быть true,args[i]
будучи недопустимым указателем.3. Вы имеете в виду, что если char *pBuf имеет значение Null в первый раз, аргументы [i] могут не инициализироваться?
4. Будет ли он инициализирован, если это будет второй раз? В третий раз? Этого не будет. Будут инициализированы только первые n значений. Например, в вашем коде ошибка seg здесь , потому
args[i]
что он не инициализирован. Инициализируйте его — добавьтеchar *args[50] = {0};
Ответ №1:
Вопрос в том, что хорошего strtok
в этом случае. Вместо того, чтобы усложнять вещи, вы можете просто выполнить синтаксический анализ вручную strchr
. Как только вы найдете разделитель amp;
, вы можете ожидать, что в конце будет пробел, и напечатать этот пробел и конец, а не начало. Пример:
#include <string.h>
#include <stdio.h>
int main(void)
{
const char str[256] = "sleep 5 amp; echo Hello amp; sleep 5; echo Hello";
size_t length = strlen(str);
const char* s1 = str;
const char* s2;
const char delim = 'amp;';
while(s1 < str length)
{
s2 = strchr(s1, delim);
if(s2 == NULL)
{
s2 = amp;str[length]; // point at null term
}
else
{
s2 ; // point at space
}
printf("%.*sn", s2-s1, s1); // print (s2-s1) characters
s1 = s2 1; // point at next char after space, or 1 past null term
}
}
Вывод:
sleep 5 amp;
echo Hello amp;
sleep 5; echo Hello
(Обратите внимание, что в C нормально указывать 1 элемент после конца массива, но не отменять ссылку на этот адрес.)