Если у меня есть функция, которая производит результат int
и результат string
, как мне вернуть их оба из функции?
Насколько я могу судить, я могу вернуть только одно значение, что определяется типом, предшествующим имени функции.
c
return-value
Тони Старк
источник
источник
string
вы имеете в виду «Я использую C ++ и этоstd::string
класс» или «Я использую C , и этоchar *
указатель илиchar[]
массив.»Ответы:
Я не знаю, что у вас
string
такое, но предполагаю, что он управляет собственной памятью.У вас есть два решения:
1: вернуть,
struct
содержащий все необходимые вам типы.struct Tuple { int a; string b; }; struct Tuple getPair() { Tuple r = { 1, getString() }; return r; } void foo() { struct Tuple t = getPair(); }
2: Используйте указатели для передачи значений.
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); }
Какой из них вы выберете, во многом зависит от личных предпочтений в отношении той семантики, которая вам больше нравится.
источник
char *
и asize_t
для длины, если только это не жизненно важно для функции, чтобы выделить ее собственную строку и / или вернутьNULL
.getPair
затем разыменовывается . В зависимости от того, что вы делаете (OP никогда не уточнял, действительно ли это вопрос C), выделение может быть проблемой, но обычно этого нет в области C ++ (оптимизация возвращаемого значения сохраняет все это), а в области C данные копии обычно происходят явно (черезstrncpy
или что-то еще).Option 1
: Объявить структуру с целым числом и строкой и вернуть структурную переменную.struct foo { int bar1; char bar2[MAX]; }; struct foo fun() { struct foo fooObj; ... return fooObj; }
Option 2
: Вы можете передать один из двух параметров через указатель и внести изменения в фактический параметр через указатель и вернуть другой как обычно:int fun(char **param) { int bar; ... strcpy(*param,"...."); return bar; }
или
char* fun(int *param) { char *str = /* malloc suitably.*/ ... strcpy(str,"...."); *param = /* some value */ return str; }
Option 3
: Аналогично варианту 2. Вы можете передать как указатель, так и ничего не вернуть из функции:void fun(char **param1,int *param2) { strcpy(*param1,"...."); *param2 = /* some calculated value */ }
источник
int fun(char *param, size_t len)
strcpy
например.Поскольку один из ваших типов результатов является строкой (и вы используете C, а не C ++), я рекомендую передавать указатели в качестве выходных параметров. Использование:
void foo(int *a, char *s, int size);
и назовите это так:
int a; char *s = (char *)malloc(100); /* I never know how much to allocate :) */ foo(&a, s, 100);
В общем, предпочтительнее выполнять распределение в вызывающей функции, а не внутри самой функции, чтобы вы могли быть максимально открыты для различных стратегий распределения.
источник
Два разных подхода:
Я думаю, что №1 немного более очевиден в том, что происходит, хотя это может стать утомительным, если у вас слишком много возвращаемых значений. В этом случае вариант №2 работает довольно хорошо, хотя есть некоторые умственные издержки, связанные с созданием специализированных структур для этой цели.
источник
string
, можно с уверенностью предположить, что C ++ ...Создайте структуру и установите внутри два значения и верните переменную структуры.
struct result { int a; char *string; }
Вы должны выделить место для файла
char *
в вашей программе.источник
Используйте указатели в качестве параметров функции. Затем используйте их для возврата нескольких значений.
источник
Передавая параметры по ссылке на функцию.
Примеры:
void incInt(int *y) { (*y)++; // Increase the value of 'x', in main, by one. }
Также с использованием глобальных переменных, но это не рекомендуется.
Пример:
int a=0; void main(void) { //Anything you want to code. }
источник
void main(void)
Ой, как горит!main
должен возвращать код состояния. В * nix обычно объявляется какint main(int argc, char *argv[])
, я полагаю, в Windows есть аналогичные соглашения.Один из подходов - использовать макросы. Поместите это в файл заголовка
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__)
Это позволяет возвращать до четырех переменных из функции и назначать их до четырех переменных. Например, вы можете использовать их так:
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; }
Вот что он печатает:
(55, 3.9, 24.15)
Решение может быть не таким переносимым, потому что оно требует C99 или более поздней версии для вариативных макросов и объявлений переменных for-statement. Но я думаю, что было достаточно интересно написать здесь. Другая проблема заключается в том, что компилятор не предупредит вас, если вы присвоите им неправильные значения, поэтому вы должны быть осторожны.
Дополнительные примеры и стековая версия кода с использованием объединений доступны в моем репозитории на github .
источник
__typeof__