จะพิมพ์เนื้อหาของเวกเตอร์ได้อย่างไร?


282

ฉันต้องการพิมพ์เนื้อหาของเวกเตอร์ใน C ++ นี่คือสิ่งที่ฉันมี:

#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <vector>
#include <sstream>
#include <cstdio>
using namespace std;

int main()
{
    ifstream file("maze.txt");
    if (file) {
        vector<char> vec(istreambuf_iterator<char>(file), (istreambuf_iterator<char>()));
        vector<char> path;
        int x = 17;
        char entrance = vec.at(16);
        char firstsquare = vec.at(x);
        if (entrance == 'S') { 
            path.push_back(entrance); 
        }
        for (x = 17; isalpha(firstsquare); x++) {
            path.push_back(firstsquare);
        }
        for (int i = 0; i < path.size(); i++) {
            cout << path[i] << " ";
        }
        cout << endl;
        return 0;
    }
}

ฉันจะพิมพ์เนื้อหาของเวกเตอร์ไปที่หน้าจอได้อย่างไร


1
ทำไม "ไม่ทำงาน"?
เริ่มต้น

คำตอบ:


394

เพื่อตอบคำถามของคุณคุณสามารถใช้ตัววนซ้ำ:

std::vector<char> path;
// ...
for (std::vector<char>::const_iterator i = path.begin(); i != path.end(); ++i)
    std::cout << *i << ' ';

หากคุณต้องการที่จะปรับเปลี่ยนเนื้อหาของเวกเตอร์ในการห่วงแล้วใช้มากกว่าiteratorconst_iterator

แต่มีอีกมากมายที่สามารถพูดเกี่ยวกับเรื่องนี้ หากคุณต้องการคำตอบที่คุณสามารถใช้ได้คุณสามารถหยุดที่นี่ มิฉะนั้นอ่านต่อ

อัตโนมัติ (C ++ 11) / typedef

นี่ไม่ใช่โซลูชันอื่น แต่เป็นส่วนเสริมสำหรับiteratorโซลูชันด้านบน หากคุณใช้มาตรฐาน C ++ 11 (หรือใหม่กว่า) จากนั้นคุณสามารถใช้autoคำหลักเพื่อช่วยในการอ่าน:

for (auto i = path.begin(); i != path.end(); ++i)
    std::cout << *i << ' ';

แต่ประเภทของiจะไม่ใช่ const (เช่นคอมไพเลอร์จะใช้std::vector<char>::iteratorเป็นประเภทของi)

ในกรณีนี้คุณอาจใช้เพียงแค่typedef(ไม่ จำกัด เฉพาะ C ++ 11 และมีประโยชน์มากที่จะใช้ต่อไป):

typedef std::vector<char> Path;
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
    std::cout << *i << ' ';

เคาน์เตอร์

แน่นอนคุณสามารถใช้ประเภทจำนวนเต็มเพื่อบันทึกตำแหน่งของคุณในforวง:

for(int i=0; i<path.size(); ++i)
  std::cout << path[i] << ' ';

หากคุณกำลังจะทำสิ่งนี้ควรใช้ประเภทสมาชิกของคอนเทนเนอร์ถ้ามีและเหมาะสม std::vectorมีประเภทสมาชิกที่เรียกว่าsize_typeสำหรับงานนี้: มันเป็นประเภทที่ส่งกลับโดยsizeวิธีการ

// Path typedef'd to std::vector<char>
for( Path::size_type i=0; i<path.size(); ++i)
  std::cout << path[i] << ' ';

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

เป็นช่วงสำหรับลูป (C ++ 11)

ดูวิธีการแก้ปัญหาของ Jefffrey ใน C ++ 11 (และใหม่กว่า) คุณสามารถใช้forวนรอบตามใหม่ซึ่งมีลักษณะดังนี้:

for (auto i: path)
  std::cout << i << ' ';

เนื่องจากpathเป็นเวกเตอร์ของรายการ (อย่างชัดเจนstd::vector<char>) วัตถุiจึงเป็นประเภทของรายการของเวกเตอร์ (กล่าวคือเป็นประเภทchar) วัตถุiมีค่าที่เป็นสำเนาของรายการจริงในpathวัตถุ ดังนั้นการเปลี่ยนแปลงทั้งหมดiในลูปจะไม่ถูกสงวนไว้ในpathตัวเอง นอกจากนี้หากคุณต้องการบังคับใช้ความจริงที่ว่าคุณไม่ต้องการที่จะสามารถเปลี่ยนค่าที่คัดลอกมาจากiในลูปคุณสามารถบังคับให้ประเภทiเป็นconst charดังนี้:

for (const auto i: path)
  std::cout << i << ' ';

หากคุณต้องการแก้ไขรายการในpathคุณสามารถใช้การอ้างอิง:

for (auto& i: path)
  std::cout << i << ' ';

และแม้ว่าคุณไม่ต้องการแก้ไขpathหากการคัดลอกวัตถุมีราคาแพงคุณควรใช้การอ้างอิง const แทนการคัดลอกตามค่า:

for (const auto& i: path)
  std::cout << i << ' ';

มาตรฐาน :: สำเนา

ดูคำตอบของโจชัว คุณสามารถใช้อัลกอริทึม STL std::copyเพื่อคัดลอกเนื้อหาเวกเตอร์ลงในสตรีมเอาต์พุต นี่เป็นคำตอบที่สวยงามหากคุณพอใจกับมัน (และยิ่งกว่านั้นมันมีประโยชน์มากไม่ใช่แค่ในกรณีของการพิมพ์เนื้อหาของเวกเตอร์)

มาตรฐาน :: for_each

ดูวิธีการแก้ปัญหาของแม็กซ์ การใช้std::for_eachเกินความจำเป็นสำหรับสถานการณ์อย่างง่าย ๆ นี้ แต่เป็นวิธีแก้ปัญหาที่มีประโยชน์มากหากคุณต้องการทำมากกว่าการพิมพ์ไปที่หน้าจอ: การใช้std::for_eachช่วยให้คุณสามารถดำเนินการใด ๆ (สมเหตุสมผล) กับเนื้อหาเวกเตอร์

โอเวอร์โหลด ostream :: ผู้ประกอบการ <<

ดูคำตอบของ Chris นี่เป็นคำตอบที่สมบูรณ์ยิ่งขึ้นสำหรับคำตอบอื่น ๆ เนื่องจากคุณยังต้องใช้หนึ่งในวิธีแก้ปัญหาข้างต้นในการรับน้ำหนักมากเกินไป ในตัวอย่างของเขาเขาใช้เคาน์เตอร์ในforวง ตัวอย่างเช่นนี่คือวิธีที่คุณสามารถใช้โซลูชันของ Joshuaได้อย่างรวดเร็ว:

template <typename T>
std::ostream& operator<< (std::ostream& out, const std::vector<T>& v) {
  if ( !v.empty() ) {
    out << '[';
    std::copy (v.begin(), v.end(), std::ostream_iterator<T>(out, ", "));
    out << "\b\b]";
  }
  return out;
}

การใช้โซลูชันอื่นใดควรตรงไปตรงมา

ข้อสรุป

โซลูชันใด ๆ ที่นำเสนอที่นี่จะใช้ได้ ขึ้นอยู่กับคุณและรหัสที่ดีที่สุด " สิ่งใดที่มีรายละเอียดมากกว่านี้น่าจะดีที่สุดสำหรับคำถามอื่นที่สามารถประเมินข้อดี / ข้อเสียได้อย่างเหมาะสม แต่เช่นเคยการตั้งค่าของผู้ใช้จะมีส่วนร่วมเสมอ: ไม่มีวิธีแก้ปัญหาใดที่นำเสนอผิด แต่บางคนก็ดูดีกว่า coder แต่ละตัว

ภาคผนวก

นี่เป็นโซลูชันเพิ่มเติมของรุ่นก่อนหน้าที่ฉันโพสต์ ตั้งแต่โพสต์นั้นยังคงได้รับความสนใจฉันตัดสินใจที่จะขยายและอ้างอิงถึงโซลูชั่นที่ยอดเยี่ยมอื่น ๆ ที่โพสต์ที่นี่ โพสต์ต้นฉบับของฉันมีคำพูดที่บอกว่าถ้าคุณได้รับการตั้งใจในการปรับเปลี่ยนเวกเตอร์ของคุณภายในforห่วงแล้วมีสองวิธีให้โดยstd::vectorองค์ประกอบการเข้าถึง: std::vector::operator[]ซึ่งไม่ได้ทำขอบเขตการตรวจสอบและstd::vector::atที่ไม่ดำเนินการตรวจสอบขอบเขต กล่าวอีกนัยหนึ่งatจะโยนถ้าคุณพยายามเข้าถึงองค์ประกอบนอกเวกเตอร์และoperator[]จะไม่ ฉันเพิ่งเพิ่มความคิดเห็นนี้เดิมเพื่อประโยชน์ในการกล่าวถึงบางสิ่งบางอย่างที่อาจเป็นประโยชน์ที่จะรู้ว่าถ้าใครไม่ได้แล้ว และฉันไม่เห็นความแตกต่างในขณะนี้ ดังนั้นภาคผนวกนี้


หากคุณวนลูปจาก0ถึงvector::size()และไม่มีการแก้ไขเวกเตอร์ภายในลูปคุณไม่จำเป็นต้องใช้at()และได้รับการตรวจสอบขอบเขตพิเศษ ที่กล่าวว่าฉันจะไปกับ iterator ตามที่คุณแนะนำ
Ed S.

1
@Ed: ใช่ไม่มีประโยชน์ในการใช้atถ้าไม่มีอะไรในลูปแก้ไขเวกเตอร์ แต่ฉันคิดว่าฉันจะพูดถึงมันในกรณีที่มีการแก้ไขเวกเตอร์ในวง (ไม่ธรรมดาเหมือนที่อาจเป็น) และเพราะมันไม่เคยได้รับ พูดถึงและอาจเป็นประโยชน์อย่างน้อยก็รู้
Zorawar

ช่วงของการวนซ้ำสามารถเขียนใหม่เพื่อใช้การอ้างอิงซึ่งอาจมีความสำคัญในกรณีของวัตถุย่อยขนาดใหญ่ดังนี้:for (auto const &i: path) std::cout << i << ' ';
underscore_d

@underscore_d: ขอบคุณ ฉันได้ทำความสะอาดส่วนนั้นแล้วและฉันหวังว่ามันจะสมบูรณ์กว่าและชัดเจนกว่าเล็กน้อยในตอนนี้
Zorawar

"ตัวดำเนินการโอเวอร์โหลด <<" ไม่ใช่วิธีแก้ปัญหาที่ดี อย่างน้อยหนึ่งตัวถูกดำเนินการของตัวดำเนินการโอเวอร์โหลดควรเป็นคลาสที่กำหนดโดยโปรแกรมของคุณเนื่องจากการค้นหาที่ขึ้นอยู่กับข้อโต้แย้ง
MM

218

วิธีที่ง่ายกว่ามากคือการใช้อัลกอริธึมการคัดลอกมาตรฐาน:

#include <iostream>
#include <algorithm> // for copy
#include <iterator> // for ostream_iterator
#include <vector>

int main() {
    /* Set up vector to hold chars a-z */
    std::vector<char> path;
    for (int ch = 'a'; ch <= 'z'; ++ch)
        path.push_back(ch);

    /* Print path vector to console */
    std::copy(path.begin(), path.end(), std::ostream_iterator<char>(std::cout, " "));

    return 0;
}

ostream_iterator คือสิ่งที่เรียกว่าอะแดปเตอร์ iterator มันถูกเทมเพลตตามประเภทเพื่อพิมพ์ไปยังสตรีม (ในกรณีนี้char) cout(aka console output) คือสตรีมที่เราต้องการเขียนและ space space ( " ") คือสิ่งที่เราต้องการพิมพ์ระหว่างแต่ละองค์ประกอบที่จัดเก็บในเวกเตอร์

อัลกอริทึมมาตรฐานนี้มีประสิทธิภาพและอื่น ๆ มากมาย พลังและความยืดหยุ่นที่ห้องสมุดมาตรฐานมอบให้คุณคือสิ่งที่ทำให้มันยอดเยี่ยมมาก แค่คิด: คุณสามารถพิมพ์เวกเตอร์ไปยังคอนโซลที่มีเพียงหนึ่งบรรทัดของรหัส คุณไม่ต้องจัดการกับกรณีพิเศษด้วยตัวคั่น คุณไม่จำเป็นต้องกังวลเกี่ยวกับการวนซ้ำ ไลบรารี่มาตรฐานทำทุกอย่างให้คุณ


3
vector<pair<int, struct node>>สิ่งที่ถ้าเวกเตอร์ของฉันคือประเภท ฉันจะใช้วิธีการด้านบนเพื่อพิมพ์เวกเตอร์นี้ได้อย่างไร
mtk

6
สตริงตัวคั่นจะถูกเขียนหลังจากทุกองค์ประกอบไม่ใช่ระหว่างเช่นหลังจากที่ผ่านมา ที่อาจต้องมีการจัดการกับกรณีพิเศษหากคุณต้องการเพียงแค่ระหว่างเป็นตัวคั่น
Quigi

2
@mtk คุณสามารถประกาศoperator<<ฟังก์ชั่นสำหรับคู่ที่เฉพาะเจาะจงของคุณ <>
ShoeLace

เพิ่มคำตอบที่แสดงวิธีการที่คล้ายกันแต่คำนึงถึงความคิดเห็น @Quigi: s ด้านบนเกี่ยวกับตัวคั่นต่อท้ายพิเศษ
dfri

@ShoeLace ไม่มีวิธีอื่นอีกไหม?
thegreatcoder

69

ใน C ++ 11 ตอนนี้คุณสามารถใช้range-based สำหรับ loop :

for (auto const& c : path)
    std::cout << c << ' ';

วิธีนี้ใช้งานได้ดีถ้าขนาดของเวกเตอร์ไม่เปลี่ยนแปลงในเนื้อความของช่วงสำหรับการวนซ้ำ
Brian

8
@BrianP ได้. การพิมพ์องค์ประกอบของคอนเทนเนอร์ไม่ได้ปรับเปลี่ยนช่วงของคอนเทนเนอร์
รองเท้า

สิ่งที่ดีกว่าที่นี่ - เป็นสำเนาค่าหรืออ้างอิง const เพื่อหลีกเลี่ยงการคัดลอกองค์ประกอบ?
kleinfreund

@kleinfreund มันขึ้นอยู่กับเนื้อหาของเวกเตอร์ ยกตัวอย่างเช่นเวกเตอร์ของchars โอกาสที่การส่งผ่านค่าอ้างอิงคงที่จะมีราคาสูงกว่ามูลค่าจริง แต่ที่นี่เรากำลังพูดถึงการเพิ่มประสิทธิภาพ super micro
รองเท้า

43

ฉันคิดว่าวิธีที่ดีที่สุดในการทำเช่นนี้คือการโอเวอร์โหลดoperator<<โดยเพิ่มฟังก์ชันนี้ในโปรแกรมของคุณ:

#include <vector>
using std::vector;
#include <iostream>
using std::ostream;

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& v) {
    out << "{";
    size_t last = v.size() - 1;
    for(size_t i = 0; i < v.size(); ++i) {
        out << v[i];
        if (i != last) 
            out << ", ";
    }
    out << "}";
    return out;
}

จากนั้นคุณสามารถใช้<<โอเปอเรเตอร์กับเวคเตอร์ใด ๆ ที่เป็นไปได้โดยสมมติว่าอิลิเมนต์นั้นได้ostream& operator<<กำหนด:

vector<string>  s = {"first", "second", "third"};
vector<bool>    b = {true, false, true, false, false};
vector<int>     i = {1, 2, 3, 4};
cout << s << endl;
cout << b << endl;
cout << i << endl;

ขาออก:

{first, second, third}
{1, 0, 1, 0, 0}
{1, 2, 3, 4}

3
การจัดเก็บ v.size () - 1 ในฐานะ int เป็นการสูญเสียความแม่นยำที่เป็นไปได้ ฉันแก้ไขสิ่งนี้ในการแก้ไขที่ตรวจสอบโดยเพื่อนที่ได้รับการยอมรับ ( stackoverflow.com/revisions/23397700/5 ) แต่หลังจากนั้นก็มีการแก้ไขอีกครั้งเพื่อเรียกคืนการสูญเสียความแม่นยำที่เป็นไปได้ ฉันเดาว่ามันไม่สำคัญในทางปฏิบัติมากนักเนื่องจากเวกเตอร์มักไม่ใหญ่ขนาดนั้น
JDiMatteo

การไม่เก็บไว้เป็นตัวแปรจะลดความสามารถในการอ่านของรหัสซึ่งเป็นส่วนหนึ่งของการแก้ไขของคุณที่ฉันไม่เห็นด้วย ฉันได้เปลี่ยนประเภทของการlast size_t
Chris Redford

size_t last = v.size() - 1;ดูซ้ำซ้อนคุณสามารถใช้if (i) out << ", ";เงื่อนไขก่อนout << v[i]; ลิงค์
Vladimir Gamalyan

3
ADL ไม่พบตัวดำเนินการนี้เนื่องจากไม่ได้อยู่ในเนมสเปซของอาร์กิวเมนต์ใด ๆ ดังนั้นมันจะถูกซ่อนไว้โดย operator<<namespace ตัวอย่าง
MM

หากคุณกำลังจะทำสิ่งนี้ทำไมต้องทดสอบif (i != last) แต่ละครั้งในลูป แต่ถ้าคอนเทนเนอร์ไม่ว่างเปล่าจากนั้น (a) ส่งองค์ประกอบแรกแล้ว (b) วนซ้ำส่ง องค์ประกอบที่เหลือให้พิมพ์ตัวคั่นก่อน (เป็นคำนำหน้า) ไม่จำเป็นต้องทำการทดสอบลูปภายใน (นอกเหนือจากเงื่อนไขลูป) ต้องการการทดสอบนอกวงเดียวเพียงหนึ่งครั้ง
WhozCraig

22

วิธีประมาณfor_each+ แลมบ์ดาแสดงออก :

#include <vector>
#include <algorithm>
...
std::vector<char> vec;
...
std::for_each(
              vec.cbegin(),
              vec.cend(),
              [] (const char c) {std::cout << c << " ";} 
              );
...

แน่นอนว่าช่วงที่ใช้สำหรับเป็นทางออกที่ดีที่สุดสำหรับงานที่เป็นรูปธรรม แต่สิ่งนี้ให้ความเป็นไปได้อื่น ๆ อีกมากมายเช่นกัน

คำอธิบาย

for_eachขั้นตอนวิธีการใช้เวลาช่วงเข้าและวัตถุ callableเรียกวัตถุนี้ในองค์ประกอบของช่วงทุก ช่วงเข้าจะถูกกำหนดโดยสองiterators วัตถุ callableอาจจะเป็นฟังก์ชั่นตัวชี้ไปยังฟังก์ชั่นวัตถุของคลาสซึ่งเกิน() operatorหรือเป็นในกรณีนี้การแสดงออกแลมบ์ดา พารามิเตอร์สำหรับนิพจน์นี้ตรงกับประเภทขององค์ประกอบจากเวกเตอร์

ความสวยงามของการนำไปใช้งานนี้คือพลังที่คุณได้รับจากการแสดงออกแลมบ์ดา - คุณสามารถใช้วิธีนี้เพื่อทำสิ่งต่าง ๆ ได้มากกว่าการพิมพ์เวกเตอร์


11

เพียงแค่คัดลอกคอนเทนเนอร์ไปยังคอนโซล

std::vector<int> v{1,2,3,4};
std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout, " " ));

ควรส่งออก:

1 2 3 4

8

ปัญหาน่าจะเป็นในลูปก่อนหน้านี้: (x = 17; isalpha(firstsquare); x++). การวนซ้ำนี้จะไม่ทำงานเลย (ถ้าfirstsquareไม่ใช่แบบอัลฟ่า) หรือจะทำงานแบบถาวร (ถ้าเป็นแบบอัลฟ่า) เหตุผลคือfirstsquareไม่เปลี่ยนแปลงตามที่xเพิ่มขึ้น


7

ใน C ++ 11 การอ้างอิงช่วงสำหรับลูปอาจเป็นโซลูชันที่ดี:

vector<char> items = {'a','b','c'};
for (char n : items)
    cout << n << ' ';

เอาท์พุท:

a b c 

6

การใช้std::copyแต่ไม่มีตัวคั่นพิเศษ

ทางเลือก / วิธีการแก้ไขโดยใช้std::copy(เดิมใช้ใน@JoshuaKravtiz คำตอบ ) แต่ไม่รวมตัวคั่นต่อท้ายเพิ่มเติมหลังจากองค์ประกอบสุดท้าย:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

template <typename T>
void print_contents(const std::vector<T>& v, const char * const separator = " ")
{
    if(!v.empty())
    {
        std::copy(v.begin(),
                  --v.end(),
                  std::ostream_iterator<T>(std::cout, separator));
        std::cout << v.back() << "\n";
    }
}

// example usage
int main() {
    std::vector<int> v{1, 2, 3, 4};
    print_contents(v);      // '1 2 3 4'
    print_contents(v, ":"); // '1:2:3:4'
    v = {};
    print_contents(v);      // ... no std::cout
    v = {1};
    print_contents(v);      // '1'
    return 0;
}

ตัวอย่างการใช้กับคอนเทนเนอร์ของประเภท POD ที่กำหนดเอง:

// includes and 'print_contents(...)' as above ...

class Foo
{
    int i;
    friend std::ostream& operator<<(std::ostream& out, const Foo& obj);
public:
    Foo(const int i) : i(i) {}
};

std::ostream& operator<<(std::ostream& out, const Foo& obj)
{
    return out << "foo_" << obj.i; 
}

int main() {
    std::vector<Foo> v{1, 2, 3, 4};
    print_contents(v);      // 'foo_1 foo_2 foo_3 foo_4'
    print_contents(v, ":"); // 'foo_1:foo_2:foo_3:foo_4'
    v = {};
    print_contents(v);      // ... no std::cout
    v = {1};
    print_contents(v);      // 'foo_1'
    return 0;
}

5

ผู้ประกอบการเกินพิกัด <<:

template<typename OutStream, typename T>
OutStream& operator<< (OutStream& out, const vector<T>& v)
{
    for (auto const& tmp : v)
        out << tmp << " ";
    out << endl;
    return out;
}

การใช้งาน:

vector <int> test {1,2,3};
wcout << test; // or any output stream

3

ฉันเห็นปัญหาสองอย่าง ตามที่ระบุไว้ในfor (x = 17; isalpha(firstsquare); x++)นั้นมีทั้งการวนซ้ำไม่สิ้นสุดหรือไม่เคยดำเนินการเลยและในif (entrance == 'S')กรณีที่อักขระทางเข้าแตกต่างจาก 'S' จะไม่มีสิ่งใดผลักไปยังเวกเตอร์ของเส้นทางทำให้มันว่างเปล่า คุณสามารถทดสอบการตรวจสอบหลังpath.empty()หรือการพิมพ์path.size()หรือพิมพ์

ไม่ว่าจะด้วยวิธีใดมันจะดีกว่าหรือไม่ถ้าจะใช้สตริงแทนที่จะเป็นเวกเตอร์ คุณสามารถเข้าถึงเนื้อหาสตริงเช่นอาร์เรย์ได้เช่นกันค้นหาตัวอักษรแยกสตริงย่อยและพิมพ์สตริงได้อย่างง่ายดาย (โดยไม่ต้องวนซ้ำ)

การทำทุกอย่างด้วยสายอักขระอาจเป็นวิธีที่ทำให้มันเขียนในลักษณะที่ซับซ้อนน้อยลงและง่ายต่อการตรวจสอบปัญหา


3

คำตอบนี้ขึ้นอยู่กับคำตอบจาก Zorawar แต่ฉันไม่สามารถแสดงความคิดเห็นได้

คุณสามารถสร้างอัตโนมัติ (C ++ 11) / typedef เวอร์ชัน const โดยใช้ cbegin และ cend แทน

for (auto i = path.cbegin(); i != path.cend(); ++i)
    std::cout << *i << ' ';

1

ใน C ++ 11``

for (auto i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';

for(int i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';

คำตอบนี้ไม่ได้ให้ข้อมูลเพิ่มเติมใด ๆ เมื่อเปรียบเทียบกับคำตอบที่มีอยู่แล้ว
Yashas

0
#include<bits/stdc++.h>
using namespace std;

int main()
{
    vector <pair<string,int> > v;
    int n;
    cin>>n;
int i;
    for( i=0;i<n;i++)
    {
        int  end;
        string str;
        cin>>str;
        cin>>end;
        v.push_back(make_pair(str,end));
    }



for (int j=0;j<n;j++)
{
    cout<<v[j].first<< " "<<v[j].second<<endl;
}``
}

2
Hi! ยินดีต้อนรับสู่ stackoverflow มันจะดีมากถ้าคุณสามารถใส่รหัสขนาดสั้นลงไปเพื่ออธิบายคำอธิบายว่าคุณกำลังทำอะไรอยู่และมันตอบคำถามอย่างไร
Slabgorb

2
คุณอาจต้องการอ่าน: ทำไมฉันไม่ #include <bits / stdc ++. h>
Blastfurnace

0

สิ่งนี้ใช้ได้กับฉัน:

    for (auto& i : name)
    {
    int r = 0;
    for (int j = 0; j < name[r].size();j++) 
    {
    std::cout << i[j];
    }
    r++;
    std::cout << std::endl;
    }

0

สำหรับผู้ที่มีความสนใจ: ฉันได้เขียนวิธีการแก้ปัญหาแบบทั่วไปที่ใช้ประโยชน์จากทั้งสองโลกได้ดียิ่งขึ้นสำหรับช่วงใด ๆ และวางเครื่องหมายคำพูดรอบประเภทที่ไม่ใช่ทางคณิตศาสตร์ นอกจากนี้วิธีการนี้ไม่ควรมีปัญหา ADL และหลีกเลี่ยง 'ความประหลาดใจ' (เนื่องจากมีการเพิ่มอย่างชัดเจนในแต่ละกรณี):

template <typename T>
inline constexpr bool is_string_type_v = std::is_convertible_v<const T&, std::string_view>;

template<class T>
struct range_out {
  range_out(T& range) : r_(range) {
  }
  T& r_;
  static_assert(!::is_string_type_v<T>, "strings and string-like types should use operator << directly");
};

template <typename T>
std::ostream& operator<< (std::ostream& out, range_out<T>& range) {
  constexpr bool is_string_like = is_string_type_v<T::value_type>;
  constexpr std::string_view sep{ is_string_like ? "', '" : ", " };

  if (!range.r_.empty()) {
    out << (is_string_like ? "['" : "[");
    out << *range.r_.begin();
    for (auto it = range.r_.begin() + 1; it != range.r_.end(); ++it) {
      out << sep << *it;
    }
    out << (is_string_like ? "']" : "]");
  }
  else {
    out << "[]";
  }

  return out;
}

ตอนนี้มันค่อนข้างใช้งานง่ายในทุกช่วง:

std::cout << range_out{ my_vector };

การตรวจสอบสตริงเหมือนออกจากห้องสำหรับการปรับปรุง ฉันมีวิธีstatic_assertเช็คอินเพื่อหลีกเลี่ยงstd::basic_string<>แต่ฉันทิ้งมันไว้ที่นี่เพื่อความเรียบง่าย


-1

คุณสามารถเขียนฟังก์ชั่นของคุณเอง:

void printVec(vector<char> vec){
    for(int i = 0; i < vec.size(); i++){
        cout << vec[i] << " ";
    }
    cout << endl;
}

-1

สำหรับผู้ที่ต้องการหนึ่งสมุทรโดยไม่ต้องลูป:

ฉันไม่อยากจะเชื่อเลยว่าจะไม่มีใครรู้เรื่องนี้ แต่อาจเป็นเพราะวิธีการแบบ C มากกว่านี้ อย่างไรก็ตามมีความปลอดภัยอย่างสมบูรณ์ในการทำสิ่งนี้โดยไม่ต้องวนซ้ำในแบบซับเดียวสมมติว่าstd::vector<char>สิ้นสุดด้วยค่า null:

std::vector<char> test { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\0' };
std::cout << test.data() << std::endl;

แต่ฉันจะห่อสิ่งนี้ในostreamโอเปอเรเตอร์ตามที่ @Zorawar แนะนำเพื่อความปลอดภัย:

template <typename T>std::ostream& operator<< (std::ostream& out, std::vector<T>& v)
{
    v.push_back('\0'); // safety-check!
    out << v.data();
    return out;
}

std::cout << test << std::endl; // will print 'Hello, world!'

เราสามารถบรรลุพฤติกรรมที่คล้ายกันโดยใช้printfแทน:

fprintf(stdout, "%s\n", &test[0]); // will also print 'Hello, world!'

บันทึก:

ostreamโอเปอเรเตอร์ที่โอเวอร์โหลดจำเป็นต้องยอมรับเวกเตอร์เป็น non-const สิ่งนี้อาจทำให้โปรแกรมไม่ปลอดภัยหรือแนะนำรหัสที่ใช้ไม่ได้ นอกจากนี้เนื่องจากตัวอักขระ null ถูกต่อท้ายการจัดสรรใหม่std::vectorอาจเกิดขึ้น ดังนั้นการใช้ลูปแบบวนซ้ำกับตัววนซ้ำจะเร็วขึ้น


1
1. fprintf(stdout, "%s\n", &test[0]);ไม่แตกต่างจากstd::cout << test.data()ทั้งคู่ต้องใช้เวกเตอร์ที่สิ้นสุดด้วยค่า null 2. "แต่ฉันจะห่อสิ่งนี้ไว้ในโอเปอร์เรเตอร์โอเปอเรเตอร์" <<ซึ่งเป็นการดัดแปลงโอเปอแรนด์ที่ถูกต้องเป็นความคิดที่แย่มาก
HolyBlackCat

ฉันใช้fprintf(stdout, "%s\n", &test[0]);รหัสเป็นเวลานานโดยที่ไม่เคยทำให้ฉันมีปัญหาใด ๆ ! ที่น่าสนใจ และฉันเห็นด้วยว่ามันไม่ดีนักที่จะปรับเปลี่ยนเวกเตอร์ในostreamโอเปอเรเตอร์ แต่ฉันไม่ชอบทั้งการวนลูปด้วยตนเองและการใช้ตัววนซ้ำ ยังไงก็เถอะฉันรู้สึกว่าสำหรับการดำเนินการอย่างง่ายเช่นการพิมพ์std::vector<char>ไลบรารีมาตรฐานควรซ่อนสิ่งเหล่านี้ออกไป แต่ C ++ กำลังพัฒนาอย่างต่อเนื่องมันอาจจะมาในไม่ช้า
ワイきんぐ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.