ไม่เคยเห็นมาก่อน C ++ สำหรับลูป


164

ฉันกำลังแปลงอัลกอริทึม C ++ เป็น C # ฉันเจอสิ่งนี้เพื่อการวนซ้ำ:

for (u = b.size(), v = b.back(); u--; v = p[v]) 
b[u] = v;

มันไม่มีข้อผิดพลาดใน C ++ แต่ทำใน C # (ไม่สามารถแปลง int เป็น bool) ฉันไม่สามารถหาสิ่งนี้สำหรับลูป, เงื่อนไขอยู่ที่ไหน

ใครช่วยอธิบายหน่อยได้ไหม?

PS เพียงตรวจสอบเพื่อปรับ VECTOR ให้เข้ากับรายการ b.back () สอดคล้องกับ b [b.Count-1] หรือไม่


35
เงื่อนไขอยู่ที่ไหน u--ที่จะเป็น Semi-colons ใช้เพื่อกำหนดขอบเขตส่วนต่าง ๆ ของforข้อความ
David Heffernan

77
นี่เป็นวงวนปกติ C # ไม่แปลงหมายเลข bools โดยปริยายดังนั้นคุณต้องเปิดสภาพลง; u-- != 0;
อาร์มาตินเฟอร์นันเด

28
@Jessie Good - รหัสที่ดีไม่มีส่วนเกี่ยวข้องกับสิ่งที่อนุญาตในภาษานั้นจะเกี่ยวข้องกับระยะเวลาที่เพื่อนร่วมงานที่ไม่ต้องการใช้เวลาอ่านรหัส ถ้ามันทำให้เกิดความสับสนทุกชนิดมันไม่ใช่ทางออกที่ดีที่สุดแม้ว่าจะถูกกฎหมายก็ตาม บ่อยครั้งที่การแก้ปัญหา verbose มากขึ้นดีกว่าหนึ่ง terse และคอมไพเลอร์ส่วนใหญ่จะรวบรวมในสิ่งเดียวกันทั้งสองวิธี
Bill K

18
ผมหวังว่าหลังจากการแปลงรหัสที่คุณให้ตัวแปรชื่อที่ดีกว่าb, u, vฯลฯ เหตุผลเดียวที่พวกเขาตั้งชื่อแบบนี้เป็นเพราะมีคนอยากจะดูสมาร์ทโดยการทำรหัสของพวกเขาไม่สามารถอ่านได้
Dan

33
@houbysoft: นี่เป็นปัญหา stackoverflow ทั่วไป หากคุณถามคำถามที่มีรายละเอียดมากการวิจัยที่ดีและน่าสนใจในโดเมนการวิจัยที่เฉพาะเจาะจงซึ่งนำไปสู่การแก้ปัญหาที่ยากและน่าสนใจและคุณตอบคำถามดังกล่าวหลังจากผ่านการวิจัยมาหลายวันคุณจะได้รับเพียงไม่กี่ ผู้เข้าชมมากกว่าหนึ่งโหลและหนึ่งหรือสอง upvotes จากผู้เชี่ยวชาญไม่กี่คนในฟิลด์ หากคุณต้องการได้รับตัวแทนจำนวนมากอย่างรวดเร็วคุณต้องถามและตอบคำถามเช่นนี้ "ฉันจะเพิ่มตัวเลขสองตัวใน php อย่างไร", "ความdoหมายใน C ++" - จะได้รับความนิยมนับพันจากผู้เริ่มต้นที่กำลังมองหาการสอน
vsz

คำตอบ:


320

สภาพของforลูปอยู่ตรงกลาง - ระหว่างอัฒภาคสอง;อัน

ใน C ++ มันก็โอเคที่จะทำให้การแสดงออกเกือบเป็นเงื่อนไขใด ๆ : อะไรก็ตามที่ประเมินเป็นศูนย์หมายถึงfalse; trueวิธีการที่ไม่ใช่ศูนย์

ในกรณีของคุณเงื่อนไขคือu--: เมื่อคุณแปลงเป็น C # เพียงเพิ่ม!= 0:

for (u = b.size(), v = b.back(); u-- != 0; v = p[v]) 
    b[u] = v; //                     ^^^^ HERE

55
อย่างไรก็ตามโทมัสอาจสับสนกับการใช้เครื่องหมายจุลภาคด้วยเช่นกันมันแตกต่างจากเซมิโคลอนมากซึ่งช่วยให้คุณทำหลายสิ่งหลายอย่างในส่วนหนึ่งของลูป (ในกรณีนี้มันเริ่มต้นตัวแปรสองตัว) ครั้งล่าสุดที่ฉันตรวจสอบสิ่งก่อสร้างที่ผิดปกติเหล่านี้ไม่ถือว่าเป็นวิธีแก้ปัญหาที่อ่านได้มากที่สุดและบางคนอาจขมวดคิ้วได้
Bill K

2
ถ้าฉันจำได้อย่างถูกต้องและนิพจน์ที่มีเครื่องหมายจุลภาคมีค่าของนิพจน์ย่อยทางด้านขวา สิ่งนี้มาจาก C และสามารถใช้ในการแสดงออกใด ๆ ไม่เพียง แต่ในการวนซ้ำ
Giorgio

7
@Roger นี่จะไม่ใช่ลูปเดียวกันเนื่องจากคุณลดค่า u ที่ส่วนท้ายของลูปแทนที่จะเป็นจุดเริ่มต้น (เช่นหลังจาก b [u] = v แทนที่จะเป็นมาก่อน) ในความเป็นจริงคุณจะต้องเริ่มต้นด้วยu = b.size() - 1แทน
Didier L

Fyi: ฉันผลักคุณเกินขีด จำกัด 500K นั่นเหมือนกับการเป็นลูกค้าหนึ่งล้านที่ใดที่หนึ่ง ไม่ว่าในกรณีใด: ขอแสดงความยินดีมากมาย ค้นหาคำตอบที่แม่นยำและคมชัดอยู่เสมอ! ทำต่อไป; พบกันคุณสร้างสิ่งที่ 1 ล้าน ... ในปลายศตวรรษนี้
GhostCat

165

คำตอบที่ถูกต้องมากมาย แต่ฉันคิดว่ามันคุ้มค่าที่จะเขียนสิ่งที่เทียบเท่าในขณะที่วนซ้ำ

for (u = b.size(), v = b.back(); u--; v = p[v]) 
   b[u] = v;

เทียบเท่ากับ:

u = b.size();
v = b.back();
while(u--) {
   b[u] = v;
   v = p[v];
}

คุณอาจลองปรับโครงสร้างเป็นรูปแบบ while () ในขณะที่คุณแปลเป็น C # ในความคิดของฉันมันชัดเจนกว่ากับดักน้อยกว่าสำหรับโปรแกรมเมอร์ใหม่และมีประสิทธิภาพเท่าเทียมกัน

ขณะที่คนอื่น ๆ ได้ออกมาชี้ - แต่เพื่อให้คำตอบทั้งหมดของฉัน - เพื่อให้การทำงานใน C # คุณจะต้องเปลี่ยนไปwhile(u--)while(u-- != 0)

... หรือwhile(u-- >0)ในกรณีที่คุณเริ่มติดลบ (ตกลงb.size()จะไม่เป็นลบ - แต่ให้พิจารณากรณีทั่วไปซึ่งอาจเป็นอย่างอื่นที่เริ่มต้นด้วย u)

หรือเพื่อให้ชัดเจนยิ่งขึ้น:

u = b.size();
v = b.back();
while(u>0) {
   u--;
   b[u] = v;
   v = p[v];
}

มันจะดีกว่าที่จะชัดเจนกว่าที่จะกระชับ


29
คำตอบนี้ไม่เพียง แต่จะอธิบายรหัสที่ไม่ถูกต้อง แต่ยังให้ทางเลือกที่ดี 1 ขึ้น !!
polvoazul

2
นอกจากนี้ฉันควรระวังในwhile (u-- >0)แบบฟอร์ม หากระยะห่างเริ่มสับสนคุณอาจจบด้วยลูป "ลงไปที่ศูนย์" while (u --> 0)ซึ่งมีแนวโน้มที่จะสร้างความสับสนให้กับทุกคนในทันทีที่เห็น ( ฉันไม่แน่ใจว่ามันเป็น C # ที่ถูกต้องหรือไม่ แต่อยู่ใน C และฉันคิดว่ามันอาจเป็น C ++ ด้วย )
Izkata

9
ฉันไม่คิดว่ารหัสของคุณจะชัดเจนกว่านี้ จุดforแทนwhileคืออย่างแม่นยำว่าคุณใส่การเริ่มต้นและการเพิ่ม / ลดลงในหนึ่งคำสั่งและนั่นไม่จำเป็นต้องทำให้รหัสยากที่จะเข้าใจ มิฉะนั้นเราไม่ควรใช้forเลย
Musiphil

1
สิ่งสำคัญคือต้องเขียนโค้ดให้น้อยที่สุดเท่าที่จะทำได้ (การวนซ้ำอาจเปลี่ยนแปลงได้หลังจากทั้งหมด) คุณใส่ "u--" ในสองแห่งแยกกันและการวนซ้ำนั้นไม่ชัดเจน (ฉันสามารถดูว่าการวนรอบทำอะไรได้ในครั้งเดียวฉันต้องสแกน มีหลายบรรทัด) ความกระชับมีประโยชน์เช่นกัน อย่ามองข้ามพวกเขา ถึงกระนั้นก็ตามตัวอย่างที่ดีของวิธีการที่สามารถเขียนได้ มันช่วยให้เข้าใจได้ง่ายขึ้นสำหรับทุกคนที่ไม่คุ้นเคยกับคำแถลงใน C ++ (หรืออาจจะเป็นเช่นนั้น)
NotKyon

2
@Izkata: มันไม่ใช่โอเปอเรเตอร์เลย, มันถูกแจงเป็น--โทเค็นตามด้วย>โทเค็น สองผู้ประกอบการแยก การวนรอบ "ลงไปที่ศูนย์" เป็นเพียงการรวมกันของการโพสต์ - ลดลงและมากกว่า การบรรทุกเกินพิกัดของตัวดำเนินการ C ++ ไม่ได้สร้างตัวดำเนินการใหม่ แต่เพิ่งนำมาใช้ใหม่
Ben Voigt

66

สภาพเป็นu--;เพราะมันอยู่ในตำแหน่งที่สองของสำหรับการเรียนการสอน

หากค่าของu--;แตกต่างจาก 0 มันจะถูกตีความว่าเป็นtrue(เช่นถูกส่งไปยังค่าบูลีนโดยปริยายtrue) ถ้าแทนค่าเป็น 0 falseก็จะได้รับการหล่อ

นี่คือรหัสที่เลวร้ายมาก

อัปเดต:ฉันพูดถึงการเขียนลูป "สำหรับ" ในโพสต์บล็อกนี้ คำแนะนำสามารถสรุปได้ในย่อหน้าต่อไปนี้:

ลูป for คือการปฏิบัติที่สามารถอ่านได้ (เมื่อคุณชินกับมันแล้ว) และสร้าง terse แต่คุณต้องใช้มันให้ดี เนื่องจากมีรูปแบบที่ผิดปกติการใช้มันในแบบที่จินตนาการเกินจริงจึงไม่ใช่ความคิดที่ดี

ทุกส่วนของ for for loop ควรสั้นและอ่านง่าย ควรเลือกชื่อตัวแปรเพื่อให้ง่ายต่อการเข้าใจ

ตัวอย่างนี้ละเมิดคำแนะนำเหล่านี้อย่างชัดเจน


3
หรือมันจะหยุดที่ u == 0 น่าจะเป็น ... ?
โทมัส

2
ไม่มี ใน C ++ มีการแปลงโดยนัยจาก int เป็นบูลโดยมี 0 แปลงเป็นเท็จ การวนซ้ำจะสิ้นสุดลงเมื่อ u-- == 0 ใน C # ไม่มีการแปลงโดยปริยายดังนั้นคุณต้องพูดอย่างชัดเจนว่า u-- == 0. แก้ไข: นี่เป็นการตอบกลับความคิดเห็นแรกของคุณ
Chris

48
นี่เป็นรหัสที่แย่มากด้วยเหตุผลง่ายๆ คุณไม่สามารถเข้าใจได้ง่ายเมื่อคุณอ่าน มันคือ "ฉลาด", "แฮ็ค"; มันใช้การรวมกันของโครงสร้างการเข้ารหัสและความรู้เกี่ยวกับวิธีการทำงานเบื้องหลังเพื่อสร้างโครงสร้างที่ทำงาน แต่ท้าทายความเข้าใจเพราะมันไม่ได้อยู่ในรูปแบบที่ผู้เขียนภาษามองเห็นและสื่อสารกับคนส่วนใหญ่ ผู้ใช้ภาษา
KeithS

4
คำตอบที่ยอดเยี่ยม ฉันจะ +1 มัน ... ถ้าไม่ใช่ "รหัสนี้แย่มาก" คำสั่ง;)
Sandman4

14
ผมไม่เข้าใจว่าทำไมผู้คนจำนวนมากดูเหมือนจะคิดu--เป็นรหัสที่เลวร้ายจริงๆเพียงเพราะของหายไป (โดยปริยายใน C ++) ! = 0 แน่นอนทุกคนที่ทำงานด้วยรหัสจะตระหนักดีว่า0 = false ทุกค่าอื่น มีขอบเขตที่กว้างกว่าสำหรับความสับสนเกี่ยวกับ pre- / post-incrementing ของuหรือผู้คนอาจสมมติว่าu = b.size ()จะดำเนินการเสมอก่อนv = b.back () (ความเข้าใจของฉันคือลำดับการดำเนินการที่ไม่ได้กำหนดไว้ แต่ฉันยืนที่จะแก้ไข)
FumbleFingers

23

นี่จะเป็นรูปแบบ C # ของลูปของคุณ

// back fetches the last element of vector in c++.
for (u = b.size(), v = b.back(); (u--) != 0; v = p[v]) 
{      
  b[u] = v;      
}

เพียงแทนที่เทียบเท่าสำหรับ size () และ back ()

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

b = b.Reverse().ToArray();

1
โดยการv = b.back();ออกจาก intializer สำหรับคุณไม่เพียงแค่เปลี่ยนวิธีการทำงานตั้งแต่v = p[v]ถูกแทนที่โดย
João Portela

v = p [v] จะไม่มีผลใด ๆ ต่อผลลัพธ์สุดท้ายเนื่องจากบรรทัดนี้จะดำเนินการในที่สุด และหลังจากนั้น v จะไม่ถูกอ้างถึงในลูป บรรทัดนี้มีไว้เพื่อแสดงวิธีการแปลงลูปจาก c ++ เป็น C #
Narendra

1
ในรหัส c ++ v = b.back();ได้รับการดำเนินการหนึ่งครั้งก่อนที่จะเริ่มการทำซ้ำและv = p[v]ถูกดำเนินการในตอนต้นของการทำซ้ำแต่ละครั้ง ในรุ่น C # ที่v = p[v]ยังคงดำเนินการในจุดเริ่มต้นของแต่ละซ้ำ แต่v = b.back();จะถูกดำเนินการทันทีหลังจากที่มันเปลี่ยนค่าของการเรียนการสอนต่อไปv b[u] = v;(อาจเป็นคำถามที่แก้ไขหลังจากที่คุณอ่าน)
João Portela

5
@Rain v = b.back()ปัญหาคือ คุณให้มันดำเนินการที่วนซ้ำทุกครั้งแทนที่จะเป็นอันแรก - เราไม่รู้ว่าเกิดอะไรขึ้นback()(มีผลข้างเคียงหรือไม่มันเปลี่ยนการแทนค่าภายในของb?) ดังนั้นลูปนี้จึงไม่เทียบเท่ากับใน คำถาม.
Izkata

1
@Rain แน่นอนให้มองมันด้วยตัวเอง เริ่มต้นขั้นตอนที่เกิดขึ้นเพียงครั้งเดียวก่อนวงเริ่มต้นไม่ได้ที่จุดเริ่มต้นของทุกซ้ำ รหัสของคุณจะถูกต้องหากv = b.back()ถูกย้ายนอกลูปข้างบน (นอกจากนี้หากคุณกำลังพยายามที่จะตอบสนองต่อใครสักคนให้ใช้@ต่อหน้าชื่อของพวกเขาดังนั้นเราจึงได้รับการแจ้งเตือน)
Izkata


14

เงื่อนไขคือผลลัพธ์ของu--ซึ่งเป็นค่าuก่อนที่จะลดลง

ใน C และ C ++, a int สามารถเปลี่ยนเป็น bool ได้โดยการ!= 0เปรียบเทียบ (0 คือfalse, ทุกอย่างเป็นอย่างอื่นtrue)

b.back()เป็นองค์ประกอบสุดท้ายในภาชนะซึ่งเป็นเมื่อb[b.size() - 1]size() != 0


11

ใน C ทุกสิ่งที่ไม่ใช่ศูนย์จะอยู่trueในบริบท "บูลีน" เช่นสภาพลูปสิ้นสุดหรือคำสั่งแบบมีเงื่อนไข ใน C # u-- != 0คุณจะต้องทำให้การตรวจสอบอย่างชัดเจนว่า:


นี่ไม่ใช่คำถามของ OP เขากำลังถามเกี่ยวกับการประเมินสภาพขั้ว (เช่น 'u--' ในกรณีนี้)
ApplePie

6

ตามที่ระบุไว้โดยผู้อื่นความจริงที่ว่า C ++ นั้นมีการส่งไปยังบูลีนโดยปริยายหมายถึงเงื่อนไขu--ซึ่งจะเป็นจริงหากค่านั้นไม่ใช่ศูนย์

เป็นมูลค่าเพิ่มที่คุณได้สมมติว่าเป็นเท็จในการถาม "ที่ไหนมีเงื่อนไข" ในทั้ง C ++ และ C # (และภาษาที่มีไวยากรณ์คล้ายคลึงกันอื่น ๆ ) คุณสามารถมีเงื่อนไขแบบว่างได้ ในกรณีนี้ก็มักจะตรวจสอบการจริงดังนั้นห่วงอย่างต่อเนื่องตลอดไปหรือจนกว่าเงื่อนไขอื่น ๆ บางอย่างออกจากมัน (ผ่านreturn, breakหรือthrow)

for(int i = 0; ; ++i)
  doThisForever(i);

อันที่จริง, ส่วนใดส่วนหนึ่งของคำสั่ง for สามารถถูกปล่อยออกไป, ซึ่งในกรณีนี้มันไม่ได้ดำเนินการ

โดยทั่วไปfor(A; B; C){D}หรือfor(A; B; C)D;กลายเป็น:

{A}
loopBack:
if(!(B))
  goto escapeLoop;
{D}
{C}
goto loopBack;
escapeLoop:

สามารถออก A, B, C หรือ D อย่างน้อยหนึ่งรายการ

ด้วยเหตุนี้บางคนชอบfor(;;) ลูปไม่มีที่สิ้นสุด ฉันทำเพราะในขณะที่while(true)ได้รับความนิยมฉันอ่านว่า "จนกระทั่งความจริงจบลงด้วยความจริง" ซึ่งฟังดูค่อนข้างจะเลวร้ายเมื่อเปรียบเทียบกับการอ่านของฉันfor(;;) ในฐานะ "ตลอดไป"

มันเป็นเรื่องของรสนิยม แต่เนื่องจากฉันไม่ใช่คนเดียวในโลกที่จะชอบfor(;;)มันก็คุ้มค่าที่จะรู้ว่ามันหมายถึงอะไร


4

คำตอบทั้งหมดถูกต้อง: -

for loop สามารถใช้งานได้หลายวิธีดังนี้:

Single Statement inside For Loop
Multiple Statements inside For Loop
No Statement inside For Loop
Semicolon at the end of For Loop
Multiple Initialization Statement inside For
Missing Initialization in For Loop
Missing Increment/Decrement Statement
Infinite For Loop
Condition with no Conditional Operator.

4
for (u = b.size(), v = b.back(); u--; v = p[v]) 
   b[u] = v;

ในโค้ดข้างต้นuและvจะเริ่มต้นได้ด้วยและb.size()b.back()

ทุกครั้งที่มีการตรวจสอบเงื่อนไขจะดำเนินการคำสั่งการลดลงเช่นu--กัน

forห่วงจะออกเมื่อจะกลายเป็นu0


3

ข้อผิดพลาดที่พบใน C # ตัวเองล้างข้อสงสัย การค้นหาวนสำหรับ

FALSE

เงื่อนไขที่จะยุติ และอย่างที่เรารู้

(BOOL) FALSE = (int) 0

แต่ C # ไม่สามารถดำเนินการได้ด้วยตัวเองซึ่งแตกต่างจาก C ++ เงื่อนไขที่คุณค้นหาคือ

ยู--

แต่คุณต้องให้เงื่อนไขอย่างชัดเจนใน C # เป็น

คุณ -! = 0

หรือ

คุณ -> 0

แต่ยังคงพยายามหลีกเลี่ยงการเขียนโค้ดแบบนี้

ในขณะที่วง

คำตอบข้างต้นเป็นหนึ่งในเวอร์ชันที่ง่ายที่สุดของคุณ

สำหรับวง


@Downvoter: Downvoting นั้นไม่เป็นไรเท่าที่คุณยังไม่พอใจโดยวิธีการแก้ปัญหา แต่ในเวลาเดียวกันโปรดใช้เวลาในการระบุเหตุผลเพื่อที่คำตอบจะได้รับการปรับปรุง
Abhineet

3

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

for (<initialization> ; <condition>; <increment>)
{
    <code...>
}

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

เหตุใดจึงu--ทำงานเป็นเงื่อนไขใน C และไม่ใช่ C # เพราะ C แปลงสิ่งต่าง ๆ มากมายโดยนัยและคนโง่อาจทำให้เกิดปัญหาได้ สำหรับตัวเลขจำนวนใดที่ไม่ใช่ศูนย์นั้นเป็นจริงและศูนย์เป็นเท็จ ดังนั้นมันจะนับถอยหลังจาก b.size () - 1 ถึง 0 การมีผลข้างเคียงในสภาพนั้นค่อนข้างน่ารำคาญและมันจะดีกว่าถ้าวางไว้ในส่วนที่เพิ่มขึ้นของ for loop แม้ว่า C จำนวนมาก รหัสทำสิ่งนี้ ถ้าฉันเขียนมันฉันจะทำมันมากกว่านี้:

for (u = b.size() - 1, v = b.back(); u>=0; --u) 
{
    b[u] = v;
    v = p[v]
}

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

ผู้ประกอบการจุลภาคอาจจะโยนคุณเป็นห่วง ในภาษา C x=1,y=2ดูเหมือนว่าคำสั่งเดียวที่เกี่ยวข้องกับคอมไพเลอร์และพอดีกับรหัสเริ่มต้น มันแค่ประเมินแต่ละส่วนและคืนค่าของชิ้นสุดท้าย ตัวอย่างเช่น:

std::cout << "(1,2)=" << (1,2) << std::endl;

จะพิมพ์ออกมา 2


ปัญหาเกี่ยวกับการเขียนซ้ำของคุณคือถ้า b.size () ไม่ได้ลงชื่อมันจะวนซ้ำเป็นเวลานาน (นอกจากนี้คุณยังขาดเครื่องหมายอัฒภาค) แต่อย่างน้อยคุณก็ไม่ได้ใช้วิธี "" Dick and Jane "เป็นภาษาอังกฤษที่ดี" ซึ่งมีคำตอบและความคิดเห็นอื่น ๆ อีกมากมายที่ทำ เพื่ออ่านโดย neophytes และโปรแกรมเมอร์ไร้ฝีมืออื่น ๆ
Jim Balter
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.