对于字符串中的每个字符

294

我该如何在C++中对字符串中的每个字符进行for循环?


11
什么类型的字符串?是C字符串还是std::string - Mysticial
它是从文本文件中读取的,所以我假设使用了std::。 - Jack Wilsdon
4
什么类型的字符?char、Unicode 码点、扩展字形集群? - Philipp
可能是如何迭代字符串并知道索引(当前位置)?的重复问题。不用担心答案中的“索引”部分。 - jww
10个回答

528
  1. Looping through the characters of a std::string, using a range-based for loop (it's from C++11, already supported in recent releases of GCC, clang, and the VC11 beta):

    std::string str = ???;
    for(char& c : str) {
        do_things_with(c);
    }
    
  2. Looping through the characters of a std::string with iterators:

    std::string str = ???;
    for(std::string::iterator it = str.begin(); it != str.end(); ++it) {
        do_things_with(*it);
    }
    
  3. Looping through the characters of a std::string with an old-fashioned for-loop:

    std::string str = ???;
    for(std::string::size_type i = 0; i < str.size(); ++i) {
        do_things_with(str[i]);
    }
    
  4. Looping through the characters of a null-terminated character array:

    char* str = ???;
    for(char* it = str; *it; ++it) {
        do_things_with(*it);
    }
    

5
@Robinson:那是错误的假设,非常错误的假设。此外,“character”有很多不同的含义,最好严格避免使用这个词。 - Puppy
2
好吧,它没有编码,但考虑到utf8现在的普及程度(特别是在网络上),以及一个人可能希望在整个流水线或应用程序中拥有单一一致的编码,为了讨论的基础,我的std :: strings都是utf8:p。 - Robinson
5
@Robinson说:“我的所有数据都被视为无编码,因为我不是在用户界面领域进行编程(也就是说,没有字符串注定要呈现给人类)。如果你想谈论字符编码,你需要讨论一个在std::string之上的更高级别的抽象概念,而std::string只是一系列字节。” - Lightness Races in Orbit
你的 #1 示例中是否可以窥视下一个字符? - Sam Eaton
2
此外,第二和第三种情况是使用“auto”关键字的好例子。 - galois
显示剩余9条评论

40

for循环可以这样实现:

string str("HELLO");
for (int i = 0; i < str.size(); i++){
    cout << str[i];
}

这将逐个打印字符串字符。 str [i] 返回索引为i的字符。
如果它是一个字符数组:
char str[6] = "hello";
for (int i = 0; str[i] != '\0'; i++){
    cout << str[i];
}

基本上,C++ 支持以上两种字符串类型。第二种称为 C 字符串,而第一种称为 std string 或(C++ 字符串)。我建议使用 C++ 字符串,更易于处理。


28

在现代的C++中:

std::string s("Hello world");

for (char & c : s)
{
    std::cout << "One character: " << c << "\n";
    c = '*';
}

在C++98/03中:

for (std::string::iterator it = s.begin(), end = s.end(); it != end; ++it)
{
    std::cout << "One character: " << *it << "\n";
    *it = '*';
}

对于只读迭代,你可以在C++98中使用std::string::const_iterator,在C++11中可以使用for (char const & c : s)或者for (char c : s)


这里有几个支持部分C++11的编译器选项:http://pastebin.com/LBULsn76 - Benjamin Lindley
@BenjaminLindley:谢谢!使用auto总是一个好主意。在使用它时,begin()cbegin()之间的区别变得相关了。 - Kerrek SB
4
在这里,char & c 中的引用角色是什么?它只是允许在需要修改字符值的情况下进行修改吗? - LunaticSoul

17

这里有另一种使用标准算法的方法。

#include <iostream>
#include <string>
#include <algorithm>

int main()
{
   std::string name = "some string";
   std::for_each(name.begin(), name.end(), [] (char c) {
      std::cout << c;
   });
}

1
我们现在是2018年,因此这应该是正确的答案。 - rwst
1
根据需要,也可以使用std::all_ofstd::any_of等函数。en.cppreference.com/w/cpp/algorithm/all_any_none_of - aurelia

8
const char* str = "abcde";
int len = strlen(str);
for (int i = 0; i < len; i++)
{
    char chr = str[i];
    //do something....
}

4
使用strlen作为循环条件是不好的做法,因为它需要对字符串进行O(n)的操作,使整个循环在字符串大小上变为O(n^2)。如果字符串在循环中发生更改,则可以调用循环条件中的strlen,但应将其保留用于实际需要的情况。请注意,这是过时的评论,但仍然可能与问题相关。 - Magnus Hoff
@MagnusHoff:是的,Schlemiel the Painter 算法又出现了。 - Fred Larson
我已经编辑了我的回答。Magnus,你是对的,哎呀,在过去的几年中一直在使用C#中的foreach ;) - demoncodemonkey
然而,仍应该在循环外使用strlen(),而不是在每次迭代中测试null。 - mckenzm

7

我没有看到任何使用基于范围的for循环来处理"C字符串"的示例。

char cs[] = "This is a c string\u0031 \x32 3";

// range based for loop does not print '\n'
for (char& c : cs) {
    printf("%c", c);
}

不相关但是整数数组示例

int ia[] = {1,2,3,4,5,6};

for (int& i : ia) {
    printf("%d", i);
}

2
for (int x = 0; x < yourString.size();x++){
        if (yourString[x] == 'a'){
            //Do Something
        }
        if (yourString[x] == 'b'){
            //Do Something
        }
        if (yourString[x] == 'c'){
            //Do Something
        }
        //...........
    }

字符串基本上是字符数组,因此您可以指定索引来获取字符。如果您不知道索引,则可以像上面的代码一样循环遍历它,但在进行比较时,请确保使用单引号(表示一个字符)。

除此之外,上面的代码是自说明的。


1

对于 C 字符串(char []),你应该这样做:

char mystring[] = "My String";
int size = strlen(mystring);
int i;
for(i = 0; i < size; i++) {
    char c = mystring[i];
}

对于std::string,您可以使用str.size()获取其大小并像示例一样进行迭代,或者可以使用迭代器:

std::string mystring = "My String";
std::string::iterator it;
for(it = mystring.begin(); it != mystring.end(); it++) {
    char c = *it;
}

1
你可以使用size()方法获取字符串的长度,使用方括号运算符访问每个单独字符。
#include<bits/stdc++.h>
using namespace std;

int main()
{
   string s;
   cin >> s;
   int length = s.size();
   for(int i = 0; i < length; i++)
   {
      process(s[i]);
   }
}

0

你可以使用字符串库的at函数来获取字符串中的每个字符,就像我这样做:

string words;
    for (unsigned int i = 0; i < words.length(); i++)
        {
            if (words.at(i) == ' ')
            {
                spacecounter++;    // to count all the spaces in a string
                if (words.at(i + 1) == ' ')
                {
                    i += 1;
                }

这只是我的代码片段,但重点是您可以通过 stringname.at(index) 访问字符。


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