Jika saya memiliki fungsi yang memberikan hasil int
dan hasil string
, bagaimana cara mengembalikan keduanya dari suatu fungsi?
Sejauh yang saya tahu, saya hanya dapat mengembalikan satu hal, sebagaimana ditentukan oleh tipe sebelum nama fungsi.
c
return-value
Tony Stark
sumber
sumber
string
maksud Anda "Saya menggunakan C ++ dan ini adalahstd::string
kelas" atau "Saya menggunakan C dan ini adalahchar *
pointer atauchar[]
larik."Jawaban:
Saya tidak tahu apa milik Anda
string
, tetapi saya akan berasumsi bahwa itu mengelola ingatannya sendiri.Anda memiliki dua solusi:
1: Kembalikan a
struct
yang berisi semua tipe yang Anda butuhkan.struct Tuple { int a; string b; }; struct Tuple getPair() { Tuple r = { 1, getString() }; return r; } void foo() { struct Tuple t = getPair(); }
2: Gunakan petunjuk untuk membagikan nilai.
void getPair(int* a, string* b) { // Check that these are not pointing to NULL assert(a); assert(b); *a = 1; *b = getString(); } void foo() { int a, b; getPair(&a, &b); }
Yang mana yang Anda pilih untuk digunakan sangat bergantung pada preferensi pribadi untuk semantik apa pun yang lebih Anda sukai.
sumber
char *
dan asize_t
untuk panjang kecuali sangat penting bagi fungsi untuk mengalokasikan string dan / atau return itu sendiriNULL
.getPair
kemudian dereferensi . Bergantung pada apa yang Anda lakukan (OP tidak pernah mengklarifikasi apakah ini sebenarnya pertanyaan C), alokasi mungkin menjadi perhatian, tetapi biasanya tidak di lahan C ++ (pengoptimalan nilai pengembalian menyimpan semua ini) dan di lahan C, data salinan biasanya terjadi secara eksplisit (melaluistrncpy
atau apapun).Option 1
: Mendeklarasikan struct dengan int dan string dan mengembalikan variabel struct.struct foo { int bar1; char bar2[MAX]; }; struct foo fun() { struct foo fooObj; ... return fooObj; }
Option 2
: Anda dapat meneruskan salah satu dari keduanya melalui pointer dan membuat perubahan pada parameter sebenarnya melalui pointer dan mengembalikan yang lain seperti biasa:int fun(char **param) { int bar; ... strcpy(*param,"...."); return bar; }
atau
char* fun(int *param) { char *str = /* malloc suitably.*/ ... strcpy(str,"...."); *param = /* some value */ return str; }
Option 3
: Mirip dengan opsi 2. Anda dapat meneruskan keduanya melalui penunjuk dan tidak mengembalikan apa pun dari fungsi:void fun(char **param1,int *param2) { strcpy(*param1,"...."); *param2 = /* some calculated value */ }
sumber
int fun(char *param, size_t len)
strcpy
misalnya.Karena salah satu jenis hasil Anda adalah string (dan Anda menggunakan C, bukan C ++), saya sarankan meneruskan pointer sebagai parameter output. Menggunakan:
void foo(int *a, char *s, int size);
dan menyebutnya seperti ini:
int a; char *s = (char *)malloc(100); /* I never know how much to allocate :) */ foo(&a, s, 100);
Secara umum, lebih suka melakukan alokasi dalam fungsi pemanggilan , bukan di dalam fungsi itu sendiri, sehingga Anda bisa seterbuka mungkin untuk strategi alokasi yang berbeda.
sumber
Dua pendekatan berbeda:
Saya pikir # 1 sedikit lebih jelas tentang apa yang terjadi, meskipun itu bisa membosankan jika Anda memiliki terlalu banyak nilai kembali. Dalam hal ini, opsi # 2 bekerja dengan cukup baik, meskipun ada beberapa beban mental yang terlibat dalam membuat struct khusus untuk tujuan ini.
sumber
string
, mungkin aman untuk menggunakan C ++ ...Buat struct dan setel dua nilai di dalamnya dan kembalikan variabel struct.
struct result { int a; char *string; }
Anda harus mengalokasikan ruang untuk
char *
program Anda.sumber
Gunakan pointer sebagai parameter fungsi Anda. Kemudian gunakan untuk mengembalikan beberapa nilai.
sumber
Dengan melewatkan parameter dengan mengacu pada fungsi.
Contoh:
void incInt(int *y) { (*y)++; // Increase the value of 'x', in main, by one. }
Juga dengan menggunakan variabel global tetapi tidak disarankan.
Contoh:
int a=0; void main(void) { //Anything you want to code. }
sumber
void main(void)
OH BAGAIMANA MEMBAKAR!main
seharusnya mengembalikan kode status. Di bawah * nix, lebih umum untuk mendeklarasikannya sebagaiint main(int argc, char *argv[])
, saya yakin Windows memiliki konvensi serupa.Salah satu pendekatannya adalah dengan menggunakan makro. Tempatkan ini di file header
multitype.h
#include <stdlib.h> /* ============================= HELPER MACROS ============================= */ /* __typeof__(V) abbreviation */ #define TOF(V) __typeof__(V) /* Expand variables list to list of typeof and variable names */ #define TO3(_0,_1,_2,_3) TOF(_0) v0; TOF(_1) v1; TOF(_2) v2; TOF(_3) v3; #define TO2(_0,_1,_2) TOF(_0) v0; TOF(_1) v1; TOF(_2) v2; #define TO1(_0,_1) TOF(_0) v0; TOF(_1) v1; #define TO0(_0) TOF(_0) v0; #define TO_(_0,_1,_2,_3,TO_MACRO,...) TO_MACRO #define TO(...) TO_(__VA_ARGS__,TO3,TO2,TO1,TO0)(__VA_ARGS__) /* Assign to multitype */ #define MTA3(_0,_1,_2,_3) _0 = mtr.v0; _1 = mtr.v1; _2 = mtr.v2; _3 = mtr.v3; #define MTA2(_0,_1,_2) _0 = mtr.v0; _1 = mtr.v1; _2 = mtr.v2; #define MTA1(_0,_1) _0 = mtr.v0; _1 = mtr.v1; #define MTA0(_0) _0 = mtr.v0; #define MTA_(_0,_1,_2,_3,MTA_MACRO,...) MTA_MACRO #define MTA(...) MTA_(__VA_ARGS__,MTA3,MTA2,MTA1,MTA0)(__VA_ARGS__) /* Return multitype if multiple arguments, return normally if only one */ #define MTR1(...) { \ typedef struct mtr_s { \ TO(__VA_ARGS__) \ } mtr_t; \ mtr_t *mtr = malloc(sizeof(mtr_t)); \ *mtr = (mtr_t){__VA_ARGS__}; \ return mtr; \ } #define MTR0(_0) return(_0) #define MTR_(_0,_1,_2,_3,MTR_MACRO,...) MTR_MACRO /* ============================== API MACROS =============================== */ /* Declare return type before function */ typedef void* multitype; #define multitype(...) multitype /* Assign return values to variables */ #define let(...) \ for(int mti = 0; !mti;) \ for(multitype mt; mti < 2; mti++) \ if(mti) { \ typedef struct mtr_s { \ TO(__VA_ARGS__) \ } mtr_t; \ mtr_t mtr = *(mtr_t*)mt; \ MTA(__VA_ARGS__) \ free(mt); \ } else \ mt /* Return */ #define RETURN(...) MTR_(__VA_ARGS__,MTR1,MTR1,MTR1,MTR0)(__VA_ARGS__)
Ini memungkinkan untuk mengembalikan hingga empat variabel dari suatu fungsi dan menetapkannya hingga empat variabel. Sebagai contoh, Anda dapat menggunakannya seperti ini:
multitype (int,float,double) fun() { int a = 55; float b = 3.9; double c = 24.15; RETURN (a,b,c); } int main(int argc, char *argv[]) { int x; float y; double z; let (x,y,z) = fun(); printf("(%d, %f, %g\n)", x, y, z); return 0; }
Ini yang dicetaknya:
(55, 3.9, 24.15)
Solusinya mungkin tidak portabel karena memerlukan C99 atau yang lebih baru untuk makro variadic dan deklarasi variabel untuk pernyataan. Tapi menurut saya cukup menarik untuk memposting di sini. Masalah lainnya adalah kompilator tidak akan memperingatkan Anda jika Anda menetapkan nilai yang salah, jadi Anda harus berhati-hati.
Contoh tambahan, dan versi kode berbasis tumpukan menggunakan serikat pekerja, tersedia di repositori github saya .
sumber
__typeof__