Periksa apakah string berisi string dalam C ++

494

Saya memiliki variabel tipe std::string. Saya ingin memeriksa apakah mengandung tertentu std::string. Bagaimana saya melakukannya?

Apakah ada fungsi yang mengembalikan true jika string ditemukan, dan false jika tidak?

ahli saraf
sumber
6
Apakah maksud Anda char * string atau string dari STL?
anthares
1
Ini bukan string * char. Saya harus #include <string> untuk menggunakannya.
ahli saraf
1
Beberapa solusi menggunakan s2 untuk string yang ingin saya temukan. Apakah masih akan berfungsi jika saya menggunakan sesuatu seperti "ini adalah string" bukan s2?
neuromancer
2
Ya karena ada konstruktor string literl untuk std :: tipe string.
18
Seseorang tolong buat proposal untuk ditambahkan std::basic_string::containske stdlib.
emlai

Jawaban:

723

Gunakan std::string::findsebagai berikut:

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

Catatan: "ditemukan!" akan dicetak jika s2merupakan substring dari s1, keduanya s1dan s2berjenis std::string.

Guy Avraham
sumber
117

Anda dapat mencoba menggunakan findfungsi ini:

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

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

Sebenarnya, Anda dapat mencoba menggunakan boost library, saya pikir std :: string tidak menyediakan metode yang cukup untuk melakukan semua operasi string yang umum. Dalam boost, Anda bisa menggunakan 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;
}
Geng Jiawen
sumber
33
"Saya pikir std :: string tidak menyediakan metode yang cukup untuk melakukan semua operasi string umum". Tapi ada findmetode untuk tugas yang dimaksud. Tidak perlu memperkenalkan ketergantungan perpustakaan.
Stefan
8
@stefan, Anda benar, ada metode find, tetapi bagaimana dengan split, ganti, dan banyak staf lainnya. Anda dapat membandingkan std :: string dengan string api di Java.PS:Juga saya pikir mengandung jauh lebih elegan daripada temukan untuk memeriksa apakah suatu string berisi string lain.
Geng Jiawen
1
Ini juga pendek, dan lebih mudah diingat. Cpp 17 telah menambahkan dukungan untuk sistem file. Saya harap Cpp 2x akan melakukan sesuatu untuk string juga. Ini sangat menyakitkan kurangnya dukungan metode string dasar di cpp modern.
Geng Jiawen
1
Apakah Anda benar-benar membutuhkan "usings"? Ketika saya membaca kode ini, saya tidak tahu apakah containsitu std::containsatau boost::contains, yang sepertinya merupakan kelemahan yang signifikan. Saya kira std :: mengandung saat ini tidak ada, tetapi saya tidak yakin itu masuk akal untuk menganggap pembaca telah menghafal semua yang ada di std. Dan std::containsmungkin ada di beberapa versi c ++ di masa depan, yang akan merusak program ini.
Don Hatch
12

Anda bisa mencoba ini

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

Jika fungsionalitasnya penting bagi sistem Anda, sebenarnya bermanfaat untuk menggunakan strstrmetode lama . The std::searchMetode dalamalgorithm adalah paling lambat mungkin. Dugaan saya adalah bahwa dibutuhkan banyak waktu untuk membuat iterator tersebut.

Kode yang saya gunakan untuk mengatur waktu semuanya adalah

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

Di sini saya menghasilkan acak haystacksdan mencari di dalamnyaneedle . Hitungan tumpukan jerami diatur, tetapi panjang string dalam setiap tumpukan jerami meningkat dari 10 di awal menjadi 10.240 pada akhirnya. Sebagian besar waktu yang dihabiskan oleh program benar-benar menghasilkan string acak, tetapi itulah yang diharapkan.

Outputnya adalah:

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.
v010dya
sumber
Versi yang lebih pendek dari jawabannya adalah: menggunakan c bukannya c ++ :)
r0ng
3

Jika Anda tidak ingin menggunakan fungsi pustaka standar, di bawah ini adalah salah satu solusinya.

#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;
}
Testing123
sumber
6
Anda sudah menggunakan std :: string, maka kode Anda sudah tergantung pada std lib. Saya rly tidak melihat alasan mengapa untuk menghindari solusi yang diterima menggunakan std :: string :: find.
b00n12
Ya, itu poin bagus. Tidak menyangka ketika saya menulis ini. Saya kira apa yang saya pikirkan ketika saya menulis ini mungkin cara menghindari menggunakan std :: find.
Testing123
3
Hanya untuk pengunjung masa depan: Algoritma ini sebenarnya tidak benar. Karena "i" tidak pernah kembali setelah kecocokan substring yang gagal, beberapa kasus tidak cocok, misalnya pertimbangkan: aaabc, aab
sAm_vdP
1
Ini memiliki beberapa bug. CheckSubstring(std::string firstString, std::string secondString)salinan mendalam kedua string diteruskan ke fungsi, yang mahal, terutama untuk string yang lebih lama yang memerlukan alokasi tumpukan. Selanjutnya, mengatakan Anda menelepon CheckSubstring("XYZab", "ab\0\0")- yang whilelingkaran akan berakhir membandingkan adengan a, buntuk b, yang NUL implisit pada akhir string pertama dengan NUL eksplisit dalam kedua, maka akan membaca di luar buffer string pertama ini, memiliki perilaku tidak terdefinisi. Untuk memperbaikinya gunakan for (... i <= firstString.size () - secondString (). Size (); ...) `.
Tony Delroy
1

Jika ukuran string relatif besar (ratusan byte atau lebih) dan c ++ 17 tersedia, Anda mungkin ingin menggunakan pencari Boyer-Moore-Horspool (contoh dari 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";
}
Konstantin Stupnik
sumber
3
Tanda-tanda zaman. Di masa lalu seseorang akan menawarkan fungsi bool contains(const std::string& haystack, const std::string& needle). Saat ini, mereka menawarkan satu set potongan puzzle yang dinamai oleh beberapa penulis kertas yang tidak dikenal untuk membuatnya lebih mirip ilmu komputer ...
BitTickler
0

Anda juga dapat menggunakan System namespace. Kemudian Anda bisa menggunakan metode berisi.

#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";
    }
}
Malindu Dilanka
sumber
Jawaban ini hanya berlaku untuk ekstensi C ++ milik Microsoft, baik C ++ / CX atau C ++ / CLI
H. Al-Amri
1
ya, saya minta maaf, saya tidak tahu itu hanya berfungsi seperti itu sampai suatu hari setelah saya mempostingnya.
Malindu Dilanka
-1

Ini adalah fungsi yang sederhana

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;
}
neda
sumber
4
Halo, selamat datang di SO. Bisakah Anda mengedit jawaban Anda dan menambahkan komentar tentang cara kerjanya dan bagaimana perbedaannya dari jawaban lain? Terima kasih!
Fabio berkata 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;
}
zonline
sumber
11
Cobalah menghindari hanya membuang kode sebagai jawaban dan coba jelaskan apa fungsinya dan mengapa. Kode Anda mungkin tidak jelas bagi orang yang tidak memiliki pengalaman pengkodean yang relevan. Harap edit jawaban Anda untuk memasukkan klarifikasi, konteks, dan coba sebutkan batasan, asumsi, atau penyederhanaan dalam jawaban Anda.
Sᴀᴍ Onᴇᴌᴀ
Terima kasih telah membuat kode menjadi jelas, untuk digunakan usinghanya dengan fungsi yang diperlukan dan tidak membuang seluruh namespace ke ruang global. Adapun komentar @ SᴀᴍOnᴇᴌᴀ, saya kira pengguna itu tidak membaca komentar dalam kode Anda.
v010dya
-2

Dari begitu banyak jawaban di situs web ini saya tidak menemukan jawaban yang jelas sehingga dalam 5-10 menit saya menemukan jawabannya sendiri. Tetapi ini bisa dilakukan dalam dua kasus:

  1. Entah Anda TAHU posisi sub-string yang Anda cari dalam string
  2. Entah Anda tidak tahu posisi dan mencarinya, char by char ...

Jadi, mari kita asumsikan kita mencari substring "cd" di string "abcde", dan kita menggunakan fungsi built-in substr yang paling sederhana di C ++

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

untuk 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;
}
pengguna7655194
sumber
2
Dengan cara apa jawaban teratas ("use std :: string :: find"), diposting 8 tahun sebelumnya, tidak cukup jelas?
Steve Smith
-3

Kita bisa menggunakan metode ini sebagai gantinya. Hanya sebuah contoh dari proyek saya. Lihat kodenya. Beberapa tambahan juga disertakan.

Lihatlah pernyataan 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
sumber
Maaf, saya tidak melihat bahwa seseorang telah memposting hal yang sama seperti yang saya lakukan sebelumnya.
Malindu Dilanka
1
"Berlangganan saya di YouTube" dapat dianggap sebagai spam. Ingatlah itu di masa depan. Baca juga Cara Menjawab dan cara untuk tidak menjadi spammer
Zoe