C ++ में स्ट्रिंग्स की एक सरणी कैसे घोषित करें?


89

मैं सबसे अच्छा संभव तरीके से तार के एक स्थिर सरणी के सभी तत्वों पर पुनरावृति करने की कोशिश कर रहा हूं। मैं एक पंक्ति में इसे घोषित करने में सक्षम होना चाहता हूं और आसानी से संख्याओं का ट्रैक रखने के बिना इसमें से तत्वों को जोड़ना / निकालना। वास्तव में सरल लगता है, है ना?

संभव गैर-समाधान:

vector<string> v;
v.push_back("abc");
b.push_back("xyz");

for(int i = 0; i < v.size(); i++)
    cout << v[i] << endl;

समस्याएं - तार की सूची के साथ एक लाइन पर वेक्टर बनाने का कोई तरीका नहीं

संभव गैर-समाधान 2:

string list[] = {"abc", "xyz"};

समस्याएं - स्वचालित रूप से स्ट्रिंग्स की संख्या प्राप्त करने का कोई तरीका नहीं (जो मुझे पता है)।

ऐसा करने का एक आसान तरीका होना चाहिए।


बढ़ावा असाइन पुस्तकालय होने के लिए आप के लिए वास्तव में क्या देख रहे हैं लगता है। यह कंटेनरों को पहले से आसान बनाना आसान बनाता है।
क्रेग एच

जवाबों:


108

C ++ 11 ने निम्नलिखित सिंटैक्स की अनुमति देने के लिए आरंभीकरण सूचियों को जोड़ा:

std::vector<std::string> v = {"Hello", "World"};

इस C ++ 11 सुविधा के लिए समर्थन कम से कम GCC 4.4 और केवल विजुअल स्टूडियो 2013 में जोड़ा गया था ।


2018. बस सी ++ शुरू करना और लचीली सरणियों के बारे में काफी कुछ शोध किया। केवल वैक्टर का उपयोग कर समाप्त ...
रॉबर्ट मोलिना

37

आप संक्षिप्त vector<string>रूप से एक सांख्यिकीय रूप से निर्मित char*सरणी से आरंभ कर सकते हैं :

char* strarray[] = {"hey", "sup", "dogg"};
vector<string> strvector(strarray, strarray + 3);

यह सभी तार को कॉपी करता है, वैसे, तो आप मेमोरी का दोगुना उपयोग करते हैं। आप यहां जादुई संख्या 3 को एरीसेज़ (str_array) के साथ बदलने के लिए विल डीन के सुझाव का उपयोग कर सकते हैं - हालांकि मुझे याद है कि कुछ विशेष मामला है जिसमें ऐरे के विशेष संस्करण में कुछ ख़राब हो सकता है (क्षमा करें, मैं तुरंत विवरण याद नहीं कर सकता) । लेकिन यह बहुत बार सही ढंग से काम करता है।

इसके अलावा, यदि आप एक पंक्ति वाली चीज़ के बारे में वास्तव में गंग-हो रहे हैं, तो आप एक वैरिएड मैक्रो को परिभाषित कर सकते हैं ताकि एक लाइन जैसे DEFINE_STR_VEC(strvector, "hi", "there", "everyone");काम करता हो।


चूंकि strarrayहेडर में है, क्या यह एक परिभाषा नियम का उल्लंघन नहीं करेगा?
jww

22

समस्याएं - स्वचालित रूप से स्ट्रिंग्स की संख्या प्राप्त करने का कोई तरीका नहीं है (जो मुझे पता है)।

ऐसा करने का एक दलदल-मानक तरीका है, जो बहुत सारे लोग (एमएस सहित) मैक्रोज़ को इस तरह परिभाषित करते हैं arraysize:

#define arraysize(ar)  (sizeof(ar) / sizeof(ar[0]))

1
वैकल्पिक रूप से, कोई इस तरह का उपयोग कर सकता है: template<typename T, size_t N> inline size_t arraysize(T (&ar)[N]) { return N; } (इनलाइन कीवर्ड आवश्यक नहीं है, लेकिन फ़ंक्शन के इरादे को दस्तावेज करने के लिए उपयोग किया जाता है। एक आधुनिक संकलक सैद्धांतिक रूप से पूरे फ़ंक्शन को वापस करने में सक्षम होना चाहिए, मेरा मानना ​​है कि
जस्टिन टाइम - मोनिका

1
यह संकेत के लिए विफल रहता है। गिनती के तत्वों को C ++ में एक अलग तरीके से किया जाना चाहिए।
jww

8

C ++ में स्ट्रिंग्स की एक सरणी को इस तरह घोषित करें: char array_of_strings[][]

उदाहरण के लिए : char array_of_strings[200][8192];

200 तार पकड़ेंगे, प्रत्येक स्ट्रिंग का आकार 8kb या 8192 बाइट होगा।

strcpy(line[i],tempBuffer); स्ट्रिंग के सरणी में डेटा डालने के लिए उपयोग करें।


FYI करें, char array_of_strings [] [] C ++ स्ट्रिंग्स को स्वीकार नहीं कर सकते हैं, पहले char * में कनवर्ट करना सुनिश्चित करें। cplusplus.com/reference/string/string/c_str
ल्यूकमैन

चूंकि array_of_stringsहेडर में है, क्या यह एक परिभाषा नियम का उल्लंघन नहीं करेगा?
jww

7

एक प्रतिगामी को एक ध्वज सूचक के रूप में NULL पॉइंटर का उपयोग करना है:

const char *list[] = {"dog", "cat", NULL};
for (char **iList = list; *iList != NULL; ++iList)
{
    cout << *iList;
}

चर ** का वास्तव में क्या मतलब है? जावा में, यह तार की एक सूची होगी?
IAmGroot 14

1
@Doomsknight: इस मामले में, हाँ। पहली पंक्ति में मैं एक सरणी को परिभाषित करता हूं char*। स्मृति में, इसे 3 पॉइंटर्स के रूप में रखा जाता है - एक बिंदु "डॉग" को, एक पॉइंट "कैट" को और एक को NULL छोड़ दिया जाता है। मैं उस पहले पॉइंटर को पॉइंटर ले जा सकता हूं, और एक char**- पॉइंटर को पॉइंटर को चार करने के लिए एक पॉइंटर प्राप्त कर सकता हूं । जब मैं वह वेतन वृद्धि करता हूं, तो मैं सूची में अगले आइटम को इंगित करने के लिए चार ** ले जाता हूं - पॉइंटर का एक पॉइंटर जो "बिल्ली" को इंगित करता है, फिर मैं फिर से वेतन वृद्धि करता हूं, और एक पॉइंटर प्राप्त करता हूं जो एनएलएल पॉइंटर को इंगित करता है, और मुझे पता है मैं कर रहा हूँ।
ग्रहण

4

बूस्ट रेंज लाइब्रेरी से आप beginऔर endफ़ंक्शंस का उपयोग आसानी से एक आदिम सरणी के सिरों को खोजने के लिए कर सकते हैं, और मैक्रो समाधान के विपरीत, यह टूटे हुए व्यवहार के बजाय एक संकलित त्रुटि देगा यदि आप गलती से इसे एक पॉइंटर पर लागू करते हैं।

const char* array[] = { "cat", "dog", "horse" };
vector<string> vec(begin(array), end(array));

3

आप विल डीन के सुझाव का उपयोग कर सकते हैं [ #define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))] यहां जादू नंबर 3 को प्रतिस्थापित करने के लिए arraysize (str_array) के साथ - हालांकि मुझे याद है कि कुछ विशेष मामला है जिसमें arraysize का विशेष संस्करण कुछ खराब कर सकता है (माफ करना, मुझे विवरण याद नहीं है। हाथोंहाथ)। लेकिन यह बहुत बार सही ढंग से काम करता है।

ऐसा मामला जहां यह काम नहीं करता है जब "सरणी" वास्तव में सिर्फ एक सूचक है, वास्तविक सरणी नहीं है। इसके अलावा, जिस तरह से सरणियों को फ़ंक्शन (पहले तत्व के लिए एक पॉइंटर में परिवर्तित) में पारित किया जाता है, यह फ़ंक्शन कॉल में काम नहीं करता है, भले ही हस्ताक्षर एक सरणी की तरह दिखता हो - some_function(string parameter[])वास्तव में some_function(string *parameter)


3

यहाँ एक उदाहरण है:

#include <iostream>
#include <string>
#include <vector>
#include <iterator>

int main() {
    const char* const list[] = {"zip", "zam", "bam"};
    const size_t len = sizeof(list) / sizeof(list[0]);

    for (size_t i = 0; i < len; ++i)
        std::cout << list[i] << "\n";

    const std::vector<string> v(list, list + len);
    std::copy(v.begin(), v.end(), std::ostream_iterator<string>(std::cout, "\n"));
}

2

उस मैक्रो के बजाय, मैं यह सुझाव दे सकता हूं:

template<typename T, int N>
inline size_t array_size(T(&)[N])
{
    return N;
}

#define ARRAY_SIZE(X)   (sizeof(array_size(X)) ? (sizeof(X) / sizeof((X)[0])) : -1)

1) हम इसे एक संकलन-समय स्थिर बनाने के लिए एक मैक्रो का उपयोग करना चाहते हैं; फ़ंक्शन कॉल का परिणाम एक संकलन-समय स्थिर नहीं है।

2) हालांकि, हम मैक्रो का उपयोग नहीं करना चाहते हैं क्योंकि मैक्रो गलती से एक पॉइंटर पर इस्तेमाल किया जा सकता है। फ़ंक्शन का उपयोग केवल संकलन-समय सरणियों पर किया जा सकता है।

इसलिए, हम मैक्रो को "सुरक्षित" बनाने के लिए फ़ंक्शन के परिभाषित-नेस का उपयोग करते हैं; यदि फ़ंक्शन मौजूद है (अर्थात इसका गैर-शून्य आकार है) तो हम ऊपर के रूप में मैक्रो का उपयोग करते हैं। यदि फ़ंक्शन मौजूद नहीं है, तो हम एक खराब मान लौटाते हैं।


2
#include <boost/foreach.hpp>

const char* list[] = {"abc", "xyz"};
BOOST_FOREACH(const char* str, list)
{
    cout << str << endl;
}

1
#include <iostream>
#include <string>
#include <vector>
#include <boost/assign/list_of.hpp>

int main()
{
    const std::vector< std::string > v = boost::assign::list_of( "abc" )( "xyz" );
    std::copy(
        v.begin(),
        v.end(),
        std::ostream_iterator< std::string >( std::cout, "\n" ) );
}

1

आप सीधे स्ट्रिंग्स की एक सरणी घोषित कर सकते हैं जैसे string s[100];। फिर यदि आप विशिष्ट तत्वों का उपयोग करना चाहते हैं, तो आप इसे सीधे पसंद कर सकते हैं s[2][90]। पुनरावृत्ति उद्देश्यों के लिए, s[i].size()फ़ंक्शन का उपयोग करके स्ट्रिंग का आकार लें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.