Đối với mỗi ký tự trong chuỗi


229

Làm thế nào tôi có thể thực hiện một vòng lặp for trên mỗi ký tự trong chuỗi trong C ++?


9
Những loại chuỗi? Chuỗi C, hay std::string?
Bí ẩn

Nó được đọc trong một tệp văn bản, vì vậy tôi giả sử std ::
Jack Wilsdon

4
Những loại nhân vật? char, Điểm mã Unicode, cụm grapheme mở rộng?
Philipp

Có thể trùng lặp Làm thế nào tôi có thể lặp qua một chuỗi và cũng biết chỉ mục (vị trí hiện tại)? . Đừng lo lắng về indexphần trong câu trả lời.
jww

Câu trả lời:


417
  1. Xoay quanh các ký tự của a std::string, sử dụng vòng lặp dựa trên phạm vi (từ C ++ 11, đã được hỗ trợ trong các bản phát hành gần đây của GCC, clang và VC11 beta):

    std::string str = ???;
    for(char& c : str) {
        do_things_with(c);
    }
  2. Vòng qua các ký tự của a std::stringvới các vòng lặp:

    std::string str = ???;
    for(std::string::iterator it = str.begin(); it != str.end(); ++it) {
        do_things_with(*it);
    }
  3. Xoay quanh các nhân vật của a std::stringvới một vòng lặp lỗi thời:

    std::string str = ???;
    for(std::string::size_type i = 0; i < str.size(); ++i) {
        do_things_with(str[i]);
    }
  4. Xoay quanh các ký tự của một mảng ký tự kết thúc null:

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

4
@Robinson: Đó là một giả định sai lầm. Một giả định rất sai lầm. Ngoài ra, "ký tự" có rất nhiều ý nghĩa khác nhau, tốt nhất là tuyệt đối tránh thuật ngữ này.
Cún con

6
@Robinson: "std :: chuỗi là UTF8 (giả sử là) " Từ khi nào?!
Các cuộc đua nhẹ nhàng trong quỹ đạo

2
Chà, OK, nó không có mã hóa, tuy nhiên có sự phổ biến của utf8 bây giờ (đặc biệt là trên web) và thực tế là người ta có thể muốn một mã hóa nhất quán trong suốt một đường ống hoặc ứng dụng, để làm cơ sở cho cuộc thảo luận này, chuỗi std :: của tôi đều là utf8: p.
Robinson

4
@Robinson: Và tất cả của tôi được coi là không mã hóa vì tôi không lập trình trong miền hướng tới người dùng (nghĩa là không có chuỗi nào được hiển thị cho con người). Nếu bạn muốn nói về bảng mã ký tự, bạn cần phải nói về một sự trừu tượng cấp cao trên đỉnh std::string , mà chỉ là một loạt các byte.
Các cuộc đua nhẹ nhàng trong quỹ đạo

1
Ngoài ra, trường hợp 2 và 3 là ví dụ điển hình về nơi bạn có thể / nên sử dụng "tự động"
galois

29

Một vòng lặp for có thể được thực hiện như thế này:

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

Điều này sẽ in ký tự chuỗi theo ký tự. str[i]trả về ký tự tại chỉ mục i.

Nếu đó là một mảng ký tự:

char str[6] = "hello";
for (int i = 0; str[i] != '\0'; i++){
    cout << str[i];
}

Về cơ bản trên hai là hai loại chuỗi được hỗ trợ bởi c ++. Chuỗi thứ hai được gọi là chuỗi c và chuỗi thứ nhất được gọi là chuỗi std hoặc (chuỗi c ++). Tôi sẽ đề nghị sử dụng chuỗi c ++, rất dễ xử lý.


24

Trong C ++ hiện đại:

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

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

Trong C ++ 98/03:

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

Đối với phép lặp chỉ đọc, bạn có thể sử dụng std::string::const_iteratortrong C ++ 98 và for (char const & c : s)hoặc chỉ for (char c : s)trong C ++ 11.


Dưới đây là một vài tùy chọn cho trình biên dịch có hỗ trợ một phần C ++ 11: pastebin.com/LBULsn76
Benjamin Lindley

@BenjaminLindley: Cảm ơn! autoluôn luôn là một ý tưởng tốt. Khi sử dụng nó, sự khác biệt giữa begin()cbegin()trở nên có liên quan.
Kerrek SB

2
vai trò của tài liệu tham khảo trong char ở đây ( char & c) là gì? Có phải chỉ để cho phép sửa đổi giá trị ký tự trong trường hợp cần thiết?
LunaticSoul

11

Đây là một cách khác để làm điều đó, sử dụng thuật toán tiêu chuẩn.

#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;
   });
}

Chúng tôi có năm 2018 vì vậy đây sẽ là câu trả lời chính xác.
rwst

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

4
(Nhận xét lỗi thời, có lẽ vẫn phù hợp với OP :) Nó không được coi là hình thức tốt để sử dụng strlentrong điều kiện vòng lặp, vì nó yêu cầu thao tác O (n) trên chuỗi cho mỗi lần lặp, tạo ra toàn bộ vòng lặp O (n ^ 2) trong kích thước của chuỗi. strlentrong điều kiện vòng lặp có thể được gọi nếu chuỗi thay đổi trong vòng lặp, nhưng nên được dành riêng cho các trường hợp thực sự cần thiết .
Magnus Hoff

@MagnusHoff: Yup, Schlemiel Họa sĩ lại lấy cái đầu xấu xí của mình.
Fred Larson

Tôi đã chỉnh sửa câu trả lời của mình. Magnus bạn đã đúng, rất tiếc đã sử dụng foreach trong c # trong vài năm qua;)
demcodemonkey

Tuy nhiên, bạn vẫn nên sử dụng strlen () bên ngoài vòng lặp để ưu tiên kiểm tra null trong mỗi lần lặp.
mckenzm

4

Tôi không thấy bất kỳ ví dụ nào sử dụng phạm vi dựa trên vòng lặp với "chuỗi 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);
}

không liên quan nhưng ví dụ mảng int

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

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

1

Đối với chuỗi C ( char []), bạn nên làm một cái gì đó như thế này:

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

Để std::stringbạn có thể sử dụng str.size()để lấy kích thước của nó và lặp lại như ví dụ hoặc có thể sử dụng một trình vòng lặp:

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

1
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
        }
        //...........
    }

Chuỗi về cơ bản là một mảng các ký tự, do đó bạn có thể chỉ định chỉ mục để lấy ký tự. Nếu bạn không biết chỉ mục, thì bạn có thể lặp qua nó như mã ở trên, nhưng khi bạn thực hiện so sánh, hãy đảm bảo bạn sử dụng dấu ngoặc đơn (chỉ định một ký tự).

Ngoài ra, mã trên là tự giải thích.


-1

bạn có thể lấy mọi char trong một chuỗi bằng cách sử dụng chức năng của thư viện chuỗi, giống như tôi đã làm như thế này

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;
                }

đây chỉ là một đoạn mã của tôi nhưng vấn đề là bạn có thể truy cập các ký tự bằng cách stringname.at(index)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.