【问题标题】:Is pointer arithmetic possible with C++ string class?C++ 字符串类可以进行指针运算吗?
【发布时间】:2011-07-05 00:58:30
【问题描述】:

在使用 C 进行了一些编程之后,我决定直接进入 C++。起初,我对字符串类的存在感到满意,并且能够将字符串视为整个单元而不是字符数组。但我很快发现,C 风格的字符串的优点是可以让程序逐个字符地遍历它,使用指针算术,并执行所需的逻辑操作。

我现在发现自己处于需要这样做的情况,但编译器告诉我它无法从类型字符串转换为 C 风格的字符串。所以我想知道,有没有一种方法可以使用指针算术来引用单个字符或将参数作为第一个字符的地址传递给函数,同时仍然使用字符串类而无需创建字符数组或者我只是想把我的蛋糕也吃了吗?

【问题讨论】:

  • 这里有char *string::c_str() const
  • 你可以做 foo = string('hello'); cout
  • 我认为@The共产鸭的评论是 OP 的想法:查看字符串中的单个字符并可能改变它们,c_str() 不允许。您可能想将其发布为答案。

标签: c++ arrays class string pointer-arithmetic


【解决方案1】:

您可以使用&your_string[0] 获取指向字符串中初始字符的指针。您还可以使用your_string.begin() 将迭代器放入字符串中,您几乎可以将其视为指针(取消引用它,对其进行算术运算等)

不过,您最好告诉我们更多关于您想要完成的工作。很有可能有比使用指针更好的方法。

编辑:对于计算字符串中元音的数量之类的事情,您几乎肯定需要使用一种算法——在这种情况下,std::count_if 可能是最合适的:

struct is_vowel {
    bool operator()(char ch) { 
        static const char vowels[] = "aeiouAEIOU";
        return strchr(vowels, ch) != NULL;
    }
};

int vowels = std::count_if(my_string.begin(), my_string.end(), is_vowel());

我们仍在使用begin(),但没有对其进行任何指针(类似)运算。

【讨论】:

  • std::string 内存是否保证 是连续的(就像自 C++03 以来的 std::vector)?
  • @FredOverflow:理论上不会,但它将在 C++0x 中,主要是因为委员会中没有人知道它不连续的一致实现(并且鉴于它将得到保证很快,我无法想象有人现在正在做一个非连续的实现)。
  • 因为我还在学习 C++,所以计算字符串中元音的数量是一个练习。我认为使用 begin() 函数就可以了。感谢您的帮助。
  • 哇,这比我为实现甚至涉及使用非常大的 switch 语句的算法而编写的大约 20 行代码要好得多。但看起来我必须更多地了解迭代器。他们仍然很新,直到我不知道这篇文章。再次感谢。您可能只是让我节省了几天阅读大量 C++ 文献的时间。
【解决方案2】:

可以通过索引、指针和使用迭代器来访问字符串字符。

如果你想使用迭代器,你可以创建一个函数来检查字符串中是否有空格:

bool spacecheck(const string& s)
{
    string::const_iterator iter = s.begin();
    while(iter != s.end()){
        if (isspace(*iter))
            return true;
        else
            ++iter;
    }
}

在函数的开头,我使用 .begin() 函数将一个迭代器初始化到字符串 s 的开头,在本例中返回一个指向字符串中第一个字符的迭代器。在 while 函数中,条件是 iter != s.end()。在这种情况下,end() 在迭代器中返回指向字符串最后一个字符之后的元素。在正文中,(*iter) 是 iter 所指向的值,被发送到函数 isspace(),该函数检查字符是否为空格。如果失败,iter 会递增,这使得 iter 指向字符串的下一个元素。

我自己也在学习 c++,通过写出所有这些东西,它有助于我自己理解一些东西。如果这一切对你来说似乎很简单,我希望我没有冒犯你,我只是想简洁。

我目前正在学习 Accelerated c++,但我对它的推荐还不够高!

【讨论】:

  • 你为什么讨厌 for 循环?使用 for 循环可以更简洁:for (string::const_iterator iter = s.begin(); iter != s.end(); ++iter) { if (isspace(*iter)) return true; }
  • 你是完全正确的蒂姆。我实际上喜欢 for 循环,我不知道为什么我没有在那里使用一个。我想我试图在精神上打破一切。
  • +1 用于迭代器,这实际上是“C++ 方式”。当然,对于这种特定情况,您可能应该使用现有的find(),但它作为示例很有价值。
  • 与问题无关,但请记住将字符转换为unsigned char,然后再将其传递给isspace。即使 char 在实现上签名,将负值(EOF 除外)传递给 isspace 也是无效的。 C++ 引入了两个参数 std::isspace 来避免这种情况,因为它实际上将 char 作为参数,而不是 C 风格的 isspace 所做的,即采用 int ,即 a 的 unsigned char 值字符或 EOF。
  • 不,恰恰相反。它让事情变得容易多了。大多数人只是发布代码并期望您自动理解它,但是对于您的示例,它花费的精力要少得多,特别是非常感谢,我想我会考虑获得 Accelerated C++。
猜你喜欢
  • 2011-04-30
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
  • 1970-01-01
  • 2011-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多