【问题标题】:C++ Compare char array with stringC++比较char数组和字符串
【发布时间】:2021-12-06 08:15:09
【问题描述】:

我正在尝试将字符数组与这样的字符串进行比较:

const char *var1 = " ";
var1 = getenv("myEnvVar");

if(var1 == "dev")
{
   // do stuff
}

这个 if 语句永远不会验证为真......当我输出 var1 它是“dev”时,我在想它可能与一个以 null 结尾的字符串有关,但是“dev”的 strlen 和 var1 是相等的。 ..我还认为 var1 == "dev" 可能是在将 "dev" 与 var1 的内存位置而不是值进行比较。 *var1 == "dev" 导致错误....尝试了很多方法,对于精明的 c++ 开发人员来说可能是一个简单的解决方案(我很久没有编写 c++ 代码了)。

编辑: 我们已经尝试过

if(strcmp(var1, "dev") == 0)

if(strncmp(var1, "dev", 3) == 0)

谢谢

编辑:在家测试后,我只是建议我的同事将数据类型更改为字符串。我相信他正在将一个大尺寸的 char 数组与一个字符串进行比较。我编写了一个输出 sizeof、strlen 等的程序来帮助我们完成它。感谢大家的帮助。

【问题讨论】:

  • 看起来您使用的是原始 C 字符串,而不是 C++ String 类。
  • 尝试使用调试器查看 var1 是否实际填充了“dev1”。此外,如果 var1 实际上是 C++ 样式字符串,请使用 c_str() 函数获取可以使用 strcmp() 与您的 char* 进行比较的 c 样式字符串;
  • 你试过 strcmp;太好了——结果如何? (因为这是一个好方法)

标签: c++ string string-comparison


【解决方案1】:

使用strcmp()比较字符串的内容:

if (strcmp(var1, "dev") == 0) {
}

说明:在 C 语言中,字符串是指向包含字节的内存位置的指针。使用相等运算符比较 char*char* 不会按预期工作,因为您正在比较字符串的 内存位置 而不是它们的字节内容。诸如strcmp() 之类的函数将遍历两个字符串,检查它们的字节以查看它们是否相等。 strcmp() 如果相等则返回 0,如果不同则返回非零值。详情请见manpage

【讨论】:

  • @Chris:你能发布一个你如何使用strcmp()的例子吗?否则,我们将不知道它是如何“不起作用”的。
  • 你确定你没有做 if(strcmp(var1, "dev")) 吗?使用 strcmp 容易陷入的陷阱...
  • @chris 另外,var1 是否以空值结尾? (即代码示例是否 100% 准确,或者您是否使用以空字符结尾的 "" 字符串进行快速解释)
  • 我是这个项目的关注者,我的工作系统上没有要测试的 c++,所以我回家后会测试并发布我发现的内容。
【解决方案2】:

您没有使用字符串。您正在使用指针。 var1 是一个字符指针 (const char*)。它不是一个字符串。如果它是以 null 结尾的,那么某些 C 函数会将其视为字符串,但它基本上只是一个指针。

因此,当您将其与 char 数组进行比较时,该数组也会衰减为指针,然后编译器会尝试查找 operator == (const char*, const char*)

这样的运营商确实存在。它需要两个指针,如果它们指向相同的地址,则返回 true。所以编译器调用它,你的代码就会中断。

如果你想进行字符串比较,你必须告诉编译器你想处理字符串,而不是指针

这样做的C方式是使用strcmp函数:

strcmp(var1, "dev");

如果两个字符串相等,这将返回零。 (如果左边按字典顺序大于右边,则返回大于零的值,否则返回小于零的值。)

因此,要比较是否相等,您需要执行以下操作之一:

if (!strcmp(var1, "dev")){...}
if (strcmp(var1, "dev") == 0) {...}

但是,C++ 有一个非常有用的string 类。如果我们使用它,您的代码会变得相当简单。当然,我们可以从两个参数创建字符串,但我们只需要使用其中一个即可:

std::string var1 = getenv("myEnvVar");

if(var1 == "dev")
{
   // do stuff
}

现在编译器遇到字符串和字符指针之间的比较。它可以处理这个问题,因为 char 指针可以隐式转换为字符串,从而产生字符串/字符串比较。并且它们的行为完全符合您的预期。

【讨论】:

  • 这个解释很震撼,并且也建议 std::string !我第一次读了一遍:)
  • 一个有趣的陷阱是字符串折叠,在发布版本中使用 "foo" == "foo" 进行测试可能是真的,因为它们成为指向同一字符串的指针,但调试已关闭字符串折叠它会失败
【解决方案3】:

在此代码中,您不是在比较字符串值,而是在比较指针值。如果要比较字符串值,则需要使用字符串比较函数,例如 strcmp。

if ( 0 == strcmp(var1, "dev")) {
  ..
}

【讨论】:

  • 哦。我讨厌把 0 放在左边(显然是个人意见)。我认为它在右边更直观,因为你正在根据函数测试结果,所以没有分配的机会。
  • 我称之为“尤达编码”(向后是表达式,嗯?)。我更喜欢使用编译选项来捕获意外分配。
  • @Fred 同意你的观点,我不同意。 :)
  • 最大编译器警告级别,警告为错误,不需要 yoda :)
【解决方案4】:

“dev”不是string,而是const char *,如var1。因此,您确实在比较内存地址。由于var1 是一个字符指针,*var1 是一个单个字符(准确地说是指向字符序列的第一个字符)。您无法将 char 与 char 指针进行比较,这就是它不起作用的原因。

因为这被标记为 c++,所以使用 std::string 而不是 char 指针是明智的,这将使 == 按预期工作。 (您只需要使用const std::string var1 而不是const char *var1

【讨论】:

    【解决方案5】:

    有更稳定的功能,也摆脱了字符串折叠。

    // Add to C++ source
    bool string_equal (const char* arg0, const char* arg1)
    {
        /*
         * This function wraps string comparison with string pointers
         * (and also works around 'string folding', as I said).
         * Converts pointers to std::string
         * for make use of string equality operator (==).
         * Parameters use 'const' for prevent possible object corruption.
         */
        std::string var0 = (std::string) arg0;
        std::string var1 = (std::string) arg1;
        if (var0 == var1)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    

    并在标题中添加声明

    // Parameters use 'const' for prevent possible object corruption.
    bool string_equal (const char* arg0, const char* arg1);
    

    对于用法,只需将“string_equal”调用作为 if(或三元)语句/块的条件。

    if (string_equal (var1, "dev"))
    {
        // It is equal, do what needed here.
    }
    else
    {
        // It is not equal, do what needed here (optional).
    }
    

    来源:sinatramultimedia/fl32编解码器(我自己写的)

    【讨论】:

      【解决方案6】:

      你对下面这个程序的看法

      #include <stdio.h>
      #include <string.h>
      
      int main ()
      {
      char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
      int n;
      puts ("Looking for R2 astromech droids...");
      for (n=0 ; n<3 ; n++)
      if (strncmp (str[n],"R2xx",2) == 0)
      {
        printf ("found %s\n",str[n]);
      }
      return 0;
      }
      //outputs:
      //
      //Looking for R2 astromech droids...
      //found R2D2
      //found R2A6
      

      当您应该考虑将某些内容输入到数组中然后使用 strcmp 函数时,例如上面的程序...查看下面的修改程序

      #include <iostream>
      #include<cctype>
      #include <string.h>
      #include <string>
      using namespace std;
      
      int main()
      {
      int Students=2;
      int Projects=3, Avg2=0, Sum2=0, SumT2=0, AvgT2=0, i=0, j=0;
      int Grades[Students][Projects];
      
      for(int j=0; j<=Projects-1; j++){
        for(int i=0; i<=Students; i++) {
       cout <<"Please give grade of student "<< j <<"in project "<< i  <<  ":";
        cin >> Grades[j][i];
      
        }
        Sum2 = Sum2 + Grades[i][j];
           Avg2 = Sum2/Students;
      }
      SumT2 = SumT2 + Avg2;
      AvgT2 = SumT2/Projects;
      cout << "avg is  : " << AvgT2 << " and sum : " << SumT2 << ":";
      return 0;
      }
      

      更改为字符串,除了它只读取 1 个输入并抛出其余输入 可能需要两个 for 循环和两个指针

      #include <cstring>
      #include <iostream>
      #include <string>
      #include <stdio.h>
      using namespace std;
      int main()
      {
      char name[100];
      //string userInput[26];
      int i=0, n=0, m=0;
      cout<<"your name? ";
      cin>>name;
      cout<<"Hello "<<name<< endl;
      
      char *ptr=name;
      for (i = 0; i < 20; i++)
      {
      cout<<i<<" "<<ptr[i]<<" "<<(int)ptr[i]<<endl;
      }   
      int length = 0;
      while(name[length] != '\0')
      {
      length++;
      }
                          for(n=0; n<4; n++)
                      {
                                  if (strncmp(ptr, "snit", 4) == 0)
                                  {
                  cout << "you found the snitch "    <<        ptr[i];
                                  }
                      }
      cout<<name <<"is"<<length<<"chars long";
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-16
        • 1970-01-01
        • 2013-03-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多