这是我的代码:
char a[18], b[18];
char oper, clear;
char *test;
init_8051();
test="0x1234567890123456 + 0x1234567890123456\0";
printf("Please enter an equation: %s \n",test );
sscanf(test,"0x%s %c 0x%s",a,&oper,b);
printf(" a= %s \n" ,a);
printf(" oper= %s \n" ,oper);
printf(" b= %s \n" ,b);
我想接受带有操作字符串的十六进制数字,并且能够将这两个数字分成2个单独的字符数组,但它不想工作,这里是以下代码的输出:
Please enter an equation: 0x1234567890123456 + 0x1234567890123456
a= 1234567890123456
oper= Ò
b= 1234567890123456
正如你所看到的那样,操作无法识别,而且我必须使用我希望我不必使用的空格我希望它的格式为0x1234567890123456 + 0x1234567890123456 在加号和数字之间没有空格。
由于
答案 0 :(得分:1)
来自sscanf
手册
s Matches a sequence of non-white-space characters; the next pointer must be a pointer to character array that is long enough to hold the input sequence and the
terminating null byte ('\0'), which is added automatically. The input string stops at white space or at the maximum field width, whichever occurs first.
这意味着%s
会消耗+
和其他字符,b
和oper
未经注册,abd溢出a
,因为它只有18
个字符的空格。
因此,当输入字符串缺少第一个操作数之后的空格时,sscanf
将继续读取,直到找到空格字符。因此,当字符串不包含操作数和运算符之间的分隔空间时,sscanf
会消耗所有输入。
我会在这里附加一个与您的问题解决方案不同的方法
我们复制字符串,这是strtok所要求的,你不能传递一个不可变的字符串,有很多方法可以复制这个字符串,你只需要为你的情况选择合适的字符串
input = strdup("0x1234567890123456 + 0x1234567890123456\0");
现在,我们使用strpbrk来查找运算符
pointer = strpbrk(input, "+-*/" /* here go the operators */);
if (pointer != NULL)
oper = *pointer; /* this will contain the operator ascii value */
创建一个包含运算符作为分隔符的字符串
operstr[0] = oper;
operstr[1] = '\0'; /* strings must be null terminated */
现在,我们使用strtok来标记字符串,并找到操作数
pointer = strtok(input, operstr);
if (pointer != NULL)
fprintf(stderr, "first operand: %s\n", pointer); /* you can copy this string if you need to */
printf("Operator: %s \n", operstr);
第二次调用strtok需要NULL
第一个参数
pointer = strtok(NULL, operstr);
if (pointer != NULL)
fprintf(stderr, "second operand: %s\n", pointer); /* you can copy this string if you need to */
最后free
输入字符串的副本。
free(input);
最好使用strtok_r可重入版本。但是现在你可以测试我的建议,可能是你需要的。
即使这适用于这种特殊情况,它也不是做这种事情的首选方式,你可以尝试编写解析器并使用Reverse Polish Notation,或者你可以尝试使用词法分析器和解析器生成器如flex和bison。
答案 1 :(得分:0)
我之前的回答被低估了,并没有解决所有OP的要求,所以我重写了这个答案。
OP需要灵活的输入,空格或空格。我建议不要使用sscanf()
,而是使用以下方法。首先,程序使用strcspn()
找到一个有效的运算符,然后在运算符和空格上使用strtok()
中断字符串。但是在字符串文字上使用strtok()
是UB,所以我首先将“等式”复制到另一个字符串。
我还更正了运算符的printf()
字段规范,并使a
和b
不同 - 在示例中对不同变量使用相同的值总是一个坏主意。< / p>
#include <stdio.h>
#include <string.h>
#define OPERATORS "+-*/"
#define DELIMS " \t\n" OPERATORS
int parse (char *test)
// return 1 if parsed successfully
{
char a[50], b[50];
char oper;
char *ptr;
int opind;
opind = strcspn (test, OPERATORS); // find operator
if (opind < 1) return 0; // fail
oper = test[opind]; // collect operator
ptr = strtok (test, DELIMS); // find a
if (ptr == NULL) return 0; // fail
strcpy (a, ptr); // collect 1st arg
ptr = strtok (NULL, DELIMS); // find b
if (ptr == NULL) return 0; // fail
strcpy (b, ptr); // collect 2nd arg
printf(" a %s \n" ,a);
printf(" oper %c \n" ,oper); // corrected format
printf(" b %s \n" ,b);
return 1;
}
int main (void)
{
char test[100];
strcpy (test, "0x123456789ABCDEF0+0xFEDCBA9876543210");
if (!parse (test))
printf("Failed\n");
printf("\n");
strcpy (test, "0x123456789ABCDEF0 + 0xFEDCBA9876543210");
if (!parse (test))
printf("Failed\n");
return 0;
}
节目输出
a 0x123456789ABCDEF0
oper +
b 0xFEDCBA9876543210
a 0x123456789ABCDEF0
oper +
b 0xFEDCBA9876543210