如何在C中区分作为字符的单个数字和多个数字?
所以,我从stdin读取输入,我必须从中计算算术。例如,我可能会得到:如何在C中区分作为字符的单个数字和多个数字?,c,arrays,char,int,arithmetic-expressions,C,Arrays,Char,Int,Arithmetic Expressions,所以,我从stdin读取输入,我必须从中计算算术。例如,我可能会得到: 3+4 4+3 7+9 然后将其放入一个字符数组中,如下所示: {3+4;4+3;7+9} 我想创建一个程序,该程序将接受此输入并返回: {7;7;16} 因为这是C中的stdin,所以每个元素都是char类型。 我创建了以下代码来处理这样的数组并返回正确的结果: char *int2string(int i, char *s) { sprintf(s, "%d", i); return s; }
3+4
4+3
7+9
然后将其放入一个字符数组中,如下所示:
{3+4;4+3;7+9}
我想创建一个程序,该程序将接受此输入并返回:
{7;7;16}
因为这是C中的stdin,所以每个元素都是char类型。
我创建了以下代码来处理这样的数组并返回正确的结果:
char *int2string(int i, char *s)
{
sprintf(s, "%d", i);
return s;
}
bufferlen = strlen(buffer);
int result;
for (i = 0; i < bufferlen; i++)
{
if (isNumeric(buffer[i]))
{
value1 = atoi(&buffer[i]);
if (buffer[i + 1] == '+')
{
if (isNumeric(buffer[i + 2]))
{
value2 = atoi(&buffer[i + 2]);
result = value1 + value2;
printf("This is the result: %d\n", result);
int2string(result, &buffer[i]);
for (int k = i + 1; k < bufferlen; k++)
{
buffer[k] = buffer[k + 2];
}
//bufferlen = bufferlen - 2;
}
}
}
}
我的代码返回以下内容:
This is the result: 26
322;
我相信这是因为我的代码一次只能读取一个字符,无法区分单个数字和由多个数字组成的数字。有什么办法可以解决这个问题吗?您可以使用
sscanf
获取运算符和任意数字。您可以按如下方式使用它:
int sum, len;
sscanf(buffer, "%d%n", &sum, &len); // get the first number
int number;
char op;
buffer += len;
// then pattern is: "operation""number"
while(sscanf(buffer, "%c%d", &op, &number) == 2) // while you can scan both operation and number
{
if (op == '+')
sum += number;
else if (op == '-')
sum -= number;
...
}
关于sscanf的更多信息。我认为,你的问题是,你正在做类似的事情
value1 = atoi(&buffer[i]);
if (buffer[i + 1] == '+')
...
char *endp;
value1 = strtol(p, &endp, 10);
p = endp;
if (*p == '+')
...
在这个片段中,索引i
指向缓冲区中当前正在解析的点。您认为(并且正确地认为)i
“指向”一个或多个数字字符中的第一个。您可以调用atoi
将这些数字转换为实际整数。到目前为止还不错。但是,然后测试buffer[i+1]
以查看数字后面是否有运算符字符。这就是错误的假设产生的地方,即数字总是一位数长。这就是为了正确处理多位数数字需要解决的问题
我认为,解决这个问题的最佳方法是使用strtol
而不是atoi
。atoi
和strtol
之间最明显的区别在于strtol
告诉您它走了多远,使用了多少位数。它通过向您返回指向它未使用的第一个字符的指针来实现这一点
这意味着,要使用strtol,您必须显式地使用指针。如果你用指针的话会容易得多
char *p;
单步执行缓冲区
,而不是索引i
。但是你可以这样说
value1 = atoi(&buffer[i]);
if (buffer[i + 1] == '+')
...
char *endp;
value1 = strtol(p, &endp, 10);
p = endp;
if (*p == '+')
...
其工作方式是,strtol
将endp
设置为指向它未使用的第一个字符。这就是您想要继续解析的地方,因此您将p
设置为endp
并继续
这里实际发生的是strtol
接受指向指针的指针。如果你还不习惯使用指针,你可能真的还没有准备好考虑指向指针的指针,但是相信我,这是有效的。我想我应该澄清一下,输入是从stdin获取的,并自动放入如下字符数组:{3+4;5+4;34+22}
我必须获取这个数组并计算算术,返回这样的数组:{7;9;56}
这无关紧要。对于char数组的每个元素,执行我提供的解决方案。您是否考虑过使用strtok
或编写一个实际的语法来与lexer和parser一起使用?不,它实际上没有那么复杂。尝试if(sscanf(s),%d+%d,&a,&b)==2)作为测试,看看输入是否是一个加法。“我必须计算算术”是含糊不清的。必须检测多少算术?谢谢您的帮助。我会尝试使用这个策略,如果我成功了会通知你。所以,我知道如何使用strtol。然而,我真的不明白如何使用它来迭代缓冲区?我也许可以使用while循环,但我不知道条件是什么。@bugg98基本思想是:(a)将inti
更改为char*p
,(b)将for(I=0;I
更改为for(p=buffer;p
,(c)更改buffer[I]的所有实例到*p
,以及(d)做我在p
、endp
和strtol
中提到的事情。如果您有剩余的缓冲区[i+1]
,您可以将其更改为*(p+1)
或p[1]
(类似于+2
等)。如果您仍然需要在k
上运行第二个循环,您可以使用char*p2
执行类似的操作。