在C++中比较字符字面量和std::string

5
我想要比较一个字符字面量和字符串的第一个元素,以检查文件中的注释。为什么使用char?我想将其制作成一个函数,接受一个字符变量作为注释。我不想允许字符串,因为我想将其限制在单个字符长度内。
考虑到这一点,我认为最简单的方法是处理字符并将其传递给std :: string的compare函数。然而,这给我带来了意想不到的结果。
我的代码如下:
#include <string>
#include <iostream>

int main ( int argc, char *argv[] )
{
  std::string my_string = "bob";
  char my_char1 = 'a';
  char my_char2 = 'b';

  std::cout << "STRING : " << my_string.substr(0,1) << std::endl
        << "CHAR : " << my_char1 << std::endl;
  if (my_string.substr(0,1).compare(&my_char1)==0)
    std::cout << "WOW!" << std::endl;
  else
    std::cout << "NOPE..." << std::endl;

  std::cout << "STRING : " << my_string.substr(0,1) << std::endl
        << "CHAR : " << my_char2 << std::endl;
  if (my_string.substr(0,1).compare(&my_char2)==0)
    std::cout << "WOW!" << std::endl;
  else
    std::cout << "NOPE..." << std::endl;

  std::cout << "STRING : " << my_string << std::endl
        << "STRING 2 : " << "bob" << std::endl;
  if (my_string.compare("bob")==0)
    std::cout << "WOW!" << std::endl;
  else
    std::cout << "NOPE..." << std::endl;
}

给我...

STRING : b
CHAR : a
NOPE...
STRING : b
CHAR : b
NOPE...
STRING : bob
STRING 2 : bob
WOW!

为什么函数认为子字符串和字符不相同?正确比较字符和std::string变量的最短方法是什么?
(避免重新分类的简短怒斥...请随意跳过)当我说最短时,我的意思是出于对编码优雅的渴望。请注意,这不是一个作业问题。我是化学工程博士候选人,正在进行独立研究的编码工作。我的最后一个问题被用户msw(还发表了轻蔑的言论)重新分类为“作业”,我认为这是滥用边界。我的代码可能会被其他人重用,但我试图使其易于阅读和可维护。我还有一种奇怪的愿望,在可能的情况下使我的代码尽可能高效。因此,关于效率和优雅性的问题。
5个回答

15

做这个:

  if (my_string.substr(0,1).compare(&my_char2)==0)

不会起作用,因为你是在“欺骗”字符串,让它认为自己得到了指向以空字符结尾的C字符串的指针。这将导致奇怪的效果,甚至可能导致程序崩溃。相反,只需使用正常的相等性比较字符串的第一个字符与my_char:

 if (my_string[0] == my_char)
   // do stuff

5
别忘了在尝试访问my_string[0]之前检查0 < my_string.length() - Roland Illig

4
为什么不直接在字符串上使用索引运算符呢?它会返回一个字符类型。
if (my_string[0] == my_char1)

3
您可以使用字符串的operator[]运算符将其与单个字符进行比较。
// string::operator[]
#include <iostream>
#include <string>
using namespace std;

int main ()
{
    string str ("Test string");
    int i; char c = 't';
    for (i=0; i < str.length(); i++)
    {
        if (c == str[i]) {
            std::cout << "Equal at position i = " << i << std::endl;
        }
    }
    return 0;
}

1

在C++中,字符串是以空字符(null-terminated)结尾的,但字符并不是。因此,通过使用标准的比较方法,您实际上是在检查 "b\0" 是否等于 'b'。

我使用了这个方法,并得到了期望的输出:

if (my_string.substr(0,1).compare( 0, 1, &my_char2, 1)==0 )
    std::cout << "WOW!" << std::endl;
else
    std::cout << "NOPE..." << std::endl;

这段话的意思是从子字符串的位置0开始,使用长度为1,并将其与我的字符引用(长度为1)进行比较。参考资料

1
C++中的字符串并不是以空字符结尾的。在C语言中,它们是以空字符结尾的,因为它们实际上是指向char的指针。 - Draco Ater
@Draco:std::string 不需要以空字符结尾(虽然在0x中正在改变),但C++标准仍有很多地方假定了以空字符结尾的字符数组,包括 std::string 内的许多方法,正如这个问题所说明的那样。 - Dennis Zickefoose

1

前两个调用 compare 的行为完全取决于紧随每个字符地址后的随机内存内容。你正在调用 basic_string::compare(const char*),这里的参数被假定为 C 字符串(以 null 结尾),而不是单个字符。compare() 调用将比较你想要的字符,以及该字符后面的内存中到下一个 0x00 字节为止的所有内容,与手头的 std::string 进行比较。

另一方面,<< 操作符确实有一个适当的重载来接受字符输入,因此你的输出并没有反映出你实际在比较什么。

将 a 和 b 的声明转换为 const char[] a = "a";,然后你将得到你想要的结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接