我正在尝试创建一个函数(在C中)来解决放在缓冲区变量中的加法。到目前为止它适用于导致一位数字的方程式,但是如果结果超过一位数,则会导致问题。例如,如果我在缓冲区中放置2 + 3 + 5 + 2,则输出102,而不是12.任何人都可以指出我的错误在哪里以及如何解决它们吗?
这是我的代码:
char buffer[50];
void *adder(void)
{
int bufferlen;
int value1, value2;
int startOffset, remainderOffset;
int i;
char result[10];
while (1)
{
startOffset = remainderOffset = -1;
value1 = value2 = -1;
bufferlen = strlen(buffer);
for (i = 0; i < bufferlen; i++) {
if(value1 == -1)
{
if(isNumeric(buffer[i]))
{
value1 = string2int(&buffer[i]);
startOffset = i;
}
}
else
{
if(buffer[i] == 43)
{
if(isNumeric(buffer[i+1]))
{
value2 = string2int(&buffer[i+1]);
remainderOffset = i+1;
}
}
}
if(value1 != -1 && value2 != -1)
{
int k=0;
int j=0;
int2string((value1 + value2),result);
/* print out the number we've found */
fprintf(stdout, "Re:%s\n", result);
int resultlen = strlen(result);
for(k=startOffset; k < bufferlen; k++)
{
if(j < resultlen)
{
buffer[k] = result[j];
j++;
}
else
{
/* shift the remainder of the string to the left */
printf("A1-Buffer:%s\nk=%i\n", buffer, k);
if(j > 0)
buffer[k] = buffer[k+2];
else
buffer[k] = buffer[k+2];
printf("A2-Buffer:%s\n", buffer);
i = i - remainderOffset;
startOffset = remainderOffset = -1;
value1 = value2 = -1;
}
}
}
}
break;
}
}
编辑:啊,对不起,忘记了额外的功能。此函数用于学校作业,isNumeric()和String2int()与isdigit()和atoi()完全相同,并提供给我们在函数中使用。
编辑2:添加数字后,必须将结果添加回表达式中的缓冲区,如下所示:(2 + 3) - &gt; (5)原因是最终将编写更多的函数来处理乘法,除法等。这是我的主要挫折所在 - 将结果放在表达式的位置并将缓冲区移到适当的位置。
答案 0 :(得分:1)
char buffer[50];
为什么50个字节?为什么不100?您应该接受指针作为参数,而不是依赖于全局。此外,buffer
不是描述性名称。
void *adder(void)
该函数不返回void *
;它没有回报价值。你可以考虑
/* return value of expression */
int evaluate_add_expression( char const *in_string )
或
/* return status code */
int evaluate_add_expression( char const *in_string, int *out_value )
接下来,在不初始化变量的情况下声明许多变量。将声明移动到循环中并包含声明的初始化,即int value1 = -1, value2 = -1;
当然,这些名称根本不具有描述性。
if(buffer[i] == 43)
值'+'
是表示加号字符的更好方式,而不是幻数43。
如果我是你,我会利用sscanf
功能。
int evaluate_add_expression( char const *in_string, int *sum ) {
int addend;
size_t offset, offset_delta;
if ( sscanf( in_string, " %d %zn", sum, &offset ) != 1 ) return 1;
while ( sscanf( in_string + offset, "+ %d %zn", &addend, &offset_delta ) == 1 ) {
* sum += addend;
offset += offset_delta;
}
return in_string[ offset ] != '\0'; /* check that all input was consumed */
}
这个工作正常,大约15%。
答案 1 :(得分:1)
请注意
if(j > 0)
buffer[k] = buffer[k+2];
else
buffer[k] = buffer[k+2];
无论j
的值如何,都会执行相同的代码。另请注意,j
在您的代码中永远不会为负数。
你的缓冲阵列越界越界。您的循环计数器i
在每个循环结束时递增1,但您也在执行
i = i - remainderOffset;
k
循环中 多次。当然,必须给你一个负面的i
?
此外,当您使用
移回缓冲区时 buffer[k] = buffer[k+2];
循环将k
提升到bufferLen
,因此此处k+2
也超出范围。
我不确定为什么要把所有东西都移回固定数量的两个位置呢?当然,假设您刚刚添加了一位数字?
考虑这些问题,你会开始看到你哪里出错了。我同意其他人的意见,如果你可以利用现有的代码,那么就这样做。
编辑:回复您的评论
我认为它是将结果存储在缓冲区中的赋值的一部分?如果没有,那么只需在整数中跟踪它,一切都简化了。如果赋值说您必须使用中间结果更新缓冲区,请注意以下内容:
假设当前缓冲区位置开头的两个数字称为A和B,A是两位数字,B是三位数字。就结果所需的存储量而言,有两种可能的结果,即R <或者
AA+BBB+remainder -> RRR+remainder
或
AA+BBB+remainder -> RRRR+remainder
这意味着您的变量取决于结果的位数,是的,您可以将其基于resultLen
(但它本身不是resultLen
)。请注意,如果你向后移动,你需要填充你在缓冲区末尾留下的一些合适字符的间隙,或者跟踪缓冲区真正结束的位置。
不是将其余部分向后移动,而是将其保持在原位并将结果写在它之前的正确位置(除非你的作业明确要求你将其向后移动)。所以你拿
AA+BBB
并将其转换为
...DDD
或
..DDDD
其中圆点表示我们不再感兴趣的字符。只要您在while
循环的每次迭代中更新了起始索引,那么这些字符就无关紧要了(摆脱{ {1}}循环)。如果你知道A,B和R的数字位数,这对你来说应该不会太困难。最后,当起始索引达到i
时,跳出while
循环。