【问题标题】:Command line arguments in C- weird outputC-奇怪的输出中的命令行参数
【发布时间】:2017-10-21 05:11:28
【问题描述】:

所以我为一个简单的逆波兰计算器编写了一个代码,它只适用于使用命令行参数的正数。它将数字存储在堆栈中。 push 和 pop 的函数位于单独的源文件中。
我还编写了另一个程序来检查我之前程序的控制流。
这是第一个程序:

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
void push(double);
double pop(void);
int main(int argc, char *argv[])
{
    int c;
    double op2;
    while(--argc>0 && (c=(*++argv)[0]))
        if(isdigit(c))
            push(atof(argv[0]));

        else if(c=='+')
            push(pop()+pop()); 

        else if(c=='-')
        {
            op2=pop();
            push(pop()-op2); 
        }

        else if(c=='*')
            push(pop() * pop()); 

        else
        {
            op2=pop();
            push(pop()/op2); 
        }

    printf("\n%f\n", pop());   
    return 0;
} 

在我运行这个程序之后,所有的操作符都工作了,除了'*'。例如,如果我的输入是“./pcalc 2 3 *”,那么我得到的输出是:
error: stack emptyerror: stack emptyerror: stack emptyerror: stack empty -nan

如果我在 while 循环中交换条件,像这样
while((c=(*++argv)[0]) &amp;&amp; --argc&gt;0)
然后我收到所有运营商的“分段错误(核心转储)”消息。

为了了解我的程序的控制流程,我把部分代码改成了这样:

while(--argc>0 && (c=(*++argv)[0]))
    if(isdigit(c))
        printf("\nentry1\n");

    else if(c=='+')
        printf("\nentry2\n");

    else if(c=='-')
        printf("\nentry3\n");    

    else if(c=='*')
        printf("\nentry4\n");

    else
        printf("\nentry5\n");  

程序的其余部分与第一个类似。在将输入作为 ' ./pcalc 2 3 * ' 时,我得到以下输出:

entry1

entry1

entry5

entry5

entry5

entry5

entry5
error: stack empty  
0.000000  

这意味着控制没有转到星号的大小写,而是转到了 else 部分。
当我交换while循环的条件时,我得到的输出与上面相似(对于所有运算符,它显示控制流,对于'*',它显示与上面相同的错误),除了它没有' 不显示任何运算符的堆栈空错误,而是显示分段错误(核心转储)消息。

所以这就是我想问的:
1)我的第一个程序适用于所有运算符,除了'*'。可能是什么原因?为什么控制权转到了else部分?

2) 交换条件后,我访问了哪些我没有权限的内存?如果它是NULL,那么不应该打破while循环并继续吗?

PS。这是我的第一个问题,所以如果我的写作风格有任何错误,或者问题太长,请告诉我!我们从错误中吸取教训 :)
还有,我的编译器-GCC,OS-Ubuntu。

【问题讨论】:

  • 旁注:您提到您的 pushpop 函数位于单独的源文件中。确保将它们保留为函数。也就是说,无论你做什么,都不要使用像#define pop() stack[--stackp] 这样的函数式宏。否则,当您编写 push(pop()+pop()) 之类的内容时,这将是未定义的行为。 (但只要pushpop 是函数,就可以了。)
  • 出于调试目的,在处理它们之前尝试打印出所有命令行参数。您可能会看到与预期不同的东西,尤其是从命令行运行程序时。
  • @xing 太好了,谢谢!但是当条件互换时,段错误的原因可能是什么?
  • @AkhilAbraham “段错误的原因是什么?”尝试为else if(c=='/') 添加一个显式测试,并在最后加上一个包罗万象的else,它只打印“意外输入”之类的东西。
  • while(--argc&gt;0 &amp;&amp; (c=(*++argv)[0])) 如果我在代码审查中看到这一点,那么您正在重写该行以使其可读。

标签: c pointers segmentation-fault command-line-arguments


【解决方案1】:

用户xing是绝对正确的。
为了扩展它,&amp;&amp; 运算符从左到右进行评估。如果左侧条件无效,则不会评估右侧条件,因为返回值已知为 0 (false)。
运行 ./pcalc 2 3 * 将扩展为 ./pcalc 2 3 &lt;all the files/directories in current working directory&gt;,因此它永远不会将运算符压入运算符堆栈。

  • while(--argc&gt;0 &amp;&amp; (c=(*++argv)[0])) 将首先检查它是否仍在参数数组中,然后再提取第一个元素。
  • while((c=(*++argv)[0]) &amp;&amp; --argc&gt;0) 将首先尝试提取一个值,然后检查它是否仍在数组的边界内。如果没有,那么它已经出现了段错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    相关资源
    最近更新 更多