char line[255];
char *token = NULL;
char *line2 = NULL;
char *temporaryToken = NULL;
if( scanf(" %[^\n]", line) > 0)
token = strtok( line, ";" ); //divide the line by ;
do
{
line2 = token;
temporaryToken = strtok(line2, " ");
do
{
//divide the line2 by spaces into command and args, not the question here]
temporaryToken = strtok( NULL, " " );
}while (temporaryToken != NULL );
token = strtok( NULL, ";" );
}while(token != NULL);
顺便说一下,这不是我的代码,只是一个如何设置的例子
在我的程序中,当我在第二次分割之前打印“令牌”变量时,它会打印出所有内容,直到;字符。
例如,假设stdIn接受了“ls -la; mkdir lololol; ls -la”,它将打印“ls -la”。但是,在第二次拆分后,打印“令牌”只会打印“ls”。
为什么会这样,我该怎么办呢?
答案 0 :(得分:4)
strtok
修改原始字符串。如果你想混合这样的电话,你需要复制或使用strtok_r
。
答案 1 :(得分:1)
strtok()
存在两个问题。
strtok()
次来电。我认为你的问题是后者。您在代码中也有缩进问题:
if (scanf(" %[^\n]", line) > 0)
token = strtok( line, ";" );
do
{
line2 = token;
temporaryToken = strtok(line2, " ");
do
{
//divide the line2 by spaces into command and args, not the question here]
temporaryToken = strtok(NULL, " ");
} while (temporaryToken != NULL);
token = strtok( NULL, ";" );
} while(token != NULL);
您可能打算阅读:
if (scanf(" %[^\n]", line) > 0)
{
token = strtok(line, ";");
do
{
line2 = token;
temporaryToken = strtok(line2, " ");
do
{
//divide the line2 by spaces into command and args, not the question here]
temporaryToken = strtok(NULL, " ");
} while (temporaryToken != NULL);
token = strtok(NULL, ";");
} while (token != NULL);
}
假设这是您的意图,您仍然遇到strtok()
上运行一个line
,然后line2
上运行第二个line2
的问题。麻烦的是,line
上的循环完全破坏了strtok()
的解释。您不能将嵌套循环与strtok_s()
一起使用。
如果您必须使用strtok()
之类的内容,请查找POSIX strtok_r()
或Microsoft strtok_s()
(但请注意,if (scanf(" %[^\n]", line) > 0)
{
char *end1;
token = strtok_r(line, ";", &end1);
do
{
char *end2;
line2 = token;
temporaryToken = strtok_r(line2, " ", &end2);
do
{
//divide the line2 by spaces into command and args, not the question here]
temporaryToken = strtok_r(NULL, " ", &end2);
} while (temporaryToken != NULL);
token = strtok_r(NULL, ";", &end1);
} while (token != NULL);
}
的C11标准附件K版本不同 - 见Do you use the TR 24731 'safe' functions?)。
strtok()
当您使用strtok_r()
或其中一个亲戚时,输入字符串将被修改,如果您有多个分隔符,您将无法分辨出哪个分隔符。您可以使用字符串的副本,并进行比较(通常基于字符串开头的偏移量)。
在使用#include <stdio.h>
#include <string.h>
int main(void)
{
char line[1024];
if (scanf(" %[^\n]", line) > 0)
{
char *end1;
char *token;
printf("Input: <<%s>>\n", line);
token = strtok_r(line, ";", &end1);
do
{
char *end2;
char *line2 = token;
char *temporaryToken;
printf("Token1: <<%s>>\n", token);
temporaryToken = strtok_r(line2, " ", &end2);
do
{
printf("Token2: <<%s>>\n", temporaryToken);
//divide the line2 by spaces into command and args, not the question here]
temporaryToken = strtok_r(NULL, " ", &end2);
} while (temporaryToken != NULL);
token = strtok_r(NULL, ";", &end1);
} while (token != NULL);
}
return 0;
}
的限制范围内,上述解决方案“有效”。这是一个测试程序,用于演示:
$ ./strtok-demo
ls -la; mkdir lololol; ls -la
Input: <<ls -la; mkdir lololol; ls -la>>
Token1: <<ls -la>>
Token2: <<ls>>
Token2: <<-la>>
Token1: << mkdir lololol>>
Token2: <<mkdir>>
Token2: <<lololol>>
Token1: << ls -la>>
Token2: <<ls>>
Token2: <<-la>>
$
输入和输出示例:
strcspn()
strspn()
和strtok()
如果您不想拆除原始字符串,则必须使用除strcspn()
系列之外的其他功能。函数strspn()
和#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char *substrdup(const char *src, size_t len);
int main(void)
{
char line[1024];
if (scanf(" %[^\n]", line) > 0)
{
char *start1 = line;
size_t len1;
printf("Input: <<%s>>\n", line);
while ((len1 = strcspn(start1, ";")) != 0)
{
char *copy = substrdup(start1, len1);
char *start2 = copy;
size_t len2;
printf("Token1: %zd <<%.*s>>\n", len1, (int)len1, start1);
printf("Copy: <<%s>>\n", copy);
start2 += strspn(start2, " "); // Skip leading white space
while ((len2 = strcspn(start2, " ")) != 0)
{
printf("Token2: %zd <<%.*s>>\n", len2, (int)len2, start2);
start2 += len2;
start2 += strspn(start2, " ");
}
free(copy);
start1 += len1;
start1 += strspn(start1, ";");
}
printf("Check: <<%s>>\n", line);
}
return 0;
}
#include <assert.h>
static char *substrdup(const char *src, size_t len)
{
char *copy = malloc(len+1);
assert(copy != 0); // Apalling error handling strategy
memmove(copy, src, len);
copy[len] = '\0';
return(copy);
}
是合适的;它们是标准C(C89及更高版本)的一部分,虽然比其他一些功能知名度低得多。但是他们已经完成了这项任务。
$ strcspn-demo
ls -la; mkdir lololol; ls -la
Input: <<ls -la; mkdir lololol; ls -la>>
Token1: 140734970342872 <<>>
Copy: <<ls -la>>
Token2: 2 <<ls>>
Token2: 3 <<-la>>
Copy: << mkdir lololol>>
Token2: 5 <<mkdir>>
Token2: 7 <<lololol>>
Copy: << ls -la>>
Token2: 2 <<ls>>
Token2: 3 <<-la>>
Check: <<ls -la; mkdir lololol; ls -la>>
$
输入和输出示例:
while
此代码返回更舒适的do-while
循环,而不是需要使用{{1}}循环,这是一个好处。