Kiểm tra xem một chuỗi có chứa một chuỗi trong C ++


494

Tôi có một loại biến std::string. Tôi muốn kiểm tra nếu nó có chứa một số nhất định std::string. Làm thế nào tôi có thể làm điều đó?

Có một hàm trả về true nếu chuỗi được tìm thấy và false nếu nó không?


6
Bạn có nghĩa là chuỗi char * hoặc chuỗi từ STL?
anthares

1
Đây không phải là một chuỗi char *. Tôi đã phải #include <string> để sử dụng nó.
neuromancer

1
Một số giải pháp đang sử dụng s2 cho chuỗi tôi muốn tìm. Nó vẫn hoạt động nếu tôi sử dụng cái gì đó như "đây là một chuỗi" thay vì s2?
neuromancer

2
Có bởi vì có một hàm tạo chuỗi ký tự chuỗi cho kiểu chuỗi std ::.

18
Ai đó hãy đưa ra một đề nghị để thêm std::basic_string::containsvào stdlib.
emlai

Câu trả lời:


722

Sử dụng std::string::findnhư sau:

if (s1.find(s2) != std::string::npos) {
    std::cout << "found!" << '\n';
}

Lưu ý: "tìm thấy!" sẽ được in nếu s2là một chuỗi con của s1cả hai s1s2là loại std::string.


117

Bạn có thể thử sử dụng findchức năng:

string str ("There are two needles in this haystack.");
string str2 ("needle");

if (str.find(str2) != string::npos) {
//.. found.
} 

27

Trên thực tế, bạn có thể thử sử dụng thư viện boost, tôi nghĩ rằng std :: string không cung cấp đủ phương thức để thực hiện tất cả các hoạt động chuỗi phổ biến. Trong boost, bạn chỉ có thể sử dụng boost::algorithm::contains:

#include <string>
#include <boost/algorithm/string.hpp>

int main() {
    std::string s("gengjiawen");
    std::string t("geng");
    bool b = boost::algorithm::contains(s, t);
    std::cout << b << std::endl;
    return 0;
}

33
"Tôi nghĩ rằng std :: string không cung cấp đủ phương thức để thực hiện tất cả các hoạt động chuỗi chung". Nhưng có một findphương pháp cho chính xác nhiệm vụ được đề cập. Không cần phải giới thiệu một phụ thuộc thư viện.
stefan

8
@stefan, bạn nói đúng, có một phương thức tìm, nhưng về việc phân chia, thay thế và nhiều nhân viên khác. Bạn có thể so sánh std :: chuỗi với chuỗi api trong Java.PS: Ngoài ra tôi nghĩ có chứa thanh lịch hơn nhiều so với tìm để kiểm tra nếu một chuỗi chứa một chuỗi khác.
Geng Jiawen

1
Ngoài ra điều này là ngắn, và dễ nhớ hơn. Cpp 17 có thêm hỗ trợ cho hệ thống tập tin. Tôi hy vọng Cpp 2x sẽ làm một cái gì đó cho chuỗi. Thật đau đớn khi thiếu hỗ trợ phương thức chuỗi cơ bản trong cpp hiện đại.
Geng Jiawen

1
Bạn có thực sự cần "sử dụng"? Khi tôi đọc mã này, tôi không biết liệu containsstd::containshay không boost::contains, có vẻ như là một nhược điểm đáng kể. Tôi đoán std :: chứa hiện không tồn tại, nhưng tôi không chắc là hợp lý khi cho rằng người đọc đã ghi nhớ mọi thứ trong std. Và std::containsrất có thể tồn tại trong một số phiên bản tương lai của c ++, sẽ phá vỡ chương trình này.
Don nở

12

Bạn có thể thử cái này

string s1 = "Hello";
string s2 = "el";
if(strstr(s1.c_str(),s2.c_str()))
{
   cout << " S1 Contains S2";
}

4

Trong trường hợp nếu chức năng là quan trọng đối với hệ thống của bạn, thì thực sự có lợi khi sử dụng một strstrphương pháp cũ . Các std::searchphương pháp trong phạm vi algorithmlà có thể chậm nhất. Tôi đoán là sẽ mất rất nhiều thời gian để tạo ra các vòng lặp đó.

Mã mà tôi đã sử dụng để tính toàn bộ thời gian là

#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <random>
#include <chrono>

std::string randomString( size_t len );

int main(int argc, char* argv[])
{
        using namespace std::chrono;

        const size_t haystacksCount = 200000;
        std::string haystacks[haystacksCount];
        std::string needle = "hello";

        bool sink = true;

        high_resolution_clock::time_point start, end;
        duration<double> timespan;

        int sizes[10] = { 10, 20, 40, 80, 160, 320, 640, 1280, 5120, 10240 };

        for(int s=0; s<10; ++s)
        {
                std::cout << std::endl << "Generating " << haystacksCount << " random haystacks of size " << sizes[s] << std::endl;
                for(size_t i=0; i<haystacksCount; ++i)
                {
                        haystacks[i] = randomString(sizes[s]);
                }

                std::cout << "Starting std::string.find approach" << std::endl;
                start = high_resolution_clock::now();
                for(size_t i=0; i<haystacksCount; ++i)
                {
                        if(haystacks[i].find(needle) != std::string::npos)
                        {
                                sink = !sink; // useless action
                        }
                }
                end = high_resolution_clock::now();
                timespan = duration_cast<duration<double>>(end-start);
                std::cout << "Processing of " << haystacksCount << " elements took " << timespan.count() << " seconds." << std::endl;

                std::cout << "Starting strstr approach" << std::endl;
                start = high_resolution_clock::now();
                for(size_t i=0; i<haystacksCount; ++i)
                {
                        if(strstr(haystacks[i].c_str(), needle.c_str()))
                        {
                                sink = !sink; // useless action
                        }
                }
                end = high_resolution_clock::now();
                timespan = duration_cast<duration<double>>(end-start);
                std::cout << "Processing of " << haystacksCount << " elements took " << timespan.count() << " seconds." << std::endl;

                std::cout << "Starting std::search approach" << std::endl;
                start = high_resolution_clock::now();
                for(size_t i=0; i<haystacksCount; ++i)
                {
                        if(std::search(haystacks[i].begin(), haystacks[i].end(), needle.begin(), needle.end()) != haystacks[i].end())
                        {
                                sink = !sink; // useless action
                        }
                }
                end = high_resolution_clock::now();
                timespan = duration_cast<duration<double>>(end-start);
                std::cout << "Processing of " << haystacksCount << " elements took " << timespan.count() << " seconds." << std::endl;
        }

        return 0;
}

std::string randomString( size_t len)
{
        static const char charset[] = "abcdefghijklmnopqrstuvwxyz";
        static const int charsetLen = sizeof(charset) - 1;
        static std::default_random_engine rng(std::random_device{}());
        static std::uniform_int_distribution<> dist(0, charsetLen);
        auto randChar = [charset, &dist, &rng]() -> char
        {
                return charset[ dist(rng) ];
        };

        std::string result(len, 0);
        std::generate_n(result.begin(), len, randChar);
        return result;
}

Ở đây tôi tạo ngẫu nhiên haystacksvà tìm kiếm trong đó needle. Số lượng đống cỏ khô được thiết lập, nhưng độ dài của chuỗi trong mỗi đống cỏ khô được tăng từ 10 vào đầu đến 10240 ở cuối. Hầu hết thời gian chương trình dành thực sự tạo ra các chuỗi ngẫu nhiên, nhưng đó là điều được mong đợi.

Đầu ra là:

Generating 200000 random haystacks of size 10
Starting std::string.find approach
Processing of 200000 elements took 0.00358503 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0022727 seconds.
Starting std::search approach
Processing of 200000 elements took 0.0346258 seconds.

Generating 200000 random haystacks of size 20
Starting std::string.find approach
Processing of 200000 elements took 0.00480959 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00236199 seconds.
Starting std::search approach
Processing of 200000 elements took 0.0586416 seconds.

Generating 200000 random haystacks of size 40
Starting std::string.find approach
Processing of 200000 elements took 0.0082571 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00341435 seconds.
Starting std::search approach
Processing of 200000 elements took 0.0952996 seconds.

Generating 200000 random haystacks of size 80
Starting std::string.find approach
Processing of 200000 elements took 0.0148288 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00399263 seconds.
Starting std::search approach
Processing of 200000 elements took 0.175945 seconds.

Generating 200000 random haystacks of size 160
Starting std::string.find approach
Processing of 200000 elements took 0.0293496 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00504251 seconds.
Starting std::search approach
Processing of 200000 elements took 0.343452 seconds.

Generating 200000 random haystacks of size 320
Starting std::string.find approach
Processing of 200000 elements took 0.0522893 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00850485 seconds.
Starting std::search approach
Processing of 200000 elements took 0.64133 seconds.

Generating 200000 random haystacks of size 640
Starting std::string.find approach
Processing of 200000 elements took 0.102082 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00925799 seconds.
Starting std::search approach
Processing of 200000 elements took 1.26321 seconds.

Generating 200000 random haystacks of size 1280
Starting std::string.find approach
Processing of 200000 elements took 0.208057 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0105039 seconds.
Starting std::search approach
Processing of 200000 elements took 2.57404 seconds.

Generating 200000 random haystacks of size 5120
Starting std::string.find approach
Processing of 200000 elements took 0.798496 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0137969 seconds.
Starting std::search approach
Processing of 200000 elements took 10.3573 seconds.

Generating 200000 random haystacks of size 10240
Starting std::string.find approach
Processing of 200000 elements took 1.58171 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0143111 seconds.
Starting std::search approach
Processing of 200000 elements took 20.4163 seconds.

Phiên bản ngắn hơn của câu trả lời là: sử dụng c thay vì c ++ :)
r0ng

3

Nếu bạn không muốn sử dụng các chức năng thư viện tiêu chuẩn, dưới đây là một giải pháp.

#include <iostream>
#include <string>

bool CheckSubstring(std::string firstString, std::string secondString){
    if(secondString.size() > firstString.size())
        return false;

    for (int i = 0; i < firstString.size(); i++){
        int j = 0;
        // If the first characters match
        if(firstString[i] == secondString[j]){
            int k = i;
            while (firstString[i] == secondString[j] && j < secondString.size()){
                j++;
                i++;
            }
            if (j == secondString.size())
                return true;
            else // Re-initialize i to its original value
                i = k;
        }
    }
    return false;
}

int main(){
    std::string firstString, secondString;

    std::cout << "Enter first string:";
    std::getline(std::cin, firstString);

    std::cout << "Enter second string:";
    std::getline(std::cin, secondString);

    if(CheckSubstring(firstString, secondString))
        std::cout << "Second string is a substring of the frist string.\n";
    else
        std::cout << "Second string is not a substring of the first string.\n";

    return 0;
}

6
Bạn đã sử dụng std :: string, do đó mã của bạn đã phụ thuộc vào std lib. Tôi rly không thấy bất kỳ lý do tại sao để tránh giải pháp được chấp nhận bằng cách sử dụng std :: string :: find.
b00n12

Vâng, đó là một điểm tốt. Tôi đã không nghĩ rằng khi tôi viết điều này. Tôi đoán những gì tôi nghĩ khi tôi viết điều này có lẽ là làm thế nào để tránh sử dụng std :: find.
tra123

3
Chỉ dành cho khách truy cập trong tương lai: Thuật toán này không thực sự chính xác. Bởi vì "i" không bao giờ quay trở lại sau khi kết hợp chuỗi con không thành công, một số trường hợp không khớp, ví dụ: hãy xem xét: aaabc, aab
sAm_vdP

1
Điều này có một số lỗi. CheckSubstring(std::string firstString, std::string secondString)các bản sao sâu cả hai chuỗi được truyền cho hàm, rất tốn kém, đặc biệt đối với các chuỗi dài hơn đòi hỏi phải phân bổ heap. Hơn nữa, nói rằng bạn gọi CheckSubstring("XYZab", "ab\0\0")- các whilevòng lặp sẽ kết thúc so sánh avới a, bđể b, các NUL ngầm ở phần cuối của chuỗi đầu tiên đến NUL rõ ràng trong lần thứ hai, sau đó nó sẽ đọc ngoài đệm chuỗi đầu tiên, có hành vi không xác định. Để sửa lỗi, hãy sử dụng for (... i <= firstString.size () - secondString (). Size (); ...) `.
Tony Delroy

1

Nếu kích thước của chuỗi tương đối lớn (hàng trăm byte trở lên) và c ++ 17 có sẵn, bạn có thể muốn sử dụng trình tìm kiếm Boyer-Moore-Horspool (ví dụ từ cppreference.com):

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

int main()
{
    std::string in = "Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
                     " sed do eiusmod tempor incididunt ut labore et dolore magna aliqua";
    std::string needle = "pisci";
    auto it = std::search(in.begin(), in.end(),
                   std::boyer_moore_searcher(
                       needle.begin(), needle.end()));
    if(it != in.end())
        std::cout << "The string " << needle << " found at offset "
                  << it - in.begin() << '\n';
    else
        std::cout << "The string " << needle << " not found\n";
}

3
Những dấu hiệu của thời đại. Ngày xưa ai đó sẽ cung cấp một chức năng bool contains(const std::string& haystack, const std::string& needle). Ngày nay, họ cung cấp một bộ các mảnh ghép được đặt theo tên của một số tác giả khó hiểu của các bài báo tối nghĩa để làm cho nó trông giống khoa học máy tính hơn ...
BitTickler

0

Bạn cũng có thể sử dụng không gian tên hệ thống. Sau đó, bạn có thể sử dụng phương thức chứa.

#include <iostream>
using namespace System;

int main(){
    String ^ wholeString = "My name is Malindu";

    if(wholeString->ToLower()->Contains("malindu")){
        std::cout<<"Found";
    }
    else{
        std::cout<<"Not Found";
    }
}

Câu trả lời này chỉ áp dụng cho phần mở rộng C ++ độc quyền của Microsoft hoặc C ++ / CX hoặc C ++ / CLI
H. Al-Amri

1
vâng, tôi xin lỗi, tôi không biết nó chỉ hoạt động theo cách đó cho đến một ngày nào đó sau khi tôi đăng nó.
Malindu Dilanka

-1

Đây là một chức năng đơn giản

bool find(string line, string sWord)
{
    bool flag = false;
    int index = 0, i, helper = 0;
    for (i = 0; i < line.size(); i++)
    {
        if (sWord.at(index) == line.at(i))
        {
            if (flag == false)
            {
                flag = true;
                helper = i;
            }
            index++;
        }
        else
        {
            flag = false;
            index = 0;
        }
        if (index == sWord.size())
        {
            break;
        }
    }
    if ((i+1-helper) == index)
    {
        return true;
    }
    return false;
}

4
Xin chào, chào mừng đến với SO. Bạn có thể vui lòng chỉnh sửa câu trả lời của bạn và thêm một bình luận về cách nó hoạt động và nó khác với các câu trả lời khác như thế nào? Cảm ơn bạn!
Fabio nói Phục hồi Monica

-1
#include <algorithm>        // std::search
#include <string>
using std::search; using std::count; using std::string;

int main() {
    string mystring = "The needle in the haystack";
    string str = "needle";
    string::const_iterator it;
    it = search(mystring.begin(), mystring.end(), 
                str.begin(), str.end()) != mystring.end();

    // if string is found... returns iterator to str's first element in mystring
    // if string is not found... returns iterator to mystring.end()

if (it != mystring.end())
    // string is found
else
    // not found

return 0;
}

11
Hãy cố gắng tránh việc chỉ bán mã như một câu trả lời và cố gắng giải thích những gì nó làm và tại sao. Mã của bạn có thể không rõ ràng đối với những người không có kinh nghiệm mã hóa có liên quan. Vui lòng chỉnh sửa câu trả lời của bạn để bao gồm làm rõ, bối cảnh và cố gắng đề cập đến bất kỳ giới hạn, giả định hoặc đơn giản hóa trong câu trả lời của bạn.
Sᴀᴍ Onᴇᴌᴀ

Cảm ơn đã làm cho mã rõ ràng, vì chỉ sử dụng usingcác chức năng cần thiết và không bỏ toàn bộ không gian tên vào không gian toàn cầu. Đối với nhận xét @ SᴀᴍOnᴇᴌᴀ, tôi đoán rằng người dùng đã không đọc các nhận xét trong mã của bạn.
v010dya

-2

Từ rất nhiều câu trả lời trong trang web này, tôi đã không tìm ra câu trả lời rõ ràng nên trong 5-10 phút tôi đã tự mình tìm ra câu trả lời. Nhưng điều này có thể được thực hiện trong hai trường hợp:

  1. Hoặc bạn BIẾT vị trí của chuỗi con bạn tìm kiếm trong chuỗi
  2. Hoặc bạn không biết vị trí và tìm kiếm nó, char bởi char ...

Vì vậy, chúng ta hãy giả sử chúng ta tìm kiếm các chuỗi con "cd" trong chuỗi "abcde", và chúng ta sử dụng đơn giản nhất substr tích hợp chức năng trong C ++

Cho 1:

#include <iostream>
#include <string>

    using namespace std;
int i;

int main()
{
    string a = "abcde";
    string b = a.substr(2,2);    // 2 will be c. Why? because we start counting from 0 in a string, not from 1.

    cout << "substring of a is: " << b << endl;
    return 0;
}

dành cho 2:

#include <iostream>
#include <string>

using namespace std;
int i;

int main()
{
    string a = "abcde";

    for (i=0;i<a.length(); i++)
    {
        if (a.substr(i,2) == "cd")
        {
        cout << "substring of a is: " << a.substr(i,2) << endl;    // i will iterate from 0 to 5 and will display the substring only when the condition is fullfilled 
        }
    }
    return 0;
}

2
Câu trả lời hàng đầu ("sử dụng std :: string :: find") theo cách nào, được đăng 8 năm trước, không đủ rõ ràng?
Steve Smith

-3

Chúng ta có thể sử dụng phương pháp này thay thế. Chỉ là một ví dụ từ các dự án của tôi. Tham khảo mã. Một số tính năng bổ sung cũng được bao gồm.

Nhìn vào câu lệnh if!

/*
Every C++ program should have an entry point. Usually, this is the main function.
Every C++ Statement ends with a ';' (semi-colon)
But, pre-processor statements do not have ';'s at end.
Also, every console program can be ended using "cin.get();" statement, so that the console won't exit instantly.
*/

#include <string>
#include <bits/stdc++.h> //Can Use instead of iostream. Also should be included to use the transform function.

using namespace std;
int main(){ //The main function. This runs first in every program.

    string input;

    while(input!="exit"){
        cin>>input;
        transform(input.begin(),input.end(),input.begin(),::tolower); //Converts to lowercase.

        if(input.find("name") != std::string::npos){ //Gets a boolean value regarding the availability of the said text.
            cout<<"My Name is AI \n";
        }

        if(input.find("age") != std::string::npos){
            cout<<"My Age is 2 minutes \n";
        }
    }

}

Tôi xin lỗi, tôi không thấy ai đó đã đăng điều tương tự tôi đã làm trước đây.
Malindu Dilanka

1
"Theo dõi tôi trên YouTube" có thể được coi là thư rác. Hãy ghi nhớ điều đó trong tương lai. Ngoài ra, hãy đọc Cách trả lờilàm thế nào để không trở thành người gửi thư rác
Zoe
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.