Bir dizenin C ++ 'da dize içerip içermediğini kontrol edin


493

Değişken tipim var std::string. Belli olup olmadığını kontrol etmek istiyorum std::string. Bunu nasıl yaparım?

Dize bulunursa true, değilse false döndüren bir işlev var mı?


6
Şunu mu demek istediniz: char * string veya STL string?
anthares

1
Bir char * string değil. Kullanmak için #string> eklemem gerekiyordu.
nöromancer

1
Bazı çözümler bulmak istediğim dize için s2 kullanıyor. Eğer s2 yerine "bu bir dize" gibi bir şey kullanırsanız yine de çalışır mı?
neuromancer

2
Evet çünkü std :: string tipi için bir string litre yapıcısı vardır.

18
Birisi lütfen std::basic_string::containsstdlib'e eklemek için bir teklifte bulunun.
emlai

Yanıtlar:


722

std::string::findAşağıdaki gibi kullanın :

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

Not: "bulundu!" Eğer basılacak s2de bir alt s1, hem de s1ve s2tiptedir std::string.


117

findİşlevi kullanmayı deneyebilirsiniz :

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

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

27

Aslında, destek kitaplığı kullanmayı deneyebilirsiniz, std :: string tüm ortak dize işlemi yapmak için yeterli yöntem sağlamaz düşünüyorum.Geliştirmek, sadece kullanabilirsiniz 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
Msgstr "Sanırım std :: string tüm ortak string işlemlerini yapmak için yeterli metot sağlamıyor". Ancak findsöz konusu görev için tam olarak bir yöntem var . Kütüphane bağımlılığı getirmeye gerek yoktur.
stefan

8
@stefan, haklısın, bir bulma yöntemi var, ama bölün, değiştir ve diğer pek çok personel hakkında. std :: string'i Java'daki dize api ile karşılaştırabilirsiniz. dizenin başka bir dize içerip içermediğini kontrol etmek için find.
Geng Jiawen

1
Ayrıca bu kısa ve hafızası daha kolaydır. Cpp 17 dosya sistemi için destek ekler. Umarım Cpp 2x de dize için bir şeyler yapar. Çok acı verici eksikliği modern cpp temel dize yöntemi desteği.
Geng Jiawen

1
Gerçekten "kullanıcılara" ihtiyacınız var mı? Bu kodu okuduğumda contains, std::containsya da boost::containsönemli bir dezavantaj gibi görünüyor, hiçbir fikrim yok . Sanırım std :: içeren şu anda mevcut değil, ancak okuyucunun std'deki her şeyi ezberlediğini varsaymanın makul olmadığından emin değilim. Ve std::containsbu programı kıracak c ++ 'ın gelecekteki bazı versiyonlarında çok iyi olabilir.
Don Hatch

12

Bunu deneyebilirsin

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

4

İşlevselliğin sisteminiz için kritik olması durumunda, eski bir strstryöntem kullanmak gerçekten yararlıdır . İçindeki std::searchyöntem algorithmmümkün olan en yavaş yöntemdir . Tahminimce bu yineleyicileri oluşturmak çok zaman alıyor.

Her şeyi zamanlamak için kullandığım kod

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

İşte ben rastgele üretmek haystacksve onları aramak needle. Samanlık sayısı ayarlanır, ancak her samanlıkta dizelerin uzunluğu başlangıçta 10'dan sonunda 10240'a çıkarılır. Çoğu zaman program aslında rastgele dizeler oluşturmak için harcıyor, ancak bu beklenen bir şey.

Çıktı:

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.

Cevabın daha kısa versiyonu: c ++ yerine c kullanılması :)
r0ng

3

Standart kütüphane işlevlerini kullanmak istemiyorsanız, aşağıda bir çözüm bulunmaktadır.

#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
Zaten std :: string kullanıyorsunuz, dolayısıyla kodunuz zaten std lib'e bağlı. Rly neden std :: string :: find kullanarak kabul edilen çözüm önlemek için herhangi bir neden görmüyorum.
b00n12

Evet, bu iyi bir nokta. Bunu yazarken bunu düşünmemiştim. Bu yazarken ne düşündüm sanırım belki nasıl sadece std :: find kullanmaktan kaçınmak olduğunu.
Testing123

3
Sadece gelecekteki ziyaretçiler için: Bu algoritma aslında doğru değil. Başarısız bir alt dize maçından sonra "i" hiçbir zaman geri dönmediğinden, bazı durumlar eşleşmez, örneğin düşünün: aaabc, aab
sAm_vdP

1
Bunun birkaç hatası var. CheckSubstring(std::string firstString, std::string secondString)Derin, her iki dizeyi işleve geçirdiğini kopyalar, bu da özellikle yığın ayırımı gerektiren daha uzun dizeler için pahalıdır. Dahası, aramak demek CheckSubstring("XYZab", "ab\0\0")- whiledöngü karşılaştıran sona erecek aiçin a, bhiç btanımlanmamış bir davranışa sahip, ikinci açık NUL ilk dizesinin sonunda örtük NUL, o zaman ilk dize ait tampon ötesinde okuyacaktır. Düzeltmek için for (... i <= firstString.size () - secondString (). Size (); ...) `.
Tony Delroy

1

Dizelerin boyutu nispeten büyükse (yüzlerce bayt veya daha fazla) ve c ++ 17 varsa, Boyer-Moore-Horspool arama aracını kullanmak isteyebilirsiniz (cppreference.com'dan örnek):

#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
Zamanın işaretleri. Eski günlerde birisi bir işlev teklif ederdi bool contains(const std::string& haystack, const std::string& needle). Günümüzde, daha fazla bilgisayar bilimi gibi görünmesini sağlamak için bazı karanlık kağıtların yazarlarından sonra adlandırılan bir dizi bulmaca parçası
sunuyorlar

0

Sistem ad alanını da kullanabilirsiniz. Sonra include yöntemini kullanabilirsiniz.

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

Bu yanıt yalnızca Microsoft'un tescilli C ++ uzantısı için C ++ / CX veya C ++ / CLI
H. Al-Amri

1
evet, özür dilerim, yayınladıktan birkaç gün öncesine kadar bu şekilde çalıştığını bilmiyordum.
Malindu Dilanka

-1

Bu basit bir işlev

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
Merhaba, SO'ya hoş geldiniz. Lütfen cevabınızı düzenleyip nasıl çalıştığı ve diğer cevaplardan nasıl farklı olduğu hakkında bir yorum ekleyebilir misiniz ? Teşekkür ederim!
Fabio, Reinstate Monica'ya

-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
Lütfen kodu bir cevap olarak atmaktan kaçının ve ne yaptığını ve nedenini açıklamaya çalışın. Kodunuz, ilgili kodlama deneyimine sahip olmayan kişiler için açık olmayabilir. Lütfen cevabınızı açıklama, bağlam
Sᴀᴍ Onᴇᴌᴀ

Kodu netleştirdiğiniz için using, yalnızca gerekli işlevlerle kullanmak ve ad alanının tamamını global alana dökmemek için teşekkür ederiz . @ SᴀᴍOnᴇᴌᴀ yorum gelince, bu kullanıcı kodunuzdaki yorumları okumadım sanırım.
v010dya

-2

Bu web sitesindeki pek çok cevaptan net bir cevap bulamadım, bu yüzden 5-10 dakika içinde cevabı kendim anladım. Ancak bu iki durumda yapılabilir:

  1. Ya BİLMEK Eğer dizede aramak alt dize pozisyonunu
  2. Ya konumu bilmiyorsunuz ve arama yapıyorsunuz , char ...

Diyelim ki, "abcde" dizesinde "cd" alt dizesini aradığımızı ve C ++ ' da en basit substr yerleşik işlevini kullandığımızı varsayalım.

1 için:

#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 için:

#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
8 yıl önce yayınlanan üst cevap ("std :: string :: find") hangi şekilde oldu, yeterince açık değil miydi?
Steve Smith

-3

Bunun yerine bu yöntemi kullanabiliriz. Sadece projelerimden bir örnek. Kodu inceleyin. Bazı ekstralar da dahildir.

İf ifadelerine bakın!

/*
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";
        }
    }

}

Üzgünüm, birisinin daha önce yaptığımla aynı şeyi paylaştığını görmedim.
Malindu Dilanka

1
"YouTube'da bana abone olun" spam olarak kabul edilebilir. Lütfen bunu aklınızda bulundurun. Ayrıca, Nasıl Yanıtlanacağını ve nasıl spam gönderilemeyeceğini
Zoe
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.