ฉันจะคืนค่าหลายค่าจากฟังก์ชันใน C ได้อย่างไร


89

ถ้าฉันมีฟังก์ชันที่สร้างผลลัพธ์intและผลลัพธ์stringฉันจะคืนค่าทั้งสองจากฟังก์ชันได้อย่างไร

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


7
โดยstringคุณหมายความว่า "ฉันใช้ C ++ และนี่คือstd::stringระดับ" หรือ "ฉันใช้ C และนี่คือchar *ตัวชี้หรือchar[]อาร์เรย์."
Chris Lutz

ในกรณีเฉพาะของฉันพวกเขาเป็นสอง ints: หนึ่งสำหรับ 'คะแนน' ของสิ่งที่ฉันกำลังเปรียบเทียบและอีกรายการสำหรับ 'ดัชนี' ที่พบคะแนนสูงสุดนั้น ฉันต้องการใช้ตัวอย่างสตริงที่นี่สำหรับกรณีทั่วไป
Tony Stark

ส่งสตริงโดยการอ้างอิงและคืนค่า int วิธีที่เร็วที่สุด ไม่จำเป็นต้องมีโครงสร้าง
Stefan Steiger

1
ไม่ใช่ฟังก์ชันที่ส่งคืนผลลัพธ์ 2 รายการที่ทำมากกว่าหนึ่งสิ่งไม่ใช่หรือ ลุงบ๊อบจะพูดอะไร?
Duncan

คำตอบ:


124

ฉันไม่รู้ว่าคุณstringคืออะไรแต่ฉันจะสมมติว่ามันจัดการหน่วยความจำของมันเอง

คุณมีสองวิธีแก้ไข:

1: ส่งคืนstructซึ่งมีทุกประเภทที่คุณต้องการ

2: ใช้พอยน์เตอร์เพื่อส่งผ่านค่า

คุณจะเลือกใช้อันไหนขึ้นอยู่กับความชอบส่วนบุคคลเป็นหลักว่าคุณชอบอรรถศาสตร์ใดมากกว่ากัน


7
ฉันคิดว่ามันขึ้นอยู่กับความสัมพันธ์ของค่าส่งคืน หาก int เป็นรหัสข้อผิดพลาดและสตริงเป็นผลลัพธ์ก็ไม่ควรนำสิ่งเหล่านี้มารวมกันในโครงสร้าง นั่นเป็นเรื่องโง่ ในกรณีที่ว่าผมจะกลับ int และผ่านสตริงเป็นchar *และsize_tสำหรับความยาวเว้นแต่มันเป็นความสำคัญอย่างยิ่งสำหรับการทำงานในการจัดสรรก็สตริงเองและ / NULLหรือผลตอบแทน
Chris Lutz

@ คริสฉันเห็นด้วยกับคุณอย่างสมบูรณ์ แต่ฉันไม่รู้เกี่ยวกับความหมายการใช้งานของตัวแปรที่เขาต้องการ
Travis Gockel

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

@BobVicktor: C ไม่มีความหมายอ้างอิงเลย (ซึ่งเป็นเอกสิทธิ์ของ C ++) ดังนั้นทุกอย่างจึงเป็นค่า วิธีการแก้ปัญหาทั้งสองตัวชี้ (# 2) จะผ่านสำเนาของตัวชี้เป็นฟังก์ชั่นที่getPairแล้วdereferences ขึ้นอยู่กับสิ่งที่คุณกำลังทำอยู่ (OP ไม่เคยชี้แจงว่านี่เป็นคำถาม C จริงหรือไม่) การจัดสรรอาจเป็นสิ่งที่น่ากังวล แต่โดยปกติแล้วจะไม่อยู่ในที่ดิน C ++ (การเพิ่มประสิทธิภาพการคืนค่าจะบันทึกสิ่งเหล่านี้ทั้งหมด) และในที่ดิน C ข้อมูล สำเนามักจะเกิดขึ้นอย่างชัดเจน (ผ่านทางstrncpyหรืออะไรก็ตาม)
Travis Gockel

@TravisGockel ขอบคุณสำหรับการแก้ไข ฉันอ้างถึงความจริงที่ว่ามีการใช้พอยน์เตอร์ดังนั้นจึงไม่ได้คัดลอกค่าเพียงแค่แบ่งปันสิ่งที่จัดสรรไปแล้ว แต่คุณพูดถูกที่เรียกว่า pass-by-reference ในภาษา C ไม่ถูกต้องและขอขอบคุณสำหรับความรู้ที่ยอดเยี่ยมอื่น ๆ เช่นกัน ฉันชอบเรียนรู้สิ่งเล็กน้อยเหล่านี้เกี่ยวกับภาษา :)
RTHarston

10

Option 1: ประกาศโครงสร้างด้วย int และสตริงและส่งคืนตัวแปร struct

Option 2: คุณสามารถส่งผ่านตัวชี้หนึ่งในสองตัวและทำการเปลี่ยนแปลงพารามิเตอร์จริงผ่านตัวชี้และส่งกลับอีกตัวได้ตามปกติ:

หรือ

Option 3: คล้ายกับตัวเลือก 2 คุณสามารถส่งผ่านทั้งตัวชี้และไม่ส่งคืนอะไรเลยจากฟังก์ชัน:


สำหรับตัวเลือกที่ 2 คุณควรส่งผ่านความยาวของสตริงด้วย int fun(char *param, size_t len)
Chris Lutz

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

7

เนื่องจากหนึ่งในประเภทผลลัพธ์ของคุณเป็นสตริง (และคุณใช้ C ไม่ใช่ C ++) ฉันขอแนะนำให้ส่งพอยน์เตอร์เป็นพารามิเตอร์เอาต์พุต ใช้:

และเรียกแบบนี้ว่า

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


6

สองแนวทางที่แตกต่างกัน:

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

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


1
C ไม่มีการอ้างอิง ;-) แม้ว่าจะใช้โปสเตอร์stringแต่มันก็ปลอดภัยที่จะถือว่า C ++ ...
Travis Gockel

ลืมไปโดยสิ้นเชิง! ฉันแก้ไขคำตอบให้ใช้พอยน์เตอร์ แต่เห็นได้ชัดว่าฉันอยู่ในที่ดิน C ++ มานานเกินไป :)
James Thompson

6

สร้างโครงสร้างและตั้งค่าสองค่าภายในและส่งคืนตัวแปร struct

คุณต้องจัดสรรพื้นที่สำหรับchar *ในโปรแกรมของคุณ


3

ใช้พอยน์เตอร์เป็นพารามิเตอร์ฟังก์ชันของคุณ จากนั้นใช้เพื่อคืนค่าหลายค่า


2

โดยส่งผ่านพารามิเตอร์โดยอ้างอิงถึงฟังก์ชัน

ตัวอย่าง:

นอกจากนี้โดยใช้ตัวแปรส่วนกลาง แต่ไม่แนะนำ

ตัวอย่าง:


4
void main(void)โอ้มันเบิร์นแค่ไหน!
Chris Lutz

คุณหมายถึงอะไร? @ Chris Lutz
Badr

6
mainควรจะส่งคืนรหัสสถานะ ภายใต้ * nix เป็นเรื่องปกติที่จะประกาศว่าเป็นint main(int argc, char *argv[])ฉันเชื่อว่า Windows มีอนุสัญญาที่คล้ายกัน
Duncan

2

แนวทางหนึ่งคือการใช้มาโคร วางสิ่งนี้ไว้ในไฟล์ส่วนหัวmultitype.h

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

นี่คือสิ่งที่พิมพ์:

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

ตัวอย่างเพิ่มเติมและรุ่นสแต็คที่ใช้ในการใช้รหัสสหภาพแรงงานมีที่ของฉันที่เก็บ GitHub


1
ปัญหาการพกพาที่ใหญ่กว่าคือฟีเจอร์ที่ไม่ได้มาตรฐาน__typeof__
MM

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