หน้าแรก  ก่อนหน้า

บทที่ 7

สายอักขระภาษา C++ มาตรฐาน
Standard C++ Strings


ในภาษา C++ มีสายอักขระภาษา C++ มาตรฐาน (standard C++ strings) ที่จัดการกับข้อมูลชนิดข้อความ การดำเนินการกับสายอักขระ C++ แตกต่างจากสายอักขระในภาษา C (C strings) โดยมีการรวมขนาดของสายอักขระเข้ากับข้อมูลข้อความ ทำให้ผู้เขียนโปรแกรมสามารถจัดการกับข้อมูลแต่ละอักขระในสายอักขระได้ง่ายขึ้น


7.1 ข้อมูลนำเข้าที่มีรูปแบบ

 

แนวคิดของสายข้อมูล (stream) ในภาษา C++ เปรียบเสมือนท่อส่งข้อมูล โดยสายข้อมูลนำเข้า (input stream) ไหลผ่านไปสู่วัตถุ istream และข้อมูลส่งออก (output stream) ไหลผ่านไปสู่วัตถุ ostream  โดยคลาส istream ได้นิยามวัตถุ cin เพื่อรองรับการนำเข้าข้อมูล ผ่านการกระทำของตัวดำเนินการดึงข้อมูล (extraction operator) ระบุโดยใช้เครื่องหมาย >> ตัวดำเนินดังกล่าวมีชื่อเรียกอีกชื่อว่า ตัวดำเนินการนำเข้า (input operator)

ตัวดำเนินการนำเข้า >> กระทำกับตัวถูกดำเนินการ 2 ตัว คือ วัตถุ istream ที่ผู้เขียนโปรแกรมต้องการดึงอักขระมาใช้งาน และ วัตถุที่ผู้เขียนโปรแกรมจะทำการคัดลอกอักขระไปเก็บ กระบวนการในการจัดรูปแบบของข้อมูลนำเข้าที่เป็นอักขระดิบ (raw characters) เรียกว่า การจัดรูปแบบ(formatting) ข้อมูลนำเข้าที่ผ่านการจัดรูปแบบแล้ว เรียกว่า formatted input

 


ตัวอย่าง 7.1  การดึงข้อมูลของตัวดำเนินการ >>

 

int n;

cin >> n;

cout << n;

 

 

ทดสอบโปรแกรม  เมื่อป้อนค่า ช่องว่าง 4 ช่องตามด้วย 46 แล้วเคาะ enter

 

 

46

 

 


จากตัวอย่าง ข้อมูลนำเข้าประกอบด้วยอักขระ 7 ตัว คือ ช่องว่างข้างหน้า 4 ตัว ตามด้วย 4 และ 6 และอักขระขึ้นบรรทัดใหม่ ('\n') ดังรูป 7-1 ในขณะที่อักขระเหล่านี้ไหลผ่านเข้าไปใน istream วัตถุ cin จะทำการตรวจสอบข้อมูลทีละหนึ่งตัวอักขระ ถ้าอักขระตัวแรกที่พบเป็นอักขระช่องว่าง (whitespace) ก็จะทำการดึงอักขระนั้นออกจาก istarem โดยจะไม่สนใจกับอักขระนั้น วัตถุ cin จะทำการตรวจสอบข้อมูลไปเรื่อย ๆ จนกว่าจะพบกับอักขระที่ไม่ใช่ช่องว่าง ซึ่งก็คือ เลข 4 (สำหรับตัวอย่างนี้) เนื่องจาก ตัวถูกดำเนินการอีกตัวของนิพจน์ cin >> n คือ ตัวแปร n ซึ่งมีข้อมูลชนิด int นั่นหมายความว่าวัตถุ cin จะต้องมองหาตัวเลขเพื่อจัดรูปให้เป็นเลขจำนวนเต็ม ดังนั้น หลังจากขจัดช่องว่างที่อยู่ข้างหน้าออกแล้ว วัตถุ cin คาดหวังที่จะได้รับอักขระหนึ่งใน 12 ตัว คือ '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' และ ในกรณีตัวอย่างนี้ได้ค่า '4' วัตถุ cin จะทำการดึงอักขระตัวนี้ออกมา และ ดำเนินการอ่านอักขระตัวต่อไป โดยคาดหวังว่าจะได้พบตัวเลข และ ตราบเท่าที่ยังพบอักขระที่เป็นตัวเลข ก็จะดึงอักขระนั้นไปเป็นส่วนหนึ่งของข้อมูลนำเข้า จนกว่าจะพบกับอักขระที่ไม่ใช่ตัวเลข จึงหยุดการดึงอักขระจาก istream ในตัวอย่าง วัตถุ cin จะดึงอักขระออกจาก istream ทั้งสิ้น 6 ตัว คือ ช่องว่างข้างหน้า 4 ตัว, อักขระ '4' และอักขระ '6' ซึ่งช่องว่างทั้งสี่ตัวจะไม่ได้รับความสนใจเหลือเพียงอักขระ '4' และ '6' วัตถุ cin จะทำการรวมอักขระทั้งสองเข้าด้วยกัน แล้วจัดรูปเป็นเลขจำนวนเต็ม 46 ก่อนที่จะคัดลอกค่านี้ให้กับตัวแปร n หลังจากการดึงอักขระใน istream เสร็จสิ้นแล้ว ตัวอักขระขึ้นบรรทัดใหม่ ('\n') จะยังคงอยู่ใน istream และถ้าคำสั่งต่อมาเป็นการนำเข้าข้อมูลที่มีรูปแบบ ตัวอักขระขึ้นบรรทัดใหม่ที่อยู่เดิมก็จะถูกละเลยไปเช่นเดียวกับช่องว่างตัวอื่น ๆ

 

 

 

 

 

รูป 7-1 สายส่งข้อมูลนำเข้า istream ที่ได้จากตัวอย่าง 7.1

 

ตัวดำเนินการนำเข้า >> จะทำการจัดรูปแบบของข้อมูลที่มันดึงจาก istream ให้มีค่าที่สอดคล้องกับชนิดข้อมูลของตัวดำเนินการที่กระทำคู่กัน การจัดการดึงข้อมูลในกระบวนการนี้มันจะละเลยช่องว่าง ที่อยู่หน้าอักขระที่มันต้องการใช้ ผลก็คือ ผู้เขียนโปรแกรมไม่สามารถใช้ตัวดำเนินการนำเข้า ในการอ่านอักขระช่องว่าง โดยถ้าผู้เขียนต้องการนำเข้าข้อมูลอักขระช่องว่าง จะต้องเลี่ยงไปใช้ฟังก์ชันการนำเข้าข้อมูลที่ไม่มีรูปแบบ (unformatted input function) แทน


ผลการทำงานของคำสั่ง ในภาษา C++

 

cin >> x ;

 

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


ตัวอย่าง 7.2  การใช้ผลการทำงานของตัวดำเนินการ >> ในการควบคุมการวนรอบ

 

int main()

{ int n;

   while (cin >> n)

      cout << "n = " << n << endl;

}

 

ทดสอบโปรแกรม  เมื่อป้อนค่า (46), (22 44 66 88) และ (33, 55, 77, 99) ตามลำดับ

 

 

46

n = 46

22 44 66 88

n = 22

n = 44

n = 66

n = 88

33, 55, 77, 99

n = 33

 

 

จากตัวอย่างใช้นิพจน์ cin >> x เป็นเงื่อนไขเพื่อควบคุมการทำงานของลูป โดยลูปจะยังคงทำงานต่อไปได้เรื่อยๆ ตราบเท่าที่สามารถดึงเลขจำนวนเต็มเป็นข้อมูลนำเข้าได้ การป้อนค่าเลขจำนวนจะใช้ช่องว่าง เป็นตัวคั่นอักขระ เครื่องหมาย , ที่อยู่หลัง 33 จะทำให้การทำงานของตัวดำเนินการนำเข้าล้มเหลว ส่งผลให้มีค่าเป็น false ทำให้ลูปหยุดการทำงาน




 

 

7.2 ข้อมูลนำเข้าที่ไม่มีรูปแบบ

 

 

ในไฟล์ส่วนหัว <iostream> มีนิยามของฟังก์ชันเพื่อนำเข้าข้อมูลที่ไม่มีรูปแบบอยู่หลายตัว ฟังก์ชันที่นิยมใช้ ได้แก่ ฟังก์ชัน cin.get ( ) ที่ใช้ในการนำเข้าอักขระ 1 ตัว และ ฟังก์ชัน cin.getline ( ) ที่ใช้นำเข้าสายอักขระ ทั้งฟังก์ชัน cin.get ( ) และ cin.getline ( ) จะคืนค่านิพจน์ชนิด bool ซึ่งจะมีค่าเป็น true ถ้าการนำเข้าข้อมูลประสบความสำเร็จ มิฉะนั้นก็จะคืนค่าที่เป็น false


ตัวอย่าง 7.3  การนำเข้าอักขระด้วยฟังก์ชัน cin.get ( )

 

int main()

{ char c;

   while (cin.get(c))

   {  if (c >= 'a' && c <= 'z') c += 'A' - 'a'; //capitalize c

           cout.put(c);

      if (c == '\n') break;

   }

}

 

ทดสอบโปรแกรม  เมื่อป้อนค่า Cogito, ergo sum!

 

 

Cogito, ergo sum!

COGITO, ERGO SUM!

 

 

การทำงานของลูปถูกควบคุมโดยนิพจน์นำเข้า cin.get (c) เมื่อวัตถุ cin ตรวจพบรหัสจบไฟล์ (เกิดจากการกดแป้น Ctrl+Z หรือ Ctrl+D) นิพจน์นำเข้าจะตีความเป็น false ทำให้ลูปจบการทำงาน การหยุดการทำงานของลูปอาจเกิดขึ้นจากคำสั่ง break ถ้าพบว่าตัวอักขระที่นำเข้าเป็นอักขระขึ้นบรรทัดใหม่ '\n' คำสั่ง cout.put (c) เป็นฟังก์ชันส่งออกอักขระหนึ่งตัวทางจอภาพ



ตัวอย่าง 7.4  การนำเข้าสายอักขระในภาษา C ด้วยฟังก์ชัน cin.getline ( )

 

const int LEN = 32;    //maximum word length

const int SIZE = 10;   //array size

typedef char Name[LEN];

int main()

{ Name king[SIZE];   //defines king to be array of 10 names

   int n = 0;

   while (cin.getline(king[n++], LEN) && n < SIZE) ;

   --n;

   for (int i = 0; i < n; i++)

      cout << '\t' << i + 1 << ". " << king[i] << endl;

}

 

ทดสอบโปรแกรม  

 

 

Kenneth II (971-995)

Constantine III (995-997)

Kenneth III (997-1005)

Malcolm II (1005-1034)

Duncan I (1034-1040)

Macbeth (1040-1057)

Lulach (1057-1058)

Malcolm III (1058-1093)

        2. Constantine III (995-997)

        3. Kenneth III (997-1005)

        4. Malcolm II (1005-1034)

        5. Duncan I (1034-1040)

        6. Macbeth (1040-1057)

        7. Lulach (1057-1058)

        8. Malcolm III (1058-1093)

 

 

วัตถุ king เป็นแถวลำดับของวัตถุ 10 ตัว ที่มีชนิดข้อมูลเป็น Name โดยที่ Name ได้รับการนิยามชนิดข้อมูลโดยคำสั่ง typedef ให้เป็นอีกชื่อหนึ่งของสายอักขระภาษา C ที่มีขนาด 32 ตัว (คือ มีอักขระที่ไม่ใช่ NUL ได้ 31 ตัว) การเรียกใช้ฟังก์ชัน cin.getline (king[n++], LEN) เป็นการอ่านอักขระจากวัตถุ cin จนกว่าจะดึงอักขระได้จำนวน LEN – 1 ตัว หรือ จนกว่าจะพบกับอักขระขึ้นบรรทัดใหม่ (แล้วแต่ว่าจะพบกับเงื่อนไขใดก่อน) หลังจากนั้น จะคัดลอกอักขระไปเก็บไว้ใน king[n] (ในกรณีที่พบอักขระขึ้นบรรทัดใหม่ อักขระขึ้นบรรทัดใหม่จะถูกดึง แต่ไม่นำไปรวมเข้าเป็นส่วนหนึ่งของข้อความ) จากนั้นจะเพิ่มค่าให้กับ n ไป 1 โดยลูปจะหยุดทำงานเมื่อ cin ตรวจพบอักขระการจบไฟล์ หรือ เมื่อ n มีค่าเท่ากับ SIZE เนื่องจาก n เริ่มที่ 0 และจะเพิ่มขึ้นอีก 1 ดังนั้น หลังจากอ่านชื่อสุดท้าย จะต้องลดค่า n ลง 1 เพื่อให้ n มีค่าเท่ากับจำนวนชื่อที่อ่านเข้ามา ให้สังเกตุว่า ในบล็อกของลูป while เป็นบล็อกว่าง ๆ ไม่มีคำสั่ง


7.3 ชนิดสายอักขระในภาษา C++ มาตรฐาน

 

ในภาษา C++ มีการนิยามข้อมูลชนิด string ในไฟล์ส่วนหัวชื่อ <string> การประกาศ และกำหนด ค่าเริ่มแรกของวัตถุชนิด string สามารถทำได้หลายรูปแบบ ดังตัวอย่าง


ตัวอย่าง 7.5  การประกาศและกำหนดค่าเริ่มแรกของ string

 

int main()

{ string s1;              //s1 contains 0 character

   string s2 = "New York"; //s2 contains 8 characters

   string s3(10, '*');     //s3 contains 10 characters

   string s4 = s3;         //s4 contains 10 characters

   string s5(s2,4,2);      //s5 contains 2 characters

   cout << "s1: " << s1 << endl;

   cout << "s2: " << s2 << endl;

   cout << "s3: " << s3 << endl;

   cout << "s4: " << s4 << endl;

   cout << "s5: " << s5 << endl;

}

 

ทดสอบโปรแกรม  

 

 

s1:

s2: New York

s3: **********

s4: **********

s5: Yo

 

 


จากตัวอย่าง ประกาศตัวแปร s1 เป็นชนิด string โดยไม่มีการกำหนดค่าเริ่มต้นให้ s1 ทำให้ s1 มีค่าเป็น “” (null string) s2 ถูกประกาศ และ กำหนดค่าเริ่มต้นให้เป็นข้อความมีอักขระ 8 ตัว คือ “New York”       s3 ถูกประกาศ และ กำหนดค่าเริ่มต้นให้เป็นข้อความที่มีอักขระ * จำนวน 10 ตัว s4 ถูกประกาศ และ กำหนดค่าเริ่มต้นให้เป็นข้อความเดียวกับสายอักขระ s3 และ s5 ถูกประกาศ และ กำหนดค่าเริ่มต้นให้เป็นข้อความที่คัดลอกจากสายอักขระ s2 ตั้งแต่ตัวที่ 4 นำมา 2 ตัว ได้เป็นสายอักขระ “Yo” (ลำดับตัวอักขระในสายอักขระเริ่มนับที่ตำแหน่ง 0)

ในภาษา C++ ผู้เขียนโปรแกรมสามารถใช้ฟังก์ชัน getline ( ) กับข้อมูลชนิด string ได้เช่นเดียวกับสายอักขระในภาษา C ฟังก์ชัน substr ( ) เป็นฟังก์ชันที่คัดลอกข้อความในสายอักขระภาษา C++ และ  การเปรียบเทียบสายอักขระสามารถทำได้ โดยจะเปรียบเทียบค่าอักขระทีละตัวตั้งแต่ตัวที่ 0 เป็นต้นไป


ตัวอย่าง 7.6  การใช้ฟังก์ชันกับสายอักขระใน C++

 

int main()

{ string s;

   getline(cin, s);

   cout << "s: " << s << "  lenght = " << s.length( ) << endl;

   char ch = s[2];

   s[4] = '*';

   cout << "ch: " << ch << "  s: " << s << endl;

   string s2 = s.substr(3,4);

   cout << "s2: " << s2 << endl;

   if (s2 <= s) cout << "s2 is lower than s\n";

   else cout << "s2 is greater than s\n";

}

 

ทดสอบโปรแกรม  เมื่อป้อนค่า s เป็น ABCDEFG

 

 

ABCDEFG

s: ABCDEFG  lenght = 7

ch: C  s: ABCD*FG

s2: D*FG

s2 is greater than s

 

 


เครื่องหมาย + ถ้ากระทำกับข้อมูลชนิด string จะหมายถึง ตัวดำเนินการเชื่อมต่อสายอักขระ ฟังก์ชัน erase ( ) เป็นฟังก์ชันในการลบส่วนของสายอักขระออกจากสายอักขระหลัก ฟังก์ชัน replace ( ) เป็นฟังก์ชันในการลบส่วนของสายอักขระเดิมแล้วแทนที่ส่วนของสายอักขระใหม่ในสายอักขระหลัก และสุดท้าย ฟังก์ชัน find ( ) เป็นฟังก์ชันในการค้นหาตำแหน่งของส่วนของสายอักขระในสายอักขระหลัก โดยถ้าพบ จะคืนค่าของตำแหน่งแรกที่พบ แต่ถ้าไม่พบ จะคืนค่าเป็นขนาดของสายอักขระหลักที่ถูกสืบค้น


ตัวอย่าง 7.7  การใช้ฟังก์ชันกับสายอักขระใน C++ ต่อ

 

int main()

{ string s1 = "ABCDEFG";

   string s2 = "xyz";

   string s3 = s1 + s2;

   s1 += s2;

   cout << "s1: " << s1 << "  s3: " << s2 << endl;

   s3.erase(4,2);

   s1.replace(4,2,s2);

   cout << "s1: " << s1 << "  s3: " << s2 << endl;

   cout << "find s2 in s1 = " << s1.find(s2) << endl;

   cout << "find \"EF\" in s1 = " << s1.find("EF") << endl;

}

 

ทดสอบโปรแกรม  

 

 

s1: ABCDEFGxyz  s3: xyz

s1: ABCDxyzGxyz  s3: xyz

find s2 in s1 = 4  

find "EF" in s1 = 11

 

 


ตัวอย่าง 7.8  การใช้งานข้อมูลชนิด string

 

bool is_vowel(char c)

{ if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'     

    || c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U')

       return true;

   return false;

}

int main()

{ string word;

   int k;

   while (cin >> word)

   { k = word.find("t") + 1;

      if (k < word.length() && is_vowel(word[k]))

            word.replace(k, 0, "eg");

      cout << word << ' ';

   }

}

 

ทดสอบโปรแกรม  เมื่อป้อนค่า The first step is to study the status of the C++ standard.

 

 

The first step is to study the status of the C++ standard.

The first stegep egis tego stegudy the stegatus egof the C++ stegandard.

 

 

โปรแกรมตัวอย่างจะทำการแทรกสายอักขระ “eg” เข้าไปในคำที่พบว่ามีอักขระ ‘t’ อยู่หน้าตัวอักขระสระ (‘A’, ‘E’, ‘I’, ‘O’, ‘U’, ‘a’, ‘e’, ‘i’, ‘o’ และ ‘u’) โปรแกรมจะนำเข้าข้อมูลทีละคำ (ตรวจสอบจากอักขระ ‘ ‘ หรือ ‘\n’) และ สิ้นสุดการวนรอบเมื่อพบอักขระจบไฟล์ (นิพาจน์ cin >> word จะให้ผลเป็นเท็จ)



7.4 ไฟล์

 

การจัดการไฟล์ (file) ในภาษา C++ มีการทำงานเหมือนกับการจัดการนำเข้าข้อมูลจากแป้นพิมพ์ และ ส่งออกข้อมูลทางจอภาพ โดยการรับค่าจากไฟล์ จะทำงานผ่านวัตถุ ifstream เหมือนกับที่ การนำเข้าข้อมูลจากแป้นพิมพ์ทำงานผ่านวัตถุชื่อ cin ของ istream ส่วนการบันทึกค่าลงไฟล์ จะทำงานผ่านวัตถุ ofstream เหมือนกับที่ การส่งออกข้อมูลทางแป้นพิมพ์ทำงานผ่านวัตถุ ชื่อ cout ของ ostream โดย istream และ ostream เป็นสายข้อมูลที่นิยามในไฟล์ส่วนหัว <fatream> (หรือ <fstraem.h>) ซึ่งต้องมีการประกาศ พร้อมทั้งระบุชื่อของไฟล์ที่มีการจัดเก็บในหน่วยความจำสำรองด้วย


ตัวอย่าง 7.9  เปลี่ยนคำทุกคำในไฟล์ข้อความให้ขึ้นต้นด้วยอักขระตัวพิมพ์ใหญ่

 

#include <fstream>

#include <iostream>

using namespace std;

int main()

{ ifstream infile("input.txt");

   ofstream outfile("output.txt");

   string word;

   char c;

   while (infile >> word)

   {  if (word[0] >= 'a' && word[0] <='z') word[0] += 'A' - 'a';

      outfile << word;

      infile.get(c);

      outfile.put(c);

   }

}

 

ข้อมูลในไฟล์ input.txt

 

 

I love C++ programming. It is fun learning

how to programming.

 

 


ข้อมูลในไฟล์ output.txt

 

 

I Love C++ Programming. It Is Fun Learning

How To Programming.

 

 

ในโปรแกรมตัวอย่างมีวัตถุทั้งสิ้น 4 ตัว คือ ifstream และ ofstream ซึ่งเป็นวัตถุที่นิยามโดยภาษา C++ ส่วนวัตถุอีก 2 ตัว คือ infile และ outfile เป็นวัตถุที่สร้างโดยผู้เขียนโปรแกรม โดยประกาศให้ infile เป็นวัตถุที่ดำเนินการกับสายข้อมูลนำเข้า ifstream ที่รับค่าจากไฟล์ ชื่อ “input.txt” ในหน่วยความจำสำรอง และ ประกาศให้ outfile เป็นวัตถุที่ดำเนินการกับสายข้อมูลส่งออก ofstream ที่จะบันทึกค่าลงไฟล์ ชื่อ “output.txt” ในหน่วยความจำสำรอง ให้สังเกตุว่า จากตัวอย่าง infile จะมีการจัดการเหมือน cin ในขณะที่ outfile จะมีการจัดการเหมือน cout เพียงแต่การดำเนินการเกิดขึ้นกับสายข้อมูลคนละตัว


ตัวอย่าง 7.10  การรวมข้อมูลในไฟล์สองไฟล์

 

bool more(ifstream& fin, int& n)

{ if (fin >> n) return true;

   else return false;

}

bool copy(ofstream& fout, ifstream& fin, int& n)

{ fout << " " << n;

   return more(fin, n);

}

int main()

{ ifstream fin1("north.dat");

   ifstream fin2("south.dat");

   ofstream fout("combined.dat");

   int n1, n2;

   bool more1 = more(fin1, n1);

   bool more2 = more(fin2, n2);

   while (more1 && more2)

      if (n1 < n2) more1 = copy(fout, fin1, n1);

      else copy(fout, fin2, n2);

   while (more1)

      more1 = copy(fout, fin1, n1);

  


while (more2)

      more2 = copy(fout, fin2, n2);

   fout << endl;

}

 

ข้อมูลในไฟล์ north.txt

 

 

20 22 26 37 45

 

 

ข้อมูลในไฟล์ south.txt

 

 

15 23 25 29

 

 

ข้อมูลในไฟล์ combined.txt

 

 

15 20 22 23 25 26 29 37 45

 

 

ฟังก์ชัน more ( ) ใช้เพื่ออ่านข้อมูลจากไฟล์นำเข้า การเรียกใช้ฟังก์ชันนี้ในแต่ละครั้ง จะทำการอ่านค่าเลขจำนวนเต็ม  1 ตัวจากไฟล์ fin ให้กับตัวแปร n ซึ่งเป็นพารามิเตอร์ที่ส่งผ่านโดยการอ้างอิง (เปลี่ยนค่าได้) และ ฟังก์ชันจะคืนค่ากลับเป็น true ถ้าการอ่านนั้นประสบความสำเร็จ มิฉะนั้น ก็คืนค่ากลับเป็น false

ฟังก์ชัน copy ( ) จะเขียนค่าของ n ลงในไฟล์ fout จากนั้นจะเรียกใช้ฟังก์ชัน more ( ) เพื่ออ่านตัวเลขตัวถัดไปจากไฟล์ fin ให้แก่ n และ จะคืนค่ากลับเป็น true ถ้าการอ่านค่าประสบความสำเร็จ มิฉะนั้น ก็คืนค่ากลับเป็น false

 

การเรียกใช้ฟังก์ชัน more ( ) สองครั้งแรกเป็นการอ่านค่า 22 และ 20 ให้แก่ n1 และ n2 ตามลำดับ ซึ่งทั้งสองครั้งจะคืนค่ากลับเป็น true ทำให้ลูป while ตัวแรกเริ่มทำงาน ในการทำงานรอบแรกของ while เงื่อนไข ( n1 < n2) เป็น false ดังนั้นฟังก์ชัน copy ( ) จะทำการคัดลอกค่า 20 ลงในไฟล์ combined.dat แล้วเรียกใช้ฟังก์ชัน more ( ) อีกครั้งซึ่งจะเป็นการอ่านค่า 30 จากไฟล์ south.dat ให้แก่ n2  ในการทำงานรอบที่ 2 เงื่อนไข (n1 < n2) เป็น true (เนื่องจาก 22 < 30) ดังนั้นฟังก์ชัน copy ( ) ก็จะทำการคัดลอกค่า 22 ของ n1 ลงในไฟล์ combined.dat จากนั้นจะเรียกใช้ฟังก์ชัน more ( ) เพื่ออ่านค่า 25 จากไฟล์ north.dat ให้แก่ n1

การทำงานในรอบต่อมาจะเขียนค่า 30 ลงในไฟล์ combined.dat จากนั้นก็จะอ่านค่า 33 จากไฟล์ south.dat ให้แก่ n2

 

กระบวนการดังกล่าวนี้ จะดำเนินต่อไปจนกระทั่ง หลังจากการเขียนค่า 85 ของ n2 ลงในไฟล์ combined.dat การเรียกใช้ฟังก์ชัน more ( ) ครั้งถัดมาล้มเหลว เนื่องจาก ค่า 85 เป็นข้อมูลตัวสุดท้ายของไฟล์ ฟังก์ชันจะคืนค่า false ให้ตัวแปร more2 ซึ่งจะเป็นการหยุดทำงานของลูป while ตัวแรก จากนั้นก็จะเป็นการทำงานของลูป while ตัวที่ 2 จำนวน 3 รอบเพื่อทำการคัดลอกค่า 3 ค่าที่เหลือในไฟล์ north.dat ลงในไฟล์ combined.dat ก่อนที่จะกำหนดค่าให้ more1 เป็น false โดยลูปของ while ตัวที่สามจะไม่มีการทำงานเกิดขึ้น

หมายเหตุ วัตถุที่เป็นไฟล์ เช่น fin1, fin2 และ fout จะถูกส่งผ่านไปในฟังก์ชันในลักษณะเดียวกับการส่งผ่านวัตถุอื่น ๆ อย่างไรก็ดี ในการจัดการกับไฟล์ ผู้เขียนโปรแกรมจะต้องส่งผ่านข้อมูลไฟล์แบบโดยการอ้างอิงเสมอ

 


7.5 String Streams

 

string streams คือ วัตถุของสายข้อมูลที่อนุญาตให้ใช้สายอักขระได้เสมือนหนึ่งเป็นไฟล์ข้อความภายใน (internal text file) บางครั้งเรียกว่า การนำเข้าและส่งออกข้อมูลในหน่วยความจำ (in-memory input/output)

ประโยชน์ คือ ผู้เขียนโปรแกรมสามารถใช้ string streams ในการสำรองเป็นบัฟเฟอร์ของข้อมูลนำเข้าและส่งออก ประเภทวัตถุของ string streams คือ    istringstream และ ostringstream ซึ่งมีนิยามอยู่ในไฟล์ส่วนหัว <sstream>


ตัวอย่าง 7.11  การใช้ข้อมูลส่งออก string stream

 

#include <sstream>

#include <string>

#include <iostream>

using namespace std;

int main()

{ ostringstream oss;

   int n = 44;

   float x = 3.14;

   oss << "Hello!\t" << n << '\t' << x;

   string s = oss.str();  //copies the stream's string to s

   oss << '\t' << &n;

}

 


ทดสอบโปรแกรม  

 

 

n = 44

x = 3.14

s = “Hello!\t44\t3.14”

oss = “Hello!\t44\t3.14\t64fddc”

 

 

วัตถุ oss เป็นวัตถุของ output string stream ซึ่งจะทำหน้าที่เหมือนเป็นท่อส่งข้อมูลให้แก่สายอักขระที่ไม่มีชื่อ ตัวดำเนินการ << จะทำการบรรจุสายอักขระคงที่ "Hello!\t" ลงใน oss

 คำสั่ง oss << n จะทำการบรรจุค่า n ลงใน oss

 จากนั้น คำสั่ง oss << ‘\t’ << x จะทำการบรรจุอักขระจุดตั้งระยะ แล้วตามด้วยค่า x ลงใน oss ผู้เขียนโปรแกรมสามารถนำข้อมูลสายอักขระของ string stream ออกมาเพื่อใช้งาน ได้โดยใช้ฟังก์ชัน oss.str ( )

หมายเหตุ  &n เป็นการเรียกใช้ค่าเลขที่อยู่ของตัวแปร n


ตัวอย่าง 7.12  (ต่อจาก โปรแกรมตัวอย่าง 7.11)

 

const string buffer = oss.str();

istringstream iss(buffer); //binds the stream iss to the string

string word;

int m;

float y;

iss >> word >> m >> y;

char c = buffer[16];

iss >> word;

 

ทดสอบโปรแกรม  

 

 

buffer = “Hello!\t44\t3.14\t64fddc”

word = “Hello”

m = 44

y = 3.14

c = ‘f’

word = “64fddc”

 

 

คำสั่งแรก จะทำการนำข้อมูลใน string stream ตัวปัจจุบันไปเก็บในตัวแปร buffer หลังจากนั้น ประกาศ iss ให้เป็น input string stream ที่ผูกกับข้อมูลใน buffer คำสั่ง iss >> word >> m >> y จะนำค่าจาก  input string stream ตัวปัจจุบัน ซึ่งก็คือ ค่าใน buffer มาใส่ในตัวแปร word, m และ y ตามลำดับ


แบบฝึกหัด

 

1.  จงบอกข้อแตกต่างระหว่างข้อมูลนำเข้าที่มีรูปแบบ และ ข้อมูลนำเข้าที่ไม่มีรูปแบบ?

 

2.  สายข้อมูล คืออะไร?

 

3.  จงอธิบายการทำงานของฟังก์ชัน read ( ) และ write ( ) ในภาษา C++?

 

4.  จงอธิบายผลการทำงานของคำสั่ง ต่อไปนี้

 

char cs1[] = "ABCDEFGHIJ";

char cs2[] = "ABCDEFGH";

cout << cs2 << endl;

cout << strlen(cs2) << endl;

cs2[4] = 'X';

if (strcmp(cs1,cs2) < 0) cout << cs1 << " < " << cs2 << endl;

else cout << cs1 << " >= " << cs2 << endl;

char buffer[80];

strcpy(buffer, cs1);

strcat(buffer, cs2);

char* cs3 = strchr(buffer, 'G');

cout << cs3 << endl;

 

5.  จงอธิบายผลการทำงานของคำสั่ง ต่อไปนี้

 

string s = "ABCDEFGHIJKLMNOP";

cout << s << s.length( ) << endl;

s[8] = '!';

s.replace(8,5,"xyz");

s.erase(6,4);

cout << s.find("!") << s.find("?") << s.substr(6,3);

s += "abcde";

string part(s,4,8);

string stars(8,'*');

6.  จงหาผลการทำงานของส่วนคำสั่งที่กำหนดให้ ต่อไปนี้

string s;

int n;

float x;

cin >> s >> n >> x >> s;

 

เมื่อป้อนค่าต่อไปนี้ทางแป้นพิมพ์

 

6.1   ABC 456 7.89  XYZ

6.2  ABC 4567 .89  XYZ

6.3  ABC 456 7.8  9XYZ

6.4  ABC456 7.8 9  XYZ

6.5  ABC456 7 .89  XYZ

6.6  ABC4 56 7.89XY Z

6.7  AB C456 7.89  XYZ

6.8  AB C 456  7.89XYZ

 

7.  จงพัฒนาโปรแกรมภาษา C++ ทำการนับจำนวนคำ และ จำนวนบรรทัดของข้อความที่รับผ่านแป้นพิมพ์ แสดงผลลัพธ์ที่ได้ทางจอภาพ

 

8.  จงพัฒนาโปรแกรมภาษา C++ ทำการนับจำนวนคำ และ จำนวนบรรทัดของข้อความในไฟล์ชื่อ “input.txt” แสดงผลลัพธ์ที่ได้ทางจอภาพ

 

9.  จงพัฒนาโปรแกรมภาษา C++ เพื่ออ่านชื่อรูปเต็มทีละบรรทัดจากไฟล์ชื่อ “namelist.txt” แล้วทำแปลงชื่อให้อยู่ในรูปแบบการแสดงชื่อในสมุดโทรศัพท์ บันทึกลงในไฟล์ชื่อ “phonelist.txt”

 

     สมมติว่า ข้อมูลใน namelist.txt มีค่าเป็น

 

Johann Sebastian Bach

George Frederic Handel

Carl Phillipp Emanuel Bach

Joseph Haydn

Johann Christian Bach

Wolf Gang Amadeus Mozart

 


จะได้ข้อมูลในไฟล์ phonelist.txt

 

Bach, Johann S.

Handel, George F.

Bach, Carl P.E.

Haydn, Joseph

Bach, Johann C.

Mazart, Wolfgang A.

 

10.  จงพัฒนาและทดสอบฟังก์ชัน reverseString ( ) รับสายอักขระเป็นพารามิเตอร์ แล้วเปลี่ยนข้อความในสายอักขระเป็นข้อความย้อนกลับ เช่น สายอักขระ “hello” จะแปลงเป็น “olleh”

           

void reverseString(string& s);

 

11.  จงพัฒนาและทดสอบฟังก์ชัน isPalindrome ( ) ทำการตรวจสอบสายอักขระว่าเป็นพารินโดรมหรือไม่ เช่น สายอักขระ “radar” จะได้ค่า true เนื่องจาก “radar” เท่ากับ “radar” แสดงว่าเป็นพารินโดรม ในขณะที่ “abcd” จะได้ค่าเท็จ เนื่องจาก “abcd” ไม่เท่ากับ “dcba” แสดงว่าไม่เป็นพารินโดรม

 

          void isPalindrome (string s);

 


หน้าแรก  ก่อนหน้า