【问题标题】:Command Line Argument Counting命令行参数计数
【发布时间】:2012-03-06 02:06:54
【问题描述】:

这是一个简单的 C 程序,它打印传递给它的命令行参数的数量:

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("%d\n", argc);
}

当我给出输入时

file_name *

它在我的电脑(操作系统 Windows 7)中打印 623 而不是 2。但它在其他情况下给出了正确的输出。 * 是命令行参数的保留字符吗? 请注意,此程序为以下输入提供正确的输出:

file_name *Rafi

输出 = 2

【问题讨论】:

  • @pmg:我已经修改了问题,所以“file_name”是一个词而不是两个词……这可能是 Rafi 的意图。如果没有,他会重新编辑,我们可以再次对 2 vs 3 提出质疑。
  • Microsoft 的 C/C++ 编译器 (cl.exe) 将在您的两个示例中打印 2。您使用的是不同的编译器吗?
  • 是的.. 你是对的 :) @Jonathan

标签: c command-line-arguments


【解决方案1】:

在 Unix 命令行上,shell 负责处理通配符。 yourapp * 将运行 yourapp,并将当前目录中所有非隐藏文件的名称作为参数传递。在您的情况下,这是 622 个文件(623 = 622 个文件 + 程序名称)。

在Windows上,应用程序负责通配符解析,所以argc为2,1为程序名(argv[0]),1为通配符(argv[1] = *);

【讨论】:

  • 谢谢 :) 我在想 623 只不过是一个错误 :)
  • @Brian:这不是“错误”,只是不同。 Windows 的风格使 ren *.jpg *.jpeg 之类的事情成为可能,而在 unix 系统上这很困难。
  • "for f in *.jpg; do mv $f echo $f | cut -d'.' -f1.jpeg; done" 有什么难的,除了当有多个 "." 时它不起作用。字符文件名? (实际上这是一个很好的例子,说明 Window 的方式也有优势)。
  • @William:是的,这很方便,但这是一个 perl 脚本,而不是 shell。对于 shell-only,for 循环是复制 windows 在单个命令中所做的唯一实用方法。
  • @MarcB:在 Windows 上,REN 是一个“命令”,不是吗?因此,在 Unix 上执行命令只需将名称用引号括起来:/usr/bin/ren '*.jpg' '*.jpeg' 可以写出来,可以做人们想做的事 - 但我同意这不是 The Unix Way™,人们忘记引号有时会被混淆和/或混乱(除非ren 命令被编写为拒绝两个以上的用户参数(argc > 3),或者当两个参数不都包含单个* 元字符时拒绝它) .
【解决方案2】:

* 被 shell 或运行时库扩展(前者在 *nixes 上,后者在 Windowses 上),而不是文字 * 你得到当前工作目录中所有文件的名称。

【讨论】:

    【解决方案3】:

    正如其他人所提到的,您将获得“shell 通配符扩展”或“通配符”,其中 * 用作通配符以匹配文件名以放置在 argv 数组中。

    在 Unix 系统上,这是由 shell 执行的,与 C 运行时无关(或很少)。

    在 Windows 系统上,此功能不是由 shell 执行的(除非您正在使用类似 Unix 的 shell 替代品,如 Cygwin)。 C 运行时的初始化可能会也可能不会执行通配功能,具体取决于您使用的工具和/或链接器选项:

    • 如果您使用 Microsoft 的编译器,默认情况下 C 运行时不会执行 glob,在您的示例中您将获得 2 的 argc 值。但是,如果您要求链接器链接到setargv.obj(或wsetargv.obj,如果您有Unicode 构建),则将通配添加到运行时初始化中,您将获得类似于Unix 的行为。从我记事起,setargv.obj 就已经随 MSVC 一起分发了,但它仍然鲜为人知。我相信大多数 Windows 程序都会执行自己的通配符扩展。

    • 如果您使用的是 MinGW/GCC 工具链,C 运行时将在调用 main() 之前执行 globbing(至少对于 MinGW 4.6.1 是这样 - 我怀疑它在 MinGW 中已经存在很长时间了)。我认为 MinGW 可能不会为 GUI 程序执行 globbing。您可以使用以下方法之一禁用 MinGW 的通配行为:

      1. 定义一个名为_CRT_glob的全局变量并将其初始化为0

        int _CRT_glob = 0;
        
      2. lib/CRT_noglob.o 目标文件中的链接(我认为这可能取决于顺序 - 您可能需要将它放在任何库之前):

        gcc c:/mingw/lib/CRT_noglob.o main.o -o main.exe
        

    【讨论】:

    • 一条很棒的信息w.r.t。 setargv.obj,非常有帮助,谢谢!
    【解决方案4】:

    问题在于,shell 将* 扩展为当前目录中的所有文件名(不以. 开头)。这都是关于 shell 的,与 C 程序几乎没有关系。

    argc 的值包括 1 代表程序自己的名称,加上一个代表 shell 传递的每个参数。

    试试:

    filename *
    filename '*'
    

    第一个会给你 623(给予或接受 - 但现在是你清理该目录的时候了!)。第二个会给你 2。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-25
      • 1970-01-01
      • 2012-10-04
      • 2011-02-25
      • 2013-02-14
      相关资源
      最近更新 更多