จะประกาศอาร์เรย์ของสตริงใน 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"};

ปัญหา - ไม่มีวิธีรับจำนวนสตริงโดยอัตโนมัติ (ที่ฉันรู้จัก)

ต้องมีวิธีง่ายๆในการทำเช่นนี้


เพิ่มห้องสมุดกำหนดน่าจะเป็นสิ่งที่คุณกำลังมองหา ทำให้การกำหนดค่าคงที่ให้กับคอนเทนเนอร์ง่ายกว่าที่เคย
Craig H

คำตอบ:


108

C ++ 11 เพิ่มรายการเริ่มต้นเพื่ออนุญาตไวยากรณ์ต่อไปนี้:

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

การสนับสนุนสำหรับ C ++ 11 คุณลักษณะนี้ถูกเพิ่มเข้ามาอย่างน้อยGCC 4.4และรายเดียวในVisual Studio 2013


2018 เพิ่งเริ่ม C ++ และทำการวิจัยเกี่ยวกับอาร์เรย์แบบยืดหยุ่น จบลงด้วยการใช้เวกเตอร์ ...
Robert Molina

37

คุณสามารถเริ่มต้นอย่างย่อvector<string>จากchar*อาร์เรย์ที่สร้างแบบสแตติก:

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

วิธีนี้จะคัดลอกสตริงทั้งหมดดังนั้นคุณจึงใช้หน่วยความจำสองเท่า คุณสามารถใช้คำแนะนำของ Will Dean เพื่อแทนที่ magic number 3 ได้ที่นี่ด้วย arraysize (str_array) - แม้ว่าฉันจะจำได้ว่ามีกรณีพิเศษบางอย่างที่ arraysize เวอร์ชันนั้นอาจทำให้เกิดสิ่งที่ไม่ดี (ขออภัยฉันจำรายละเอียดไม่ได้ในทันที) . แต่มักจะทำงานได้อย่างถูกต้อง

นอกจากนี้หากคุณสนใจเกี่ยวกับบรรทัดเดียวจริงๆคุณสามารถกำหนดมาโครแบบแปรผันเพื่อให้บรรทัดเดียวเช่นDEFINE_STR_VEC(strvector, "hi", "there", "everyone");ทำงานได้


เนื่องจากstrarrayอยู่ในส่วนหัวจึงไม่ละเมิดกฎนิยามเดียวหรือไม่?
jww

22

ปัญหา - ไม่มีวิธีรับจำนวนสตริงโดยอัตโนมัติ (ที่ฉันรู้)

มีวิธีที่เป็นมาตรฐานในการทำสิ่งนี้ซึ่งผู้คนจำนวนมาก (รวมถึง MS) กำหนดมาโครเช่น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; } (ไม่จำเป็นต้องใช้คำหลักแบบอินไลน์ แต่ใช้เพื่อบันทึกเจตนาของฟังก์ชันคอมไพเลอร์สมัยใหม่ควรจะคืนฟังก์ชันทั้งหมดในทางทฤษฎี
Justin Time - Reinstate Monica

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
Luqmaan

เนื่องจากarray_of_stringsอยู่ในส่วนหัวจึงไม่ละเมิดกฎนิยามเดียวหรือไม่?
jww

7

ความเป็นไปได้อย่างหนึ่งคือการใช้ตัวชี้ NULL เป็นค่าแฟล็ก:

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

ถ่าน ** หมายถึงอะไร? ใน java มันจะเป็นรายการสตริงหรือไม่?
IAmGroot

1
@ Doomsknight: ในกรณีนี้ใช่ ในบรรทัดแรกฉันกำหนดอาร์เรย์ของchar*. ในหน่วยความจำสิ่งนี้จะถูกจัดวางเป็น 3 พอยน์เตอร์ - หนึ่งจุดสำหรับ "สุนัข", หนึ่งชี้ไปที่ "แมว" และอีกตัวหนึ่งเป็นโมฆะ ฉันสามารถนำตัวชี้ไปที่ตัวชี้ตัวแรกนั้นและรับchar**- ตัวชี้เพื่อชี้ไปยังถ่าน เมื่อฉันเพิ่มสิ่งนั้นฉันย้ายอักขระ ** เพื่อชี้ไปยังรายการถัดไปในรายการ - ตัวชี้ไปยังตัวชี้ที่ชี้ไปที่ "cat" จากนั้นฉันจะเพิ่มขึ้นอีกครั้งและได้ตัวชี้ที่ชี้ไปที่ตัวชี้ NULL และ ฉันรู้ว่าฉันทำเสร็จแล้ว (
คราส

4

คุณสามารถใช้beginและendฟังก์ชันจากไลบรารีช่วง Boost เพื่อค้นหาจุดสิ้นสุดของอาร์เรย์ดั้งเดิมได้อย่างง่ายดายและแตกต่างจากโซลูชันมาโครซึ่งจะทำให้เกิดข้อผิดพลาดในการคอมไพล์แทนการทำงานที่เสียหายหากคุณนำไปใช้กับตัวชี้โดยไม่ได้ตั้งใจ

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

3

คุณสามารถใช้คำแนะนำของ Will Dean [ #define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))] เพื่อแทนที่ Magic Number 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()ฟังก์ชัน

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