嗨我想在C
中标记一个字符串以下是字符串。
{工作开始} {工作正在运行} {工作正在运行} {工作完成}
我想在{和}标记,以便我得到“工作开始”,“工作正在运行”和“完成工作”
我也希望将相同的分隔符用作转义字符
{工作已开始} {工作\ {ID1 \}正在运行} {工作\ {ID2 \}正在运行} {工作完成}
应该在
之后回复我作业已开始,作业{ID1}正在运行,作业{ID2}正在运行,作业已完成。
我有指针airthmatic的解决方案,但希望避免多次重复输入字符串。
任何建议。
答案 0 :(得分:5)
您可以使用简单的有限状态机:
#include <stdio.h>
int main() {
char *src = "{Job Started}{Job \\{ID1\\} Running}{Job \\{ID2\\} Running}{Job Finished}";
char token[100] = {}, *dst = token, ch;
int state = 0;
while ((ch = *src++) != 0) {
switch (state) {
case 0:
if (ch == '{') state = 1;
break;
case 1:
switch (ch) {
case '}':
printf("token: %s\n", token);
dst = token;
*dst = 0;
state = 0;
break;
case '\\':
state = 2;
break;
default:
*dst++ = ch;
*dst = 0;
}
break;
case 2:
*dst++ = ch;
*dst = 0;
state = 1;
break;
}
}
}
答案 1 :(得分:1)
您可以使用strtok
()
并将分隔符设置为{}
(以及您需要的任何其他内容)。解析后的字符串中的两个或多个连续分隔符字符序列被视为单个分隔符,您还可以修改连续调用之间的分隔符集。另请注意,strtok()会修改赋予它的字符串。
编辑:我意识到这还不足以满足你的第二个要求。
答案 2 :(得分:1)
{a}{
,{{1} },{{{{{
,}a{
)。
类似[快速编写且未经测试!!]:
{blah} {blah}
答案 3 :(得分:0)
我已经使用strtok()了。这对于具有转义字符的字符串不起作用,但我认为可以对其进行修改以理解它们。尽管如此,这并不是那么微不足道。希望这会给你一些帮助。
#include <stdio.h>
#include <string.h>
int main(void) {
char str[] = "{Job Started}{Job Running}{Job Running}{Job Finished}";
char* pch;
pch = strtok(str,"{}");
while(pch!=NULL) {
printf("%s\n",pch);
pch = strtok(NULL,"{}");
}
return 0;
}
德尔南在那里有一个观点。字符串操作太难了,容易受到C中指针处理失败的影响。如果C对于你的项目不是必需的,你肯定应该使用其他语言。
答案 4 :(得分:0)
如果您想扩展其功能,可以查看Eric Robert's scannerADT
。使用起来非常简单,您可以添加setDelimiter
方法。
Here是.c和.h。
答案 5 :(得分:0)
char **
split( char **result, char *tmp, const char *src, const char *delim, size_t len)
{
int i=0;
char *p=NULL;
for(i=0; i<len; i++)
result[i]=NULL;
if(!*src)
return result;
strcpy(tmp, src);
for(i=0, p=strtok(tmp, delim); p!=NULL; p=strtok(NULL, delim), i++ )
{
result[i]=p;
}
return result;
}
此示例不会销毁原始字符串,而是传入一个工作字符串。
答案 6 :(得分:0)
char *tokenizer(char *ptr) {
char *str = ptr;
char *aux = ptr;
while (*ptr) {
if ( *ptr == '\\' && ( *(ptr + 1) == '{' || *(ptr + 1) == '}') ) {
*aux++ = *(ptr + 1);
ptr += 2;
}
else if ( *ptr == '{') {
++ptr;
}
else if ( *ptr == '}' ) {
*aux++ = ( *(++ptr) != '\0' ) ? ',' : '.';
}
else {
*aux++ = *ptr++;
}
}
*aux = '\0';
return str;
}
答案 7 :(得分:0)
您可以使用sscanf。您可能希望使用链接中的引用创建适当的分隔符。
/ * sscanf示例* /
#include <stdio.h>
int main ()
{
char sentence []="Rudolph is 12 years old";
char str [20];
int i;
sscanf (sentence,"%s %*s %d",str,&i);
printf ("%s -> %d\n",str,i);
return 0;
}
<强>输出:强>
Rudolph -> 12
Strtok和strtok_r(strtok的可重入版本)也可用于解析字符串。
PS:我在这里从另一个有类似要求的问题复制我的例子
答案 8 :(得分:0)
如果那个是您唯一的扫描/标记问题,您可能最好使用您已有的解决方案或实施FSM作为Ferruccio建议。
如果您有其他类似的问题,另一方面,您可能会寻找可以帮助您的工具或库。有人建议使用lex,但你也可以设置正则表达式库。
给定一个字符串匹配库,您可以编写如下内容:
pmx_t ret;
ret = pmxMatchStr(src,"&e\\&K{(<*!}>)}&K{(<*!}>)}&K{(<*!}>)}&L")));
if (ret) {
printf("%.*s, %.*s, %.*s\n",pmxLen(ret,1),pmxStart(ret,1),
pmxLen(ret,2),pmxStart(ret,2),
pmxLen(ret,3),pmxStart(ret,3)
}
(也处理{...}
之前或之间的空格并吃完线的末尾)
是的,这个例子是对我的library (pmx)的无耻推广,但同样的概念适用于您可以在C中使用Google搜索regexp或正则表达式库的其他许多其他概念。