使用命令行界面减少程序代码?

Reduce code for program with command line interface?

我希望我的程序具有如下所示的界面:

gen_data [start] [stop] [step]

[start][stop][step] 是可选的,默认设置为 -3*PI/23*PI/20.01。我有以下代码:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

#define PI 3.14569

int main (int argc, char **argv)
{
    float i, start, stop, step;
    printf ("# gnuplot data\n" 
            "# x sin(x) cos(x)\n");
    switch (argc) {
        case 1:
            start = -(3*PI)/2;
            stop = (3*PI)/2;
            step = 0.01;
            break;

        case 2:
            start = atof (argv[1]);
            stop = (3*PI)/2;
            step = 0.01;
            break;

        case 3:
            start = atof (argv[1]);
            stop = atof (argv[2]);
            step = 0.01;
            break;

        case 4:
            start = atof (argv[1]);
            stop = atof (argv[2]);
            step = atof (argv[3]);
            break;
    }
    for (i = start; i <= stop; i += step)
    printf ("%6f\t%6f\t%6f\n", i, sin (i), cos (i));

    return 0; 
}

如您所见,所有三个变量 startstopstep 都被赋值 每次 - 这不是多余的吗?我大致想到了这样的事情:

我使用 switch-case 的原因是为了能够利用 fall through - 但无法让它发挥作用。有什么想法吗?代码是否正常?

使用三进制真的很容易。你可以简单地做:

    if (argc < 2) {
        fputs ("error: insufficient arguments\n"
               "usage: ./program start [stop] [step]\n", stderr);
        return 1;
    }
    
    char *endptr;
    float start = strtof (argv[1], &endptr),                         /* validation omitted */ 
          stop = argc > 2 ? strtof (argv[2], &endptr) : -3*PI/2.,
          step = argc > 3 ? strtof (argv[3], &endptr) :  3*PI/2.;
    
    /* rest of code */

注意: 建议使用 doublestrtod() 而不是 float 除非在微控制器上)

如果给出足够的参数,您可以选择设置 stopstep,如果没有,您将使用默认值。

避免在实践中使用 atoi()atof(),它们提供零错误检测并且在发生故障时不提供任何指示。 atof() 会愉快地接受 atof("my cow"); 并在你不知情的情况下默默地返回 0

检查一下,如果您还有其他问题,请告诉我。

您可以先为所有变量设置默认值。然后设置它们不是根据 argc 的相等性,而是根据 > 例如

#include <stdlib.h>
#include <stdio.h>

int main (int argc, char **argv)
{
    float start = -(3*PI)/2;
    float stop (3*PI)/2;
    float step = 0.01;
    
    printf ("# gnuplot data\n"  
            "# x sin(x) cos(x)\n");
            
    if (argc > 1)
        start = atof (argv[1]);
    if (argc > 2)
        stop = atof (argv[2]);
    if (argc > 3)
        step = atof (argv[3]);

    for (float i = start; i <= stop; i += step)
        printf ("%6f\t%6f\t%6f\n", i, sin (i), cos (i));
    return 0; 
}

如前所述,floatatof 的使用还有很多不足之处,但这是另一个问题。