ฉันจะสร้างไฟล์บันทึกสำหรับเกม C ++ ได้อย่างไร


33

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


มีความเป็นไปได้ที่ซ้ำกันของวิธีสร้างรูปแบบไฟล์บันทึกเกมใน c ++ โดยใช้ STL
Ali1S232

2
คุณยังสามารถใช้ SQLite
Nick Shvelidze

1
@Shvelo ในขณะที่คุณสามารถทำได้ดูเหมือนว่ามันจะเพิ่มความซับซ้อนมากมายที่ไม่จำเป็น
เนท

คำตอบ:


38

คุณต้องใช้การจัดลำดับเพื่อบันทึกตัวแปรในหน่วยความจำลงในฮาร์ดไดรฟ์ของคุณ มีหลายประเภทของการทำให้เป็นอันดับใน. NET XML เป็นรูปแบบทั่วไปแม้ว่าจะมี binary และ JSON serializers ใช้ได้ ฉันไม่ได้เป็นโปรแกรมเมอร์ C ++ มากนัก แต่การค้นหาอย่างรวดเร็วได้เปิดตัวอย่างในการทำให้เป็นอนุกรมใน C ++:

มีห้องสมุดที่เสนอฟังก์ชันการทำให้เป็นอันดับ บางคนกล่าวถึงในคำตอบอื่น ๆ

ตัวแปรที่คุณจะสนใจนั้นอาจจะเกี่ยวข้องกับสถานะของเกม ตัวอย่างเช่นคุณอาจต้องการทราบข้อมูลประเภทนี้

  1. ผู้เล่นกำลังเล่นระดับ 3
  2. ผู้เล่นอยู่ที่พิกัด X, Y โลก
  3. ผู้เล่นมีสามรายการในกระเป๋าเป้สะพายหลังของเขา
    1. อาวุธ
    2. เกราะ
    3. อาหาร

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

เมื่อคุณเริ่มเกมของคุณคุณจะเริ่มเกมตามปกติสำหรับเกม "ใหม่" (สิ่งนี้จะโหลดพื้นผิวแบบจำลองของคุณ ฯลฯ ) แต่ในเวลาที่เหมาะสมคุณจะโหลดค่าจากไฟล์บันทึกของคุณกลับไปเป็นวัตถุสถานะเกมแทน "ค่าเริ่มต้น" ใหม่ สถานะเกม จากนั้นคุณอนุญาตให้ผู้เล่นกลับมาเล่นต่อ

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


ฉันเข้าใจสิ่งที่ฉันต้องการบันทึก แต่สิ่งที่ฉันต้องการทราบว่าเป็นวิธีที่แน่นอนคุณบันทึกไปยังไฟล์. txt ในโครงการตัวแปรที่ปรับเปลี่ยนเหล่านั้นหรือวิธีอื่น ๆ
Tucker Morgan

ใช่ถ้าเกมของคุณง่ายไฟล์ข้อความอาจจะเพียงพอ คุณต้องจำไว้ว่าทุกคนสามารถแก้ไขไฟล์ข้อความและทำให้ตัวเองบันทึกเกม ...
Nate

การบันทึกไฟล์ข้อความไม่ได้มีไว้สำหรับเกมง่ายๆ Paradox ใช้รูปแบบข้อความที่มีโครงสร้างสำหรับบันทึกไฟล์สำหรับเกมทั้งหมดที่สร้างขึ้นโดยใช้เอนจิ้นเดียวกับเครื่องยนต์ Europa Universalis โดยเฉพาะช่วงท้ายเกมไฟล์เหล่านี้อาจมีขนาดใหญ่มาก
Dan Neely

1
@DanNeely จุดยุติธรรมไม่มีเหตุผลที่คุณไม่สามารถใช้รูปแบบข้อความเพื่อเก็บข้อมูลที่ซับซ้อนมากมาย แต่โดยทั่วไปเมื่อข้อมูลของคุณมีความซับซ้อนประโยชน์ของรูปแบบอื่น (ไบนารี xml ฯลฯ ) จะเด่นชัดกว่า
Nate

1
@NateBross เห็นด้วย เกม Paradox นั้นมีความเป็นมิตรมากและใช้รูปแบบที่เหมือนกัน (เหมือนกันหรือไม่) สำหรับข้อมูลสถานการณ์ การจัดเก็บข้อมูลส่วนใหญ่เป็นข้อความหมายความว่าพวกเขาไม่จำเป็นต้องลงทุนในเครื่องมือแก้ไขสถานการณ์จำลองสำหรับการใช้งานสาธารณะ
Dan Neely

19

โดยทั่วไปนี่เป็นเฉพาะเกมของคุณ ฉันแน่ใจว่าคุณได้เรียนรู้เกี่ยวกับการเขียนและอ่านจากไฟล์ในชั้นเรียนของคุณแล้ว แนวคิดพื้นฐานคือ:

  1. เมื่อออกจากเกมให้เขียนค่าที่คุณต้องการบันทึกลงในไฟล์
  2. เมื่อโหลดเกมให้ตรวจสอบว่ามีไฟล์บันทึกอยู่หรือไม่ให้โหลดค่าที่อ่านเข้าในโปรแกรมของคุณ หากไฟล์ไม่มีอยู่ให้ดำเนินการเหมือนที่คุณทำตอนนี้และตั้งค่าเป็นค่าเริ่มต้น / ค่าเริ่มต้น

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

ตัวอย่างเช่น (ในรหัสหลอกอย่างรวดเร็ว):

SaveGame(FileInput file) {
    file.writeInt(playerLevel);
    file.writeInt(playerHealth);
    file.writeInt(gameProgress);
}

LoadGame(FileInput file) {
    if(file.exists()) {
        playerLevel= file.readInt();
        playerHealth = file.readInt();
        gameProgress = file.readInt();
    } else {
        playerLevel = 1;
        playerHealth = 100;
        gameProgress = 0;
    }
}

1
วิธีนี้ดีและเล็ก แต่ฉันขอแนะนำให้ใส่แท็กง่ายๆสำหรับกลุ่มข้อมูล ด้วยวิธีนี้หากคุณต้องการเปลี่ยนแปลงสิ่งที่ตามปกติในช่วงกลางของไฟล์คุณสามารถทำได้และ "การแปลงจากเก่า" เท่านั้นที่คุณต้องทำคือภายในหนึ่งช่วงตึก มันไม่สำคัญเท่าไรสำหรับการมอบหมายครั้งเดียว แต่ถ้าคุณทำงานต่อไปหลังจากที่ผู้คนเริ่มได้รับการบันทึกไฟล์มันเป็นฝันร้ายเพียงแค่ใช้ไบต์ตรงกับตำแหน่งที่เป็นตัวระบุเท่านั้น
Lunin

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

6

อาจมีหลายวิธีในการทำสิ่งนี้ แต่สิ่งที่ง่ายที่สุดที่ฉันพบเสมอและใช้ทั้งส่วนตัวและมืออาชีพคือการสร้างโครงสร้างที่มีค่าทั้งหมดที่ฉันต้องการบันทึก

struct SaveGameData
{
    int              characterLevel; // Any straight up values from the player
    int              inventoryCount; // Number of items the player has on them or stored or what not
    int[STAT_COUNT]  statistics;     // This is usually a constant size (I am tracking X number of stats)
    // etc
}

struct Item
{
    int itemTypeId;
    int Durability; // also used as a 'uses' count for potions and the like
    int strength;   // damage of a weapon, protection of armor, effectiveness of a potion
    // etc
}

ฉันเพียงแค่เขียน / fread ข้อมูลไปยังและจากไฟล์โดยใช้ค่า File IO พื้นฐาน InventoryCount คือจำนวนของโครงสร้างรายการที่บันทึกไว้หลังจากโครงสร้าง SaveGameData หลักในไฟล์ดังนั้นฉันจึงรู้ว่ามีกี่รายการที่ต้องอ่านหลังจากดึงข้อมูลนั้น กุญแจสำคัญคือเมื่อฉันต้องการบันทึกสิ่งใหม่เว้นแต่ว่าจะมีรายการของรายการหรือสิ่งที่ชอบสิ่งที่ฉันต้องทำคือเพิ่มมูลค่าให้กับโครงสร้างบางที่ หากรายการของรายการนั้นฉันจะต้องเพิ่มการอ่านผ่านเหมือนฉันได้โดยนัยแล้วสำหรับวัตถุรายการเคาน์เตอร์ในส่วนหัวหลักและจากนั้นรายการ

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

อีกไม่กี่วิธีในการทำสิ่งนี้และสิ่งนี้อาจนำไปสู่ ​​C มากกว่า C ++ แต่มันทำให้งานเสร็จ!


1
นอกจากนี้ยังเป็นที่น่าสังเกตว่านี่ไม่ได้เป็นแพลตฟอร์มอิสระจะไม่ทำงานกับสตริง C ++ หรือสำหรับวัตถุที่อ้างถึงผ่านการอ้างอิงหรือพอยน์เตอร์หรือวัตถุใด ๆ ที่มีองค์ประกอบใด ๆ ข้างต้น!
Kylotan

ทำไมแพลตฟอร์มนี้จึงไม่ขึ้นกับใคร มันทำงานได้ดีบนพีซีระบบ PS * และ 360 .. fwrite (pToDataBuffer, sizeof (ประเภทข้อมูล), countOfElements, pToFile); เหมาะสำหรับวัตถุทั้งหมดที่สมมติว่าคุณสามารถรับตัวชี้ไปยังข้อมูลและขนาดของวัตถุจากนั้นจำนวนของวัตถุที่คุณต้องการเขียน .. และอ่านการจับคู่ที่ ..
James

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

3
ที่จริงแล้วไม่มีอะไรรับประกันได้ว่ามันจะทำงานให้คุณตลอดไป - จะเกิดอะไรขึ้นถ้าคุณปล่อยเวอร์ชั่นใหม่ที่สร้างขึ้นด้วยคอมไพเลอร์ใหม่หรือแม้แต่ตัวเลือกการคอมไพล์ใหม่ที่เปลี่ยนโครงสร้างแพ็ด? ฉันขอปฏิเสธการใช้ raw-struct fwrite () อย่างแรงด้วยเหตุผลนี้เพียงอย่างเดียว (ฉันกำลังพูดจากประสบการณ์เกี่ยวกับสิ่งนี้โดยบังเอิญ)
ปุย

1
มันไม่เกี่ยวกับ '32 บิตของข้อมูล ' โปสเตอร์ต้นฉบับขอแค่ "ฉันจะบันทึกตัวแปรของฉันได้อย่างไร" หากคุณเขียนตัวแปรโดยตรงคุณจะสูญเสียข้อมูลข้ามแพลตฟอร์ม หากคุณต้องประมวลผลล่วงหน้าก่อนการเขียนคุณก็จะต้องละทิ้งส่วนที่สำคัญที่สุดของคำตอบนั่นคือ วิธีการประมวลผลข้อมูลเพื่อให้บันทึกได้อย่างถูกต้องและรวมบิตที่ไม่สำคัญเช่น การเรียก fwrite เพื่อวางบางสิ่งบนดิสก์
Kylotan

3

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

ถัดไปเขียนรหัสเพื่อบันทึกสิ่งนี้ลงในไฟล์ (ใช้กระแสข้อมูล) รูปแบบที่ค่อนข้างง่ายที่คุณสามารถใช้ได้มีดังนี้:

x y score coins

ดังนั้นไฟล์จะมีลักษณะดังนี้:

14 96 4200 100

ซึ่งหมายความว่าเขาอยู่ในตำแหน่ง (14, 96) ด้วยคะแนน 4200 และ 100 เหรียญ

คุณต้องเขียนโค้ดเพื่อโหลดไฟล์นี้ (ใช้ ifstream)


การบันทึกศัตรูสามารถทำได้โดยรวมถึงตำแหน่งของพวกเขาในไฟล์ เราสามารถใช้รูปแบบนี้:

number_of_enemies x1 y1 x2 y2 ...

ก่อนอื่นให้number_of_enemiesอ่านจากนั้นอ่านแต่ละตำแหน่งด้วยการวนซ้ำอย่างง่าย


1

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


0

ฉันคิดว่าทางออกที่ดีที่สุดของคุณคือ boost :: serialization เพราะง่ายต่อการเผยแพร่ในลำดับชั้นของคุณ คุณจะต้องเรียกใช้ฟังก์ชันบันทึก / โหลดบนสุดของวัตถุและคลาสทั้งหมดของคุณจะถูกสร้างขึ้นอย่างง่ายดาย

ดู: http://www.boost.org/doc/libs/1_49_0/libs/serialization/doc/index.html


0

เพื่อความสมบูรณ์ฉันต้องการพูดถึงไลบรารี่อนุกรม c ++ ที่ฉันใช้เป็นการส่วนตัวและยังไม่ได้กล่าวถึง: ซีเรียล
มันใช้งานง่ายและมีไวยากรณ์ที่ดีและสะอาดสำหรับการทำให้เป็นอนุกรม นอกจากนี้ยังมีรูปแบบหลายรูปแบบที่คุณสามารถบันทึกลงใน (XML, Json, Binary (รวมถึงรุ่นพกพาที่มีความเคารพ)) สนับสนุนการสืบทอดและเป็นส่วนหัวเท่านั้น


0

เกมของคุณจะประนีประนอมโครงสร้างข้อมูล (หวังว่า?) ที่คุณต้องการแปลงเป็นไบต์ (เป็นอันดับ) เพื่อให้คุณสามารถเก็บไว้ ในอนาคตคุณสามารถโหลดไบต์เหล่านั้นกลับมาและแปลงกลับเป็นโครงสร้างเดิมของคุณ (ดีซีเรียลไลเซชัน) ใน C ++ มันไม่ยุ่งยากนักเนื่องจากการสะท้อนมี จำกัด มาก แต่ถึงกระนั้นห้องสมุดบางแห่งสามารถช่วยคุณได้ที่นี่ ฉันเขียนบทความเกี่ยวกับเรื่องนี้: https://rubentorresbonet.wordpress.com/2014/08/25/an-overview-of-data-serialization-techniques-in-c/ โดยทั่วไปฉันขอแนะนำให้คุณดู ไลบรารีซีเรียลหากคุณสามารถกำหนดเป้าหมายคอมไพเลอร์ C ++ 11 ได้ ไม่จำเป็นต้องสร้างไฟล์ระดับกลางเช่นเดียวกับ protobuf ดังนั้นคุณจะประหยัดเวลาหากคุณต้องการผลลัพธ์ที่รวดเร็ว คุณอาจเลือกระหว่างไบนารีและ JSON เพื่อให้สามารถช่วยแก้ไขข้อบกพร่องได้ที่นี่

ยิ่งไปกว่านั้นหากความปลอดภัยเป็นเรื่องที่น่ากังวลคุณอาจต้องการเข้ารหัส / ถอดรหัสข้อมูลที่คุณจัดเก็บโดยเฉพาะถ้าคุณใช้รูปแบบที่มนุษย์สามารถอ่านได้เช่น JSON อัลกอริทึมเช่น AES มีประโยชน์ที่นี่


-5

คุณต้องใช้fstreamสำหรับไฟล์อินพุต / เอาต์พุต ไวยากรณ์เป็นเรื่องง่าย EX:

#include <fstream>
// ...
std::ofstream flux ; // to open a file in ouput mode
flux.open("myfile.whatever") ; 

หรือ

#include <fstream>
// ...
std::ifstream flux ; // open a file in input mode
flux.open("myfile.whatever") ;

การกระทำอื่น ๆ ที่เป็นไปได้ในไฟล์ของคุณ: ผนวก , ไบนารี , trunc , ฯลฯ คุณจะใช้ไวยากรณ์เดียวกันข้างต้นแทนเราใส่ std :: ios: :( ธง) ตัวอย่างเช่น:

  • ios::out สำหรับการดำเนินการส่งออก
  • ios::in สำหรับการดำเนินการอินพุต
  • ios::binary สำหรับการดำเนินการแบบไบนารี (raw byte) IO แทนการใช้อักขระ
  • ios::app สำหรับการเริ่มเขียนที่ส่วนท้ายของไฟล์
  • ios::trunc สำหรับถ้าไฟล์มีอยู่แล้วแทนที่ลบเนื้อหาเก่าและแทนที่ด้วยใหม่
  • ios::ate - วางตัวชี้ไฟล์ "ที่ท้าย" สำหรับอินพุต / เอาต์พุต

Ex:

#include <fstream>
// ...
std::ifstream flux ;
flux.open("myfile.whatever" , ios::binary) ;

นี่คือตัวอย่างที่สมบูรณ์ แต่เรียบง่ายมากขึ้น

#include <iostream>
#include <fstream>

using namespace std ;

int input ;
int New_Apple ;
int Apple_Instock ;
int Eat_Apple ;
int Apple ;

int  main()
{
  bool shouldQuit = false;
  New_Apple = 0 ;
  Apple_Instock = 0 ;
  Eat_Apple = 0 ;

  while( !shouldQuit )
  {
    cout << "------------------------------------- /n";
    cout << "1) add some apple " << endl ;
    cout << "2) check apple in stock " << endl ;
    cout << "3) eat some apple " << endl ;
    cout << "4) quit " << endl ;
    cout << "------------------------------------- /n";
    cin >> input ;

    switch (input)
    {
      case 1 :
      {
        system("cls") ;

        cout << "------------------------------------ /n";
        cout << " how much apple do you want to add /n";
        cout << "------------------------------------ /n";      
        cin >> New_Apple ;

        ifstream apple_checker ;
        apple_checker.open("apple.apl") ;
        apple_checker >> Apple_Instock ;
        apple_checker.close() ; 

        Apple = New_Apple + Apple_Instock ;

        ofstream apple_adder ;
        apple_adder.open("apple.apl") ;
        apple_adder << Apple ;
        apple_adder.close() ;

        cout << "------------------------------------ /n";
        cout << New_Apple << " Apple has been added ! /n";
        cout << "------------------------------------ /n";
        break;
      }

      case 2 :  
      {
        system("cls") ;

        ifstream apple_checker ;
        apple_checker.open("apple.apl") ;
        apple_checker >> Apple_Instock ;
        apple_checker.close() ;

        cout << "------------------------------------ /n";
        cout << " there is " << Apple_Instock ;
        cout << "apple in stock /n" ;
        cout << "------------------------------------ /n";
        break;
      }

      case 3 :
      {
        system("cls") ;

        cout << "------------------------------------ /n";
        cout << "How many apple do you want to eat /n" ;
        cout << "------------------------------------ /n";
        cin >> Eat_Apple ;

        ifstream apple_checker ;
        apple_checker.open("apple.apl") ;
        apple_checker >> Apple_Instock ;
        apple_checker.close() ;

        Apple = Apple_Instock - Eat_Apple ; 

        ofstream apple_eater ;
        apple_eater.open("apple.apl") ;
        apple_eater << Apple ;
        apple_eater.close() ;

        cout << "----------------------------------- /n";
        cout << Eat_Apple ;
        cout << " Apple has been eated! /n";
        cout << "----------------------------------- /n";
        cout << Apple << " Apple left in stock /n";
        cout << "----------------------------------- /n";
        break;
      }

      case 4 :
      {
        shouldQuit = true;
        break;
      }

      default :
      {
        system("cls") ;

        cout << "------------------------------------ /n";
        cout << " invalide choice ! /n";
        cout << "------------------------------------ /n"; 
        break;
      }
    }
  }
  return 0;
}

4
-1 นี่เป็นคำตอบที่แย่มาก คุณควรจัดรูปแบบและแสดงรหัสอย่างถูกต้องและอธิบายสิ่งที่คุณกำลังทำอยู่ไม่มีใครต้องการถอดรหัสรหัสอันใดอันหนึ่ง
Vaillancourt

ขอบคุณ Katu สำหรับความคิดเห็นของคุณมีสิทธิที่ฉันควรจะอธิบายรหัสของฉันดีกว่าคุณสามารถบอกฉันว่าฉันจัดรูปแบบแหล่งที่มาของฉันจากเว็บไซต์สาเหตุที่ฉันใหม่ชนิดของสิ่งนี้
ฟรานซิส Forcier

จากไซต์นี้หรือสำหรับไซต์นี้ สำหรับความช่วยเหลือในการจัดรูปแบบการโพสต์, คุณสามารถเยี่ยมชมหน้าความช่วยเหลือการจัดรูปแบบ มีเครื่องหมายอัศเจรีย์ข้างส่วนหัวของพื้นที่ข้อความที่คุณใช้โพสต์เพื่อช่วยคุณเช่นกัน
Vaillancourt

ลองบันทึกสิ่งที่ถาม คุณไม่จำเป็นต้องแสดงความคิดเห็นทุกอย่าง และโดยไม่อธิบายสิ่งที่คุณทำในความคิดเห็นของฉันฉันหมายความว่าโดยทั่วไปคุณแนะนำกลยุทธ์ที่คุณแนะนำอย่างน้อยย่อหน้าสั้น ๆ (เช่น "หนึ่งในเทคนิคคือการใช้รูปแบบไฟล์ไบนารีกับตัวดำเนินการสตรีมคุณต้องระมัดระวังในการอ่านและเขียนในลำดับเดียวกัน bla bla lba")
Vaillancourt

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