C ++ में एक स्ट्रिंग को कई बार एक चर संख्या कैसे दोहराएं?


127

मैं C ++ में स्ट्रिंग की शुरुआत में 'n' स्पेस (या कोई स्ट्रिंग) सम्मिलित करना चाहता हूं। वहाँ किसी भी तरह से यह करने का कोई सीधा तरीका है :: stings :: strings या char * strings?

जैसे कि पाइथन में आप बस कर सकते हैं

>>> "." * 5 + "lolcat"
'.....lolcat'
c++ 

कोई व्यक्ति QString का उपयोग करके उत्तर प्रदान करता है?
अक्विवा

जवाबों:


175

किसी एकल वर्ण को दोहराने के विशेष मामले में, आप इसका उपयोग कर सकते हैं std::string(size_type count, CharT ch):

std::string(5, '.') + "lolcat"

एनबी। इसका उपयोग बहु-वर्ण स्ट्रिंग्स को दोहराने के लिए नहीं किया जा सकता है।


79
ओपी ने एक स्ट्रिंग को दोहराने के लिए कहा, चरित्र नहीं।
फ्लोरियन कॉफ़मैन

39

पायथन में * ऑपरेटर के बराबर या पर्ल में x ऑपरेटर में स्ट्रिंग को दोहराने के लिए कोई प्रत्यक्ष मुहावरेदार तरीका नहीं है । यदि आप एक एकल वर्ण दोहरा रहे हैं, तो दो-तर्क निर्माता (जैसा कि पिछले उत्तरों द्वारा सुझाया गया है) अच्छी तरह से काम करता है:

std::string(5, '.')

यह इस बात का एक वंचित उदाहरण है कि आप स्ट्रिंग स्ट्रिंग को दोहराने के लिए एक ऑस्ट्रिंगस्ट्रीम का उपयोग कैसे कर सकते हैं:

#include <sstream>

std::string repeat(int n) {
    std::ostringstream os;
    for(int i = 0; i < n; i++)
        os << "repeat";
    return os.str();
}

कार्यान्वयन के आधार पर, यह केवल स्ट्रिंग n समय को ध्यान में रखते हुए थोड़ा अधिक कुशल हो सकता है।


17

स्ट्रिंग के कुछ रूपों का उपयोग करें :: सम्मिलित करें:

std::string str("lolcat");
str.insert(0, 5, '.');

यह स्ट्रिंग की शुरुआत में "....." (पांच डॉट्स) डालेगा (स्थिति 0)।


15
ओपी ने एक स्ट्रिंग को दोहराने के लिए कहा, चरित्र नहीं।
ब्रेंट

@Brent ओपी ने दोनों के लिए कहा - "n 'रिक्त स्थान (या कोई स्ट्रिंग)", और फिर स्ट्रिंग के रूप में एक एकल अवधि के साथ अपने इरादे का प्रदर्शन करने के लिए जाता है। अंग्रेजी कई लोगों की पहली भाषा नहीं है, इसलिए आपको कभी-कभी उनकी सटीक आवश्यकताओं का अनुमान लगाने की आवश्यकता होती है और जब विश्लेषण किया जाता है, तो सवाल वास्तव में पूछ रहा है कि किसी एकल चरित्र के साथ ऐसा कैसे करें। मुझे खेद है कि आपने मेरे जवाब को अस्वीकार कर दिया कि आपको इसे वोट करने की आवश्यकता थी।
camh

13

मुझे पता है कि यह एक पुराना सवाल है, लेकिन मैं वही काम करना चाह रहा था और मैंने जो सोचा है, वह सरल समाधान है। ऐसा प्रतीत होता है कि cout में यह फ़ंक्शन cout.fill () के साथ बनाया गया है, एक 'पूर्ण' स्पष्टीकरण के लिए लिंक देखें

http://www.java-samples.com/showtutorial.php?tutorialid=458

cout.width(11);
cout.fill('.');
cout << "lolcat" << endl;

आउटपुट

.....lolcat

6
केवल डॉट्स: अंतिम पंक्ति बदल कर ...cout << "" << endl;
musefan

9

उदाहरण के प्रयोजनों के लिए ओपी std :: स्ट्रिंग के ctor द्वारा प्रदान की गई पर्याप्त है std::string(5, '.'):। हालांकि, अगर कोई भी कई बार std को दोहराने के लिए एक फ़ंक्शन की तलाश में है: स्ट्रिंग कई बार:

std::string repeat(const std::string& input, unsigned num)
{
    std::string ret;
    ret.reserve(input.size() * num);
    while (num--)
        ret += input;
    return ret;
}

8

जैसा कि कमोडोर जैगर ने कहा, मुझे नहीं लगता कि वास्तव में इस सवाल का कोई अन्य उत्तर है; सवाल पूछता है कि एक स्ट्रिंग को कैसे दोहराया जाए, चरित्र नहीं।

जबकि कमोडोर द्वारा दिया गया उत्तर सही है, यह काफी अक्षम है। यहां एक तेज़ कार्यान्वयन है, यह विचार है कि स्ट्रिंग को पहले तेजी से बढ़ाकर संचालन और मेमोरी आवंटन को कम करना है:

#include <string>
#include <cstddef>

std::string repeat(std::string str, const std::size_t n)
{
    if (n == 0) {
        str.clear();
        str.shrink_to_fit();
        return str;
    } else if (n == 1 || str.empty()) {
        return str;
    }
    const auto period = str.size();
    if (period == 1) {
        str.append(n - 1, str.front());
        return str;
    }
    str.reserve(period * n);
    std::size_t m {2};
    for (; m < n; m *= 2) str += str;
    str.append(str.c_str(), (n - (m / 2)) * period);
    return str;
}

हम operator*पायथन संस्करण के करीब कुछ पाने के लिए भी परिभाषित कर सकते हैं :

#include <utility>

std::string operator*(std::string str, std::size_t n)
{
    return repeat(std::move(str), n);
}

मेरी मशीन पर यह कमोडोर द्वारा दिए गए कार्यान्वयन की तुलना में लगभग 10 गुना तेज है, और एक भोले 'एपेंड एन - 1 बार' समाधान की तुलना में लगभग 2x तेज है ।


आपका कार्यान्वयन 'प्रतिलिपि को न्यूनतम नहीं' करता है। ध्यान रखें कि +=आपके लूप के भीतर आंतरिक रूप से कुछ प्रकार का एक लूप भी होता है जो str.size()पुनरावृत्तियों करता है । str.size()प्रत्येक बाहरी लूप पुनरावृत्ति में बढ़ता है, इसलिए प्रत्येक बाहरी पुनरावृत्ति के बाद आंतरिक लूप को अधिक पुनरावृत्तियों करना पड़ता है। आपके और भोले 'कॉपी n समय' के कार्यान्वयन में कुल दोनों प्रतिलिपि n * periodवर्ण हैं। आपका कार्यान्वयन प्रारंभिक के कारण केवल एक मेमोरी आवंटन करता है reserve। मुझे लगता है कि आपने अपने कार्यान्वयन को एक छोटे strऔर एक बड़े के nसाथ नहीं बल्कि बड़े strऔर छोटे के साथ भी लागू किया है n
फ्लोरियन कॉफमैन

@FlorianKaufmann यकीन नहीं है कि आपने मेरे जवाब पर हमला करने के लिए क्यों चुना है। लेकिन "कम से कम नकल" से मेरा मतलब है 'ऑपरेशन की नकल'। यह विचार किया जा रहा है कि बड़ी संख्या में छोटे ब्लॉकों की नकल करने की तुलना में बड़ी संख्या में बड़े ब्लॉक की नकल करना अधिक कुशल (कई कारणों से) है। मैं संभावित रूप से अनुभवहीन पद्धति पर इनपुट स्ट्रिंग पर एक अतिरिक्त आवंटन से बचता हूं।
डैनियल

2
यह बताते हुए टिप्पणी की गई कि मुझे आपके दावे पर विश्वास नहीं है कि आपका समाधान भोली समाधान की तुलना में दक्षता के मामले में बहुत बेहतर है। मेरे माप में, भोले समाधान की तुलना में, आपका कोड छोटे तार और कई पुनरावृत्ति के साथ तेज है, लेकिन लंबे तार और कुछ पुनरावृत्ति के साथ धीमा है। क्या आप और अधिक विस्तार से यह बताकर लिंक प्रदान कर सकते हैं कि कई बड़े ब्लॉकों की नकल करने के कई छोटे ब्लॉकों की नकल करने की तुलना में उच्च प्रदर्शन क्यों है? मैं शाखा भविष्यवाणी के बारे में सोच सकता हूं। सीपीयू कैश के बारे में मैं अनिश्चित हूं कि कौन सा संस्करण पसंद किया जाता है।
फ्लोरियन कॉफमैन

@FlorianKaufmann मैं दो दृष्टिकोणों के बीच बड़े strऔर छोटे के लिए कोई महत्वपूर्ण अंतर नहीं देखता n। मेरा मानना ​​है कि शाखा भविष्यवाणी प्रति से ज्यादा समग्र पाइपलाइन के साथ ऐसा करना है, विचार करने के लिए डेटा संरेखण मुद्दे भी हैं । आपको इस बात के विवरणों के लिए एक नया प्रश्न पूछना चाहिए कि यह अधिक प्रोसेसर / मेमोरी फ्रेंडली क्यों है, मुझे यकीन है कि यह बहुत अधिक ब्याज प्राप्त करेगा, और इससे बेहतर उत्तर मैं यहां दे सकता हूं।
डेनियल

1
@FlorianKaufmann: x86 पर, rep movsbप्रतिलिपि बनाने के सबसे प्रभावी तरीकों में से एक है, कम से कम मध्यम से बड़ी प्रतियों के लिए। इसके माइक्रो-कोडेड कार्यान्वयन में कुछ निकट-स्थिर स्टार्टअप ओवरहेड (AMD और Intel दोनों पर) हैं, उदाहरण के लिए Sandybridge पर, ~ 15 से 40 चक्र, प्लस 4 साइकिल प्रति 64B कैश लाइन (सबसे अच्छा मामला) । छोटी प्रतियों के लिए, एक एसएसई लूप सबसे अच्छा है क्योंकि इसमें स्टार्टअप ओवरहेड नहीं है। लेकिन इसके बाद यह शाखा बदमाशों के अधीन है।
पीटर कॉर्ड्स

6

आपको अपनी स्ट्रीम मैनिपुलेटर लिखनी चाहिए

cout << मल्टी (5) << "जो भी" << "lolcat";


15
एक स्ट्रीम मैनिप्युलेटर लिखना बहुत सरल कुछ करने का एक जटिल तरीका है!
शून्य

10
C ++ कुछ सरल करने का एक बहुत ही जटिल तरीका है।
JDPeckham

5

ITNOA

आप ऐसा करने के लिए C ++ फ़ंक्शन का उपयोग कर सकते हैं।

 std::string repeat(const std::string& input, size_t num)
 {
    std::ostringstream os;
    std::fill_n(std::ostream_iterator<std::string>(os), num, input);
    return os.str();
 }

1
पृथ्वी पर "ITNOA" का क्या अर्थ है? इसका कोई संदर्भ ऑनलाइन नहीं मिल सकता है।
फॉलिंग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.