【问题标题】:Equals returning false in c++等于在 C++ 中返回 false
【发布时间】:2019-03-07 12:39:12
【问题描述】:

我对 cpp 还很陌生,我正在尝试做一个项目。它说代码必须以文件名作为参数,并将由以下人员运行:

./main -i filename

我编写了一个 for 循环,它将遍历参数列表以查找“-i”参数,以便确定文件名。但是这一行总是返回 false:

argv[i] == "-i"

下面是我的代码:

#include <string>
#include <iostream>

int main(int argc, char *argv[]) {
    std::string test = argv[0];
    for(int i = 0; i < argc; i++){
        if(argv[i] == "-i"){
            test = argv[i+1];
            break;
        }
    }
    std::cout << test;
    return 1;
}

【问题讨论】:

  • 我了解到您正在编写自己的解析器以用于学习目的。一旦你知道如何去做并且你理解了实现它的路径,看看这里。 gnu.org/software/libc/manual/html_node/…
  • 使用函数 strcmp 而不是 "argv[i] == "-i"",这是你在 C 中比较两个字符串的方式,而在你的代码中,“==”的两边会衰减指向指针。

标签: c++ g++ command-line-arguments


【解决方案1】:
argv[i] == "-i"

在上面的行中,您比较了两个指针:分别为 char*const char*

换句话说,不是比较argv[i]"-i",而是比较两个不太可能指向同一位置的指针。因此,该检查不适用于您的情况。

您可以通过多种方式修复它,例如将"-i" 包装成std::string 以使比较正常工作:

const auto arg = std::string{ "-i" };

for(int i = 0; i < argc; i++){
    if(argv[i] == arg){
        test = argv[i+1];
        break;
    }
}

C++17 开始,您还可以使用 std::string_view:

const std::string_view sv{ "-i" };

for(int i = 0; i < argc; i++){
    if(argv[i] == sv){
        test = argv[i+1];
        break;
    }
}

这是一种更可取的方式,因为它避免了 std::string 创建。

【讨论】:

  • 如果在-i 后面没有文件名的情况下调用代码,你真的应该指出越界错误。可能最好的方法是针对 argc-1 进行测试。
  • 从索引 1 开始也是一个好主意,因为 0 用于程序名称。
  • It compares two pointers so the result is always false.:不正确。指针比较定义明确。指向同一个地址的指针之间的比较是一种合理的操作,这是相当普遍的。 char* 文字和 argv 的成员之间的比较相等的机会几乎为零,但在技术上仍然是合法的结果。有点吹毛求疵,但就是这样¯\_(ツ)_/¯
  • @Cyclic3 这不是挑剔,它是完全正确的:) 但对我来说,有时不清楚答案应该有多详细。可能,我需要编辑答案并提供更详细的解释。
  • 如果您使用的是 C++17,为什么不使用字符串文字而不是声明一个完全不必要的常量呢? if( argv[i] == "-i"sv) ….
【解决方案2】:

您不能使用 == 将指向 char 的指针与字符串文字 (char const*) 进行比较。使用std::strcmp() (&lt;cstring&gt;) 或从中构造一个std::string (&lt;string&gt;) 以使其与使用==char* 相当。

【讨论】:

  • 解决i超出范围的最简单方法是使用i &lt; argc-1作为限制
  • 或使用std::string_view (C++17)。
  • 请注意,argv[argc] 被标准定义为始终有效且为空,因此如果代码定义明确,它可能不是您所期望的。
  • @JonathanCallen 我会引用事实。
【解决方案3】:

试试这个:

#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[]) {
    string test;
    for(int i = 0; i < argc; i++){        
        cout << "\n" << argv[i] << endl;
        if((string)argv[i] == "-i"){
            test = argv[i + 1];
            cout << "test= " << test << endl;
            break;
        }
    }
    cout << test << endl;
    system("pause");
    return 0;
}

【讨论】:

  • 对于一个好的答案,解释你改变了什么以及为什么它解决了问题。除了其他人已经说过的之外,目前还不清楚这有什么。我还 (A) 不建议 C 风格的演员表和 (B) 仔细看看你在哪里索引到 argv[i + 1]。如果-i 是最后一个参数并且您没有费心检查它之后是否有一个可以索引的参数,将会发生什么?没什么好 - 只是未定义的行为(即如果 OP 是 幸运 则崩溃,以及中毒程序)。 编辑:好的,not quite, but still
猜你喜欢
  • 1970-01-01
  • 2012-07-25
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2013-09-21
  • 2021-11-15
相关资源
最近更新 更多