Si tengo una función que produce un resultado int
y un resultado string
, ¿cómo devuelvo ambos de una función?
Por lo que puedo decir, solo puedo devolver una cosa, según lo determinado por el tipo que precede al nombre de la función.
c
return-value
Tony Stark
fuente
fuente
string
Qué quiere decir "Estoy usando C ++ y esta es lastd::string
clase" o "Estoy usando C y este es unchar *
puntero ochar[]
matriz."Respuestas:
No sé cuál
string
es el tuyo , pero voy a asumir que maneja su propia memoria.Tienes dos soluciones:
1: Devuelve un
struct
que contiene todos los tipos que necesitas.struct Tuple { int a; string b; }; struct Tuple getPair() { Tuple r = { 1, getString() }; return r; } void foo() { struct Tuple t = getPair(); }
2: Utilice punteros para pasar valores.
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); }
El que elija utilizar depende en gran medida de las preferencias personales en cuanto a la semántica que más le guste.
fuente
char *
y asize_t
para la longitud a menos que sea absolutamente vital que la función asigne su propia cadena y / o regreseNULL
.getPair
luego elimina las referencias . Dependiendo de lo que esté haciendo (OP nunca aclaró si esto es realmente una pregunta C), la asignación puede ser una preocupación, pero generalmente no está en la tierra C ++ (la optimización del valor de retorno guarda todo esto) y en la tierra C, los datos las copias suelen suceder de forma explícita (víastrncpy
o lo que sea).Option 1
: Declara una estructura con un int y una cadena y devuelve una variable de estructura.struct foo { int bar1; char bar2[MAX]; }; struct foo fun() { struct foo fooObj; ... return fooObj; }
Option 2
: Puede pasar uno de los dos a través del puntero y realizar cambios en el parámetro real a través del puntero y devolver el otro como de costumbre:int fun(char **param) { int bar; ... strcpy(*param,"...."); return bar; }
o
char* fun(int *param) { char *str = /* malloc suitably.*/ ... strcpy(str,"...."); *param = /* some value */ return str; }
Option 3
: Similar a la opción 2. Puede pasar ambos a través del puntero y no devolver nada de la función:void fun(char **param1,int *param2) { strcpy(*param1,"...."); *param2 = /* some calculated value */ }
fuente
int fun(char *param, size_t len)
strcpy
por ejemplo.Dado que uno de sus tipos de resultado es una cadena (y está usando C, no C ++), le recomiendo pasar punteros como parámetros de salida. Utilizar:
void foo(int *a, char *s, int size);
y llámalo así:
int a; char *s = (char *)malloc(100); /* I never know how much to allocate :) */ foo(&a, s, 100);
En general, prefiera hacer la asignación en la función de llamada , no dentro de la función en sí, de modo que pueda estar lo más abierto posible a las diferentes estrategias de asignación.
fuente
Dos enfoques diferentes:
Creo que el número 1 es un poco más obvio sobre lo que está sucediendo, aunque puede volverse tedioso si tiene demasiados valores de retorno. En ese caso, la opción # 2 funciona bastante bien, aunque hay una sobrecarga mental involucrada en la creación de estructuras especializadas para este propósito.
fuente
string
, podría ser seguro asumir C ++ ...Cree una estructura y establezca dos valores dentro y devuelva la variable de estructura.
struct result { int a; char *string; }
Tienes que asignar espacio para el
char *
en tu programa.fuente
Utilice punteros como parámetros de su función. Luego utilícelos para devolver múltiples valores.
fuente
Pasando parámetros por referencia a la función.
Ejemplos:
void incInt(int *y) { (*y)++; // Increase the value of 'x', in main, by one. }
También mediante el uso de variables globales, pero no se recomienda.
Ejemplo:
int a=0; void main(void) { //Anything you want to code. }
fuente
void main(void)
¡Oh, cómo arde!main
se supone que devuelve un código de estado. En * nix, es más habitual declararlo comoint main(int argc, char *argv[])
, creo que Windows tiene convenciones similares.Un enfoque es utilizar macros. Coloque esto en un archivo de encabezado
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__)
Esto hace posible devolver hasta cuatro variables de una función y asignarlas a hasta cuatro variables. Como ejemplo, puede usarlos así:
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; }
Esto es lo que imprime:
(55, 3.9, 24.15)
Es posible que la solución no sea tan portátil porque requiere C99 o posterior para macros variadic y declaraciones de variables for-statement. Pero creo que fue lo suficientemente interesante como para publicarlo aquí. Otro problema es que el compilador no te advertirá si les asignas valores incorrectos, por lo que debes tener cuidado.
En mi repositorio de github hay disponibles ejemplos adicionales y una versión del código basada en pilas que usa uniones .
fuente
__typeof__