【发布时间】:2014-11-22 02:06:29
【问题描述】:
我正在尝试做一个 RPN,其中我的非恒定 argv 向量通过将运算符替换为操作结果来存储和检索计算结果: argv[0]="2"; argv[1]="3"; argv[2]="+" ==> argv[0]="2";argv[1]="3";argv[2]=5 我的代码适用于简单的 RPN 输入——最多一次操作的输入;它在嵌套操作中失败,因为当它读取 argv[n] 时,它没有在其中找到任何内容,因此它认为它为零。 你们能帮忙吗?代码如下:
/*
* Ahmed AlJehairan
* Github: aj326
* Description: Reverse Polish Calc. Usage ./expr n1 n2 op
*/
#include <stdio.h>
#include <stdlib.h>
#define DEBUG 1
//Will implement error checking later:
/*
Errors to check for:
arg starts with letter
first arg not a number
check at least two arg for binary ops
*/
int main(int argc, char *argv[])
{
char **s = argv;
int len = argc;
if (argc < 3)
{
printf("At least 2 arguments\n");
return 1;
}
if (--argc) argv++;
int val;
while (argc--)
{
switch (**argv)
{
case '+': ; val = atoi(*(argv - 2)) + atoi(*(argv - 1)); snprintf (*argv, sizeof(int), "%d", val); if (DEBUG) printf("after arith *argv %s \n", *argv); break;
case '=': ; val = atoi(*(argv - 2)) == atoi(*(argv - 1)); snprintf (*argv, sizeof(int), "%d", val); if (DEBUG) printf("after arith *argv %s \n", *argv); break;
case '-': ; val = atoi(*(argv - 2)) - atoi(*(argv - 1)); snprintf (*argv, sizeof(int), "%d", val); if (DEBUG) printf("after arith *argv %s \n", *argv); break;
case '*': ; val = atoi(*(argv - 2)) * atoi(*(argv - 1)); snprintf (*argv, sizeof(int), "%d", val); if (DEBUG) printf("after arith *argv %s \n", *argv); break;
case '/': ; val = atoi(*(argv - 2)) / atoi(*(argv - 1)); snprintf (*argv, sizeof(int), "%d", val); if (DEBUG) printf("after arith *argv %s \n", *argv); break;
case '%': ; val = atoi(*(argv - 2)) % atoi(*(argv - 1)); snprintf (*argv, sizeof(int), "%d", val); if (DEBUG) printf("after arith *argv %s \n", *argv); break;
}
if (DEBUG)
{
int i;
for (i = 0; i < len; ++i)
{
printf("%s\t", s[i]);
}
printf("\n");
}
argv++;
}
printf("%s\n", *--argv);
return 0;
}
【问题讨论】:
-
为结果准备另一个转换的数组。
-
我将简单地指出编写一个在给定无效输入的情况下按设计调用未定义行为的程序是多么可怕。 IE。
+ 0 1。更糟糕的是,假设输入是“有效的”,尽管标准允许您将 alternate 地址存储在 0..argc 中的任何n的argv[n]。它没有声称 exiting 地址处的内存是可写的。简而言之,这是一个可怕的想法。使用适当大小的本地int堆栈。 -
@WhozCraig 关于“标准允许您将备用地址存储在 argv[n]”参见stackoverflow.com/questions/25737434/is-argvn-writable/25747537 此外,规范明确表示 argv[][] 是可写的,尽管它在该范围内是安静的。
-
@chux 对我来说是新手。我记得(诚然可能不正确),argv 指向的字符串并不总是可修改的,尽管地址 in
argv是可替换的。但是,即使在 OP 的情况下,给定字符串单字符参数'1'的大小也不是sizeof(int)(32 位 = 4 个八位字节)。最多是1可写字符+终止NULL(snprintf的第二个参数应该解释;即2表示1+nullchar,4表示3+nullchar,这显然不适合以前的字符串1+nullchar).