你好,我在 C 中遇到了一个复杂的问题。我想拆分这个字符串(在这个例子中,我包含了所有可能的陷阱)
"command1";"sleep 30; command2 -a ; command3";"command4="MyTest""
到:
command1
sleep 30; command2 -a ; command3
command4="MyTest"
字符串为“制表符”,元素之间用双引号和分隔;
我如何为此使用 strtok()
?
我尝试将 strtok()
与“;”一起使用像这样的分隔符:
char mystring[1024]="\"command1\";\"sleep 30; command2 -a ; command3\";\"command4=\"MyTest\"\"";
token = strtok(mystring, "\";\"");
while( token != NULL ) {
error(token);
token = strtok(NULL, s);
}
但我有这个输出:
command1
"sleep 30
command2 -a
command3"
"command4="MyTest""
感谢您的帮助
最佳答案
下面的示例按要求解析输入字符串。它需要进行一些调整才能完全满足您的需求(将 printf
替换为您的实际处理代码)。
要理解代码,请从描述字符串语法的顶部注释开始。然后转到 main
- 使用调试器。
一些解释:
iss_t
是一个输入字符串流模拟。iss_get_char
使用它从输入字符串中读取字符。wschar_t
用于存储从输入流中读取的字符以及之前的空格。这是必需的,因为您没有指定"
和;
之间是否有空格。它由iss_get_wschar
和iss_peek_wschar< 使用
。iss_get_wschar
读取空格,直到找到非 ws 字符。iss_peek_wschar
除了不从流中提取字符外,与上面相同。token_t
描述构成流的标记。parser_get_token
从流中提取一个标记。这可能是最重要的功能。parser_commands
从流中提取所有命令,它是解析器的主要功能。parser_command
从流中提取命令。
可以测试代码here .
#include <stdlib.h>
#include <ctype.h>
/*
commands:
EOF
|
command commands
command:
command_begin string command_end
string:
anything but command_end
command_begin:
QUOTE
command_end:
QUOTE SEMICOLON
|
QUOTE EOF
*/
struct iss_t
{
char* s;
char* g;
};
typedef struct iss_t iss_t;
char iss_get_char( iss_t* self )
{
if ( !*self->g )
return 0;
return *self->g++;
}
struct wschar_t
{
char c;
char s[ 1024 ];
};
typedef struct wschar_t wschar_t;
char iss_get_wschar( iss_t* self, wschar_t* r )
{
char* p = r->s;
while ( isspace( *p++ = r->c = iss_get_char( self ) ) )
;
*p = 0;
return r->c;
}
char iss_peek_wschar( iss_t* self )
{
char* savedg = self->g;
wschar_t t;
iss_get_wschar( self, &t );
self->g = savedg;
return t.c;
}
enum token_t
{
tk_done,
tk_beg,
tk_end,
tk_rest
};
typedef enum token_t token_t;
struct parser_t
{
iss_t* iss;
wschar_t wschar;
token_t token;
};
typedef struct parser_t parser_t;
token_t parser_get_token( parser_t* self )
{
iss_get_wschar( self->iss, &self->wschar );
// if done
if ( self->wschar.c == 0 )
return self->token = tk_done;
// not a quote
if ( self->wschar.c != '\"' )
return self->token = tk_rest;
// it is quote: check the next token
switch ( iss_peek_wschar( self->iss ) )
{
case 0:
case ';':
iss_get_wschar( self->iss, &self->wschar ); // eat
return self->token = tk_end;
default:
return self->token = tk_beg;
}
}
int parser_command( parser_t* self )
{
printf( "COMMAND: " );
if ( self->token != tk_beg )
{
printf( "command begin expected" );
return -1;
}
while ( parser_get_token( self ) == tk_rest || self->token == tk_beg )
printf( self->wschar.s );
if ( self->token != tk_end )
{
printf( "command end expected" );
return -1;
}
printf( "\n" );
return 0;
}
void parser_commands( parser_t* self )
{
while ( 1 )
{
switch ( parser_get_token( self ) )
{
case tk_done:
return;
default:
if ( parser_command( self ) < 0 )
return;
};
};
}
int main()
{
char* s = "\"command1\"; \"sleep 30; command2 -a ; command3\"; \"command4=\"MyTest\"\"";
iss_t iss = { s, s };
parser_t parser = { &iss };
parser_commands( &parser );
return 0;
}
关于C strtok 解析复杂字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50721554/