ตรวจสอบว่าสตริงมีสตริงใน C ++ หรือไม่


493

std::stringฉันมีตัวแปรประเภท std::stringฉันต้องการที่จะตรวจสอบว่ามันมีบางอย่าง ฉันจะทำอย่างไร

มีฟังก์ชั่นที่คืนค่าจริงหากพบสตริงและเท็จถ้าไม่ใช่?


6
คุณหมายถึง char * string หรือสตริงจาก STL หรือไม่
anthares

1
ไม่ใช่สตริง * ฉันต้องรวม <string> เพื่อใช้งาน
ประสาทวิทยา

1
โซลูชันบางตัวใช้ s2 สำหรับสตริงที่ฉันต้องการค้นหา มันจะยังใช้งานได้ไหมถ้าฉันใช้บางอย่างเช่น "นี่คือสตริง" แทนที่จะเป็น s2
ประสาทวิทยา

2
ใช่เพราะมีคอนสตรัคลิตรลิตรสำหรับ std :: type type

18
มีคนโปรดทำข้อเสนอเพื่อเพิ่มลงstd::basic_string::containsใน stdlib
emlai

คำตอบ:


722

ใช้std::string::findดังต่อไปนี้:

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

หมายเหตุ: "พบ!" จะถูกพิมพ์ถ้าs2เป็นย่อยของs1ทั้งสองs1และเป็นประเภทs2std::string


117

คุณสามารถลองใช้findฟังก์ชั่น:

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

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

27

ที่จริงแล้วคุณสามารถลองใช้ห้องสมุดเพิ่มผมคิดว่า std :: string ไม่ได้ให้วิธีการที่เพียงพอในการดำเนินการกับสตริงทั้งหมดในการเพิ่มคุณเพียงแค่ใช้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
"ฉันคิดว่า std :: string ไม่ได้ให้วิธีการที่เพียงพอในการดำเนินการกับสตริงทั่วไป" แต่มีfindวิธีการสำหรับงานที่เป็นปัญหา ไม่จำเป็นต้องแนะนำการพึ่งพาไลบรารี
ฟาน

8
@ สตีฟคุณพูดถูกมีวิธีการค้นหา แต่สิ่งที่เกี่ยวกับการแยกเปลี่ยนและพนักงานอื่น ๆ อีกมากมายคุณสามารถเปรียบเทียบ std :: string กับ API api ใน Java.PS: ฉันคิดว่ามันมีความสวยงามมากกว่า ค้นหาเพื่อตรวจสอบว่าสตริงมีสตริงอื่น
เกิง Jiawen

1
นอกจากนี้ยังสั้นและง่ายต่อการจำ Cpp 17 ได้เพิ่มการรองรับระบบไฟล์ ฉันหวังว่า Cpp 2x จะทำบางสิ่งบางอย่างสำหรับสตริงเช่นกัน มันเจ็บปวดมากขาดการสนับสนุนวิธีสตริงพื้นฐานใน cpp ที่ทันสมัย
เกิง Jiawen

1
คุณต้องการ "การใช้งาน" จริง ๆ หรือไม่? เมื่อฉันอ่านรหัสนี้ฉันไม่รู้ว่าจะcontainsเป็นstd::containsหรือboost::containsไม่ ฉันเดาว่า std :: contain ไม่มีอยู่ในขณะนี้ แต่ฉันไม่แน่ใจว่ามีเหตุผลที่ผู้อ่านจะจดจำทุกสิ่งที่อยู่ใน std และstd::containsอาจมีอยู่ใน c ++ รุ่นต่อไปในอนาคตซึ่งจะทำให้โปรแกรมนี้พัง
Don Hatch

12

คุณสามารถลองสิ่งนี้

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

4

ในกรณีที่ฟังก์ชันการทำงานมีความสำคัญต่อระบบของคุณจริง ๆ แล้วมันมีประโยชน์ในการใช้strstrวิธีการแบบเก่า std::searchวิธีภายในalgorithmเป็นไปได้ช้าที่สุด ฉันเดาว่าจะใช้เวลานานในการสร้างตัววนซ้ำเหล่านั้น

รหัสที่ฉันใช้ในเวลาทั้งหมดคือ

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

นี่ฉันสร้างแบบสุ่มและการค้นหาในพวกเขาhaystacks needleจำนวนของกองหญ้าถูกตั้งค่าไว้ แต่ความยาวของสตริงภายในแต่ละกองหญ้าจะเพิ่มขึ้นจาก 10 ในตอนเริ่มต้นเป็น 10240 ในตอนท้าย ส่วนใหญ่เวลาที่โปรแกรมใช้จริงสร้างสตริงสุ่ม แต่ที่คาดว่าจะได้

ผลลัพธ์คือ:

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.

คำตอบที่สั้นกว่าคือ: ใช้ c แทน c ++ :)
r0ng

3

หากคุณไม่ต้องการใช้ฟังก์ชันไลบรารีมาตรฐานด้านล่างเป็นโซลูชันเดียว

#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
คุณใช้ std :: string อยู่แล้วดังนั้นโค้ดของคุณขึ้นอยู่กับ std lib แล้ว ฉันไม่เห็นเหตุผลใด ๆ ที่จะหลีกเลี่ยงโซลูชันที่ยอมรับโดยใช้ std :: string :: find
b00n12

ใช่นั่นเป็นจุดที่ดี ไม่คิดว่าเมื่อฉันเขียนสิ่งนี้ ฉันเดาสิ่งที่ฉันคิดว่าเมื่อฉันเขียนสิ่งนี้อาจเป็นวิธีการหลีกเลี่ยงการใช้ std :: find
ทดสอบ 123

3
สำหรับผู้เยี่ยมชมในอนาคต: อัลกอริทึมนี้ไม่ถูกต้องจริง เนื่องจาก "i" จะไม่กลับไปหลังจากการจับคู่สตริงย่อยที่ล้มเหลวบางกรณีไม่ถูกจับคู่ตัวอย่างเช่นพิจารณา: aaabc, aab
sAm_vdP

1
สิ่งนี้มีข้อบกพร่องหลายประการ CheckSubstring(std::string firstString, std::string secondString)คัดลอกลึกทั้งสตริงที่ส่งผ่านไปยังฟังก์ชันซึ่งมีราคาแพงโดยเฉพาะอย่างยิ่งสำหรับสตริงที่ยาวกว่าซึ่งจำเป็นต้องจัดสรรฮีป นอกจากว่าคุณโทรCheckSubstring("XYZab", "ab\0\0")- The whileห่วงจะจบลงเมื่อเปรียบเทียบกับaการa, bเพื่อbที่ NUL นัยในตอนท้ายของสายแรกไป NUL อย่างชัดเจนในครั้งที่สองแล้วมันจะอ่านเกินบัฟเฟอร์สายแรกของการมีพฤติกรรมที่ไม่ได้กำหนด ในการแก้ไขปัญหาให้ใช้for (... i <= firstString.size () - secondString (). size (); ... ) `
Tony Delroy

1

หากขนาดของสตริงค่อนข้างใหญ่ (ร้อยไบต์หรือมากกว่า) และมี c ++ 17 คุณอาจต้องการใช้ตัวค้นหา Boyer-Moore-Horspool (ตัวอย่างจาก 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
สัญญาณของเวลา bool contains(const std::string& haystack, const std::string& needle)ในสมัยก่อนคนที่จะได้นำเสนอฟังก์ชั่น ทุกวันนี้พวกเขาเสนอชุดของตัวต่อที่ได้รับการตั้งชื่อตามผู้แต่งเอกสารที่คลุมเครือเพื่อให้ดูเหมือนวิทยาศาสตร์คอมพิวเตอร์ ...
BitTickler

0

คุณยังสามารถใช้ System namespace จากนั้นคุณสามารถใช้วิธีการที่มี

#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 ++ ที่เป็นกรรมสิทธิ์ของ Microsoft ไม่ว่าจะเป็น C ++ / CX หรือ C ++ / CLI
H. Al-Amri

1
ใช่ฉันขอโทษฉันไม่รู้ว่าใช้งานได้จนกว่าจะถึงวันหนึ่งหลังจากฉันโพสต์
Malindu Dilanka

-1

นี่คือฟังก์ชั่นที่เรียบง่าย

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
สวัสดียินดีต้อนรับสู่ SO คุณช่วยแก้ไขคำตอบของคุณและเพิ่มความเห็นเกี่ยวกับวิธีการทำงานและความแตกต่างจากคำตอบอื่น ๆ ได้ไหม ขอบคุณ!
ฟาบิโอพูดว่า Reinstate 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
โปรดพยายามหลีกเลี่ยงเพียงแค่ทิ้งรหัสเป็นคำตอบและพยายามอธิบายว่ามันทำอะไรและทำไม รหัสของคุณอาจไม่ชัดเจนสำหรับผู้ที่ไม่มีประสบการณ์การเข้ารหัสที่เกี่ยวข้อง โปรดแก้ไขคำตอบของคุณเพื่อรวมคำอธิบายบริบทและพยายามพูดถึงข้อ จำกัด ข้อสันนิษฐานหรือการทำให้เข้าใจง่ายในคำตอบของคุณ
SᴀᴍOnᴇᴌᴀ

ขอบคุณที่ทำให้โค้ดชัดเจนสำหรับการใช้งานusingกับฟังก์ชั่นที่จำเป็นเท่านั้นและไม่ได้ทิ้ง namespace ทั้งหมดลงในพื้นที่ส่วนกลาง สำหรับความคิดเห็น @ SᴀᴍOnᴇᴌᴀฉันเดาว่าผู้ใช้ไม่ได้อ่านความคิดเห็นในรหัสของคุณ
v010dya

-2

จากคำตอบมากมายในเว็บไซต์นี้ฉันไม่พบคำตอบที่ชัดเจนดังนั้นภายใน 5-10 นาทีฉันก็พบคำตอบด้วยตัวเอง แต่สามารถทำได้ในสองกรณี:

  1. ไม่ว่าคุณจะรู้ตำแหน่งของสตริงย่อยที่คุณค้นหาในสตริง
  2. ไม่ว่าคุณจะไม่ทราบตำแหน่งและค้นหามัน, ถ่านโดยถ่าน ...

ดังนั้นสมมติว่าเราค้นหาสตริงย่อย "cd" ในสตริง "abcde" และเราใช้ฟังก์ชันในตัวsubstr ที่ง่ายที่สุดใน C ++

สำหรับ 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;
}

สำหรับ 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
คำตอบยอดนิยมในทางใด ("ใช้ std :: string :: find") โพสต์เมื่อ 8 ปีก่อนไม่ชัดเจนเพียงพอ?
Steve Smith

-3

เราสามารถใช้วิธีนี้แทน เป็นเพียงตัวอย่างจากโครงการของฉัน ดูรหัส ค่าบริการพิเศษบางอย่างรวมอยู่ด้วย

ดูคำสั่ง 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";
        }
    }

}

ฉันขอโทษฉันไม่เห็นว่ามีคนโพสต์สิ่งเดียวกับที่ฉันทำไปก่อนหน้านี้
Malindu Dilanka

1
"สมัครกับฉันทาง YouTube" ถือได้ว่าเป็นสแปม โปรดระลึกไว้เสมอว่าในอนาคต นอกจากนี้อ่านวิธีการตอบและวิธีที่จะไม่เป็นผู้ส่งสแปมด้วย
Zoe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.