【问题标题】:Convert command line argument to string将命令行参数转换为字符串
【发布时间】:2013-03-11 17:23:36
【问题描述】:

我有一个读取硬编码文件路径的程序,我想让它从命令行读取文件路径。为此,我像这样更改了代码:

#include <iostream>

int main(char *argv[])
{
...
}

但是,argv[1] 以这种方式暴露的变量似乎是指针类型,我需要它作为字符串。我应该怎么做才能将此命令行参数转换为字符串?

【问题讨论】:

  • main 的规范格式是 int main(int argc, char *argv[])。你所拥有的将编译,但它会导致未定义的行为。
  • 我不需要 arg 计数,只需要表示第一个参数的字符串。
  • hmm..std::string s(argv[1]);这是你想做的吗?
  • @theta:没关系;还是不行。
  • “当我在命令行上使用程序时,它会引发错误。” -- 随意更具体一点。

标签: c++


【解决方案1】:

它已经是一个 C 风格的字符串数组了:

#include <iostream>
#include <string>
#include <vector>


int main(int argc, char *argv[]) // Don't forget first integral argument 'argc'
{
  std::string current_exec_name = argv[0]; // Name of the current exec program
  std::vector<std::string> all_args;

  if (argc > 1) {
    all_args.assign(argv + 1, argv + argc);
  }
}

参数argc 是参数计数加上当前执行文件。

【讨论】:

    【解决方案2】:

    无需对此进行投票。如果Benjamin Lindley 将他的单行评论作为答案,那就太酷了,但既然他没有,那就这样吧:

    std::vector&lt;std::string&gt; argList(argv, argv + argc);

    如果您不想包含argv[0],因此您不需要处理可执行文件的位置,只需将指针加一即可:

    std::vector&lt;std::string&gt; argList(argv + 1, argv + argc);

    【讨论】:

      【解决方案3】:

      您可以创建一个std::string

      #include <string>
      #include <vector>
      int main(int argc, char *argv[])
      {
        // check if there is more than one argument and use the second one
        //  (the first argument is the executable)
        if (argc > 1)
        {
          std::string arg1(argv[1]);
          // do stuff with arg1
        }
      
        // Or, copy all arguments into a container of strings
        std::vector<std::string> allArgs(argv, argv + argc);
      }
      

      【讨论】:

        【解决方案4】:

        我不确定这是否 100% 可移植,但操作系统 应该 解析 args 的方式是扫描控制台命令字符串并在每个字符的末尾插入一个 nil-term char令牌,而int main(int,char**) 不使用const char**,所以我们可以从第三个参数(@note 第一个参数是工作目录)开始遍历 args 并向后扫描到 nil -term char 并将其转换为空格,而不是从第二个参数的开头开始并向前扫描到 nil-term char。这是带有测试脚本的函数,如果您确实需要对多个 nil-term char 进行 un-nil-ify,请发表评论,以便我修复它;谢谢。

        #include <cstdio>
        #include <iostream>
        
        using namespace std;
        
        namespace _ {
        /* Converts int main(int,char**) arguments back into a string.
        @return false if there are no args to convert.
        @param arg_count The number of arguments.
        @param args      The arguments. */
        bool ArgsToString(int args_count, char** args) {
          if (args_count <= 1) return false;
          if (args_count == 2) return true;
          for (int i = 2; i < args_count; ++i) {
            char* cursor = args[i];
            while (*cursor) --cursor;
            *cursor = ' ';
          }
          return true;
        }
        }  // namespace _
        
        int main(int args_count, char** args) {
          cout << "\n\nTesting ArgsToString...\n";
        
          if (args_count <= 1) return 1;
          cout << "\nArguments:\n";
          for (int i = 0; i < args_count; ++i) {
            char* arg = args[i];
            printf("\ni:%i\"%s\" 0x%p", i, arg, arg);
          }
          cout << "\n\nContiguous Args:\n";
          char* end = args[args_count - 1];
          while (*end) ++end;
          cout << "\n\nContiguous Args:\n";
          char* cursor = args[0];
          while (cursor != end) {
            char c = *cursor++;
            if (c == 0)
              cout << '`';
            else if (c < ' ')
              cout << '~';
            else
              cout << c;
          }
          cout << "\n\nPrinting argument string...\n";
          _::ArgsToString(args_count, args);
          cout << "\n" << args[1];
          return 0;
        }
        

        【讨论】:

          【解决方案5】:

          这很简单。只需这样做:

          #include <iostream>
          #include <vector>
          #include <string.h>
          
          int main(int argc, char *argv[])
          {
              std::vector<std::string> argList;
              for(int i=0;i<argc;i++)
                  argList.push_back(argv[i]);
              //now you can access argList[n]
          }
          

          @Benjamin Lindley 你是对的。这不是一个好的解决方案。请阅读 juanchopanza 的回答。

          【讨论】:

          • 跳过循环,只使用向量构造函数。 std::vector&lt;std::string&gt; argList(argv, argv + argc);
          • 提取一个字符串的开销很大。
          • @BenjaminLindley 你能解释一下这是什么意思吗?例如,如果我不想包含argv[0],我会在该行中进行哪些更改?我认为这是正在使用的初始化程序,但我不能确定:initializer_list&lt;value_type&gt; il, const allocator_type&amp; alloc = allocator_type()cplusplus.com/reference/vector/vector/vector
          • 好吧,我的同事至少回答了我的具体要求 :) std::vector&lt;std::string&gt; args(argv+1, argv + argc); 我没有意识到第一个参数只是一个指针,所以单个增量会满足所有需要。
          • @BenjaminLindley 你能解释一下这段代码是如何工作的吗?
          【解决方案6】:
          #include <iostream>
          
          std::string commandLineStr= "";
          for (int i=1;i<argc;i++) commandLineStr.append(std::string(argv[i]).append(" "));
          

          【讨论】:

          • 这将无缘无故地创建临时字符串对象。 commandLineStr.append(argv[i]).append(" ") 会更有效率(append 返回*this 以允许这种链接)。另外,默认构造函数会使字符串为空,所以初始化也很浪费。
          【解决方案7】:

          因为打印我放置在变量中的参数的所有尝试都失败了,这里我的 2 个字节用于这个问题:

          std::string dump_name;
          
          (stuff..)
          
          if(argc>2)
          {
              dump_name.assign(argv[2]);
              fprintf(stdout, "ARGUMENT %s", dump_name.c_str());
          }
          

          注意assign的使用,还有c_str()函数调用的需要。

          【讨论】:

            猜你喜欢
            • 2014-12-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-12-19
            • 1970-01-01
            • 2017-12-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多