【问题标题】:Casting issues using argument input from C使用来自 C 的参数输入的转换问题
【发布时间】:2015-05-27 18:24:21
【问题描述】:

我正在尝试编写一个 C 程序,其中用户必须在命令行中输入两个参数。首先,它们必须提供要读取的值的文本文件的名称。其次,它们必须提供 0 或 1 的值,该值将保存为整数以用作布尔值(0=false,1=true)。

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

int main(int argc, char *argv[]){
   FILE *f;
   char *fname;
   int boolVal;

  if (argc != 2){
    printf("This program requires two input types, data file and boolean value of 0 or 1\n");
    return 1;
  } 

  fmame = argv[1];
  boolVal = argv[2];
  printf("The file name is %s and the boolVal is %d.\n", fmame, boolVal);

   f = fopen(fname, "r");
   if (f == NULL) perror ("Could not open file");
      else {
         if (fgets(myStr, 1000, f) != NULL )
            puts(myStr);
            fclose(f);
      }
   return 0;
}

我收到一个错误:

testArg.c: In function ‘main’:
testArg.c:16: warning: assignment makes integer from pointer without a cast

我有两个问题:我读入的文件名是否正确?二、如何解决铸造问题?

【问题讨论】:

  • 这不是错误,而是警告。
  • 在 C 中,它实际上是对大多数编译器的警告。这是不正确的,但技术上可以在静态级别上做到@danielfranca。
  • @danielfranca,这是违反约束的,编译器必须至少发出警告,但也可能拒绝编译。换句话说,这个警告应该被视为错误。
  • 如果参数数量不正确(应该是 3,而不是 2,因为程序名称是 argv[0]),程序返回 -1 那么为什么程序返回成功指示 (0)无法打开文件?

标签: c string command-line-arguments compiler-warnings strtol


【解决方案1】:

按照您的要求,

用户必须在命令行中输入两个参数。首先,它们必须提供要读取的值的文本文件的名称。其次,它们必须提供 0 或 1 的值,该值将保存为整数以用作布尔值(0=false,1=true)。

你的代码应该是这样的

if (argc != 3)
{  //code

请记住,二进制名称也很重要。所以./&lt;binary&gt; &lt;filename&gt; &lt;1/0&gt; 使argc 成为3

接下来,您的代码中出现警告的原因是为了

boolVal = argv[2];

所有命令行输入都以字符串 [char *] 的形式读取。如果您检查argv[2]的数据类型,您可以轻松理解这一点。不是说char *吗?然后,您需要在将该值分配给int 变量之前,将该(alpha)数字字符串转换 为一个整数 值。

所以,这里需要的是

boolVal = atoi(argv[2]);

或者,甚至更好和推荐,

boolVal = strtol(argv[2], NULL, 0);    

详情请查看strtol() 的手册页。

【讨论】:

  • 为什么不if (argc &gt; 2) { //code 允许稍后添加额外的命令行参数而不重写现有代码?
  • 非常感谢!我想知道我是否还会问...为什么我的代码将文件的第一行打印到控制台中?有什么办法可以抑制它吗?我感觉它发生在 else 语句的一部分中。
  • @JosephHudson 是的,它打印出来是因为你要求它这样做。 :-) 看,如果fgets() 返回成功,puts(string); 将被执行,打印文件的第一行。如果您不想要 o/p,请删除 puts()
【解决方案2】:

您正在分配一个指向 bool 变量的指针。你必须这样做。

boolVal=atoi(argv[2]);

现在它不会抛出任何警告。然后你必须检查不是argc != 3 的条件。否则它会给你一个分段错误。因为argc 将从零开始计数。如果您很简单地给出./a.out,那么argc 计数就是一。

你是这样访问的,argv[2] 所以你必须检查argc != 3

 int atoi(const char *nptr);

atoi 将数组值转换为整数值。来自atoi的手册页

atoi() 函数将 nptr 指向的字符串的初始部分转换为 int。

参考here.

【讨论】:

  • atoi 是做什么的?请在您的帖子中包含该信息。
【解决方案3】:

argv 中传递的字符串参数的值与1 进行比较的一种方法如下:

boolVal = argv[2][0] == '1';

然而,这是一个有效的快捷方式,因为字符串是单个字符长。对于更长的字符串,使用strcmp:

boolVal = strcmp(argv[2], "yes") == 0;

注意:您还应该检查 argc 是否为 3,因为位置为零的强制参数。

【讨论】:

    【解决方案4】:

    这个:

    if (argc != 2){
    

    应该是

    if (argc != 3){
    

    argv[0] 将是您运行的程序的名称,并且您还需要另外两个输入。因此,argc 的检查应该是 3 而不是 2。

    至于警告,是因为这里:

    boolVal = argv[2];
    

    boolValint 类型,而 argv[2]char* 类型。您不能直接分配它们,这就是编译器所抱怨的。使用

    sscanf(argv[2],"%d",&boolVal);
    

    argv[2]中提取一个数字并将其存储在boolVal的地址中。 sscanf 返回成功扫描和分配的项目总数。因此,您还可以使用以下方法检查提取是否成功

    if(sscanf(argv[2],"%d",&boolVal)==1)
        //Extraction successful!
    

    此外,您可以通过使用检查成功提取的数字是1还是0

    if(boolVal !=0 && boolVal !=1)
        //Bad Value
    

    【讨论】:

      【解决方案5】:

      改变这个:

      if (argc != 2)
      

      到这里:

      if (argc != 3 || (argv[2][0] != '0' && argv[2][0] != '1') || argv[2][1] != '\0')
      

      还有这个:

      boolVal = argv[2];
      

      到这里:

      boolVal = argv[2][0]-'0';
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-15
        • 2014-10-26
        • 1970-01-01
        相关资源
        最近更新 更多