我正在研究用C编写的计算器的终端解析器。我无法弄清楚如何连接运算符之间的所有数字以将它们放入数组中。
例如,如果输入(命令行参数)是“ 4+342
”,则理想情况下input[] = {"4", "+", "342"}
。
到目前为止,这是我的代码。 我包括 ,
和
。
typedef char * string; int main(int argc, char *argv[]) { string inputS = argv[1]; string input[10]; string temp; printf("%sn", inputS); int i; int len = strlen(inputS); printf("parsed:n"); for(i = 0; i < len; inputS++, i++) { if(isdigit(*inputS)) { printf("%c",*inputS); } else { printf("n%cn",*inputS); } } printf("n"); return 0; }
如果它以./calc 4+5-546
运行,它将输出:
4 + 5 - 546
那么将每一行放入自己的arrays插槽的最简单方法是什么?
试试这个尺码……
#include #include typedef char * string; int main(int argc, char *argv[]) { string inputS = argv[1]; string input[50]; /* Up to 50 tokens */ char buffer[200]; int i; int strnum = 0; char *next = buffer; char c; if (argc != 2) { fprintf(stderr, "Usage: %s expressionn", argv[0]); return 1; } printf("input: <<%s>>n", inputS); printf("parsing:n"); while ((c = *inputS++) != ' ') { input[strnum++] = next; if (isdigit(c)) { printf("Digit: %cn", c); *next++ = c; while (isdigit(*inputS)) { c = *inputS++; printf("Digit: %cn", c); *next++ = c; } *next++ = ' '; } else { printf("Non-digit: %cn", c); *next++ = c; *next++ = ' '; } } printf("parsed:n"); for (i = 0; i < strnum; i++) { printf("%d: <<%s>>n", i, input[i]); } return 0; }
鉴于该程序被称为tokenizer
和命令:
tokenizer '(3+2)*564/((3+4)*2)'
它给了我输出:
input: <<(3+2)*564/((3+4)*2)>> parsing: Non-digit: ( Digit: 3 Non-digit: + Digit: 2 Non-digit: ) Non-digit: * Digit: 5 Digit: 6 Digit: 4 Non-digit: / Non-digit: ( Non-digit: ( Digit: 3 Non-digit: + Digit: 4 Non-digit: ) Non-digit: * Digit: 2 Non-digit: ) parsed: 0: <<(>> 1: <<3>> 2: <<+>> 3: <<2>> 4: <<)>> 5: <<*>> 6: <<564>> 7: <>> 8: <<(>> 9: <<(>> 10: <<3>> 11: <<+>> 12: <<4>> 13: <<)>> 14: <<*>> 15: <<2>> 16: <<)>>
最简单的解决方案是使用像flex之类的工具来生成词法分析器并让它完成将输入分解为标记的工作(尽管flex期望其输入来自文件流,而不是字符数组)。
由于以下几个原因, strtok()
不是一个好的解决方案:
通常的解决方案是编写一个状态机(这基本上就是flex为你做的)。 这是一个非常快速的脏(强调脏)示例:
#include #include #include #include /** * Read from a string specified by source, updating the pointer as we go. * We're assuming that token points to a buffer large enough to hold * our largest token; ideally, you would want to pass the length of the * target buffer and check against it, but I'm leaving it out for brevity. * * Tokens are either integers (strings of digits) or operators. * * Return 1 if we successfully read a token, 0 if we encountered an unexpected * character, and EOF if the next character is the end of the input string. */ int getToken(char **source, char *token) { enum {START, DIGIT, ERROR, DONE} state = START; size_t i = 0; char *operators="+-*/"; if (**source == 0) // at end of input return EOF; while (**source != 0) { switch(state) { /** * Initial state for this call. */ case START: if (isdigit(**source)) { state = DIGIT; token[i++] = *(*source)++; // append the digit to the token } else if (strchr(operators, **source) != NULL) { state = DONE; token[i++] = *(*source)++; // add the operator to the token token[i++] = 0; // and terminate the string } else if (isspace(**source)) { (*source)++; // ignore whitespace } else { /** * We've read something that isn't a digit, operator, or * whitespace; treating it as an error for now. */ state = ERR; } break; /** * We've read at least one digit. */ case DIGIT: if (isdigit(**source)) { token[i++] = *(*source)++; // append next digit to token } else { /** * We've read a non-digit character; terminate the token * and signal that we're done. */ token[i++] = 0; state = DONE; } break; case DONE: return 1; break; case ERR: return 0; break; } } return 1; } int main(int argc, char **argv) { char token[20]; char *input = argv[1]; for (;;) { int result = getToken(&input, token); if (result == 1) printf("%sn", token); else if (result == 0) { printf("Bad character '%c'; skippingn", *input); input++; } else if (result == EOF) { printf("donen"); break; } } return 0; }
为什么(*source)++
而不是*source++
或source++
? 我不想更新source
,我想更新source
点 ,所以我必须在应用++
之前取消引用指针。 表达式*(*source)++
基本上转换为“给我表达*source
指向的字符的值,然后更新*source
的值”。
– > MAN STRCAT
#include #include #include int main (int argc, const char **argv) { char *toto_str = "Toto"; char *is_str = "Is"; char *awesome_str = "Awesome"; char *final_str; size_t i; i = strlen(toto_str); i += strlen(is_str); i += strlen(awesome_str); final_str = malloc((i * sizeof(char)) + 1); strcat(final_str, toto_str); strcat(final_str, is_str); strcat(final_str, awesome_str); printf("%s", final_str); free(final_str); return 0; }
strsep在这里是一个不错的选择 – 抓住令牌,然后决定你想用它做什么……
char * string =“(3+(5 + 6)/ 8)”
char 令牌; while((token = strsep(&string,“(+ / )”))){//存储令牌…如果它不是(或)或空格}
这里 – 令牌将被处理类似于Java / C#中的Split()。 这会在处理字符串时破坏字符串 – 但是,使用正确的分隔符 – 事情会很好:)
听起来你想看看标准的strtok
function。
这会给你一个想法:
#include #include main(int argc, char *argv[]) { printf("nargv[1]: %s",argv[1]); char *p; p = strtok(argv[1],"+"); printf("np: %s", p); p = strtok(NULL,"+"); printf("np: %s", p); p = strtok(NULL,"+"); printf("np: %s", p); printf("n"); }
这只是一个示例代码,演示了如何仅使用附加案例来完成它。
了解此代码的主要概念并将其应用于您的代码中。
示例输出:
./a.out 5+3+9 argv[1]: 5+3+9 p: 5 p: 3 p: 9
同样,我只是在展示“+”标志。 你可能想检查p直到它为NULL,然后继续下一个操作,比如减法,然后乘法,然后除法。
以上就是c/c++开发分享用C标记字符串?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/559842.html