Si j'ai une fonction qui produit un résultat int
et un résultat string
, comment puis-je les renvoyer tous les deux à partir d'une fonction?
Pour autant que je sache, je ne peux renvoyer qu'une seule chose, comme déterminé par le type précédant le nom de la fonction.
c
return-value
Tony Stark
la source
la source
string
voulez-vous dire "J'utilise C ++ et c'est lastd::string
classe" ou "J'utilise C et ceci est unchar *
pointeur ou unchar[]
tableau."Réponses:
Je ne sais pas ce que vous
string
êtes, mais je vais supposer qu'il gère sa propre mémoire.Vous avez deux solutions:
1: Renvoyez un
struct
qui contient tous les types dont vous avez besoin.struct Tuple { int a; string b; }; struct Tuple getPair() { Tuple r = { 1, getString() }; return r; } void foo() { struct Tuple t = getPair(); }
2: Utilisez des pointeurs pour transmettre des valeurs.
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); }
Celui que vous choisissez d'utiliser dépend en grande partie de vos préférences personnelles quant à la sémantique que vous préférez.
la source
char *
et asize_t
pour la longueur à moins qu'il ne soit absolument vital pour la fonction d'allouer sa propre chaîne et / ou de retournerNULL
.getPair
ensuite . En fonction de ce que vous faites (OP n'a jamais clarifié s'il s'agit en fait d'une question C), l'allocation peut être un problème, mais ce n'est généralement pas dans le domaine C ++ (l'optimisation de la valeur de retour enregistre tout cela) et dans le domaine C, les données les copies se produisent généralement explicitement (via ou autre).strncpy
Option 1
: Déclarez une structure avec un int et une chaîne et retournez une variable de structure.struct foo { int bar1; char bar2[MAX]; }; struct foo fun() { struct foo fooObj; ... return fooObj; }
Option 2
: Vous pouvez passer l'un des deux via le pointeur et apporter des modifications au paramètre réel via le pointeur et renvoyer l'autre comme d'habitude:int fun(char **param) { int bar; ... strcpy(*param,"...."); return bar; }
ou
char* fun(int *param) { char *str = /* malloc suitably.*/ ... strcpy(str,"...."); *param = /* some value */ return str; }
Option 3
: Similaire à l'option 2. Vous pouvez passer les deux via le pointeur et ne rien renvoyer de la fonction:void fun(char **param1,int *param2) { strcpy(*param1,"...."); *param2 = /* some calculated value */ }
la source
int fun(char *param, size_t len)
strcpy
par exemple.Étant donné que l'un de vos types de résultats est une chaîne (et que vous utilisez C, pas C ++), je recommande de passer des pointeurs en tant que paramètres de sortie. Utilisation:
void foo(int *a, char *s, int size);
et appelez-le comme ceci:
int a; char *s = (char *)malloc(100); /* I never know how much to allocate :) */ foo(&a, s, 100);
En général, préférez faire l'allocation dans la fonction appelante , pas à l'intérieur de la fonction elle-même, afin que vous puissiez être aussi ouvert que possible pour différentes stratégies d'allocation.
la source
Deux approches différentes:
Je pense que le n ° 1 est un peu plus évident sur ce qui se passe, bien que cela puisse devenir fastidieux si vous avez trop de valeurs de retour. Dans ce cas, l'option n ° 2 fonctionne assez bien, bien qu'il y ait une surcharge mentale impliquée dans la création de structures spécialisées à cet effet.
la source
string
, il pourrait être prudent de supposer C ++ ...Créez un struct et définissez deux valeurs à l'intérieur et retournez la variable struct.
struct result { int a; char *string; }
Vous devez allouer de l'espace pour le
char *
dans votre programme.la source
Utilisez des pointeurs comme paramètres de fonction. Ensuite, utilisez-les pour renvoyer plusieurs valeurs.
la source
En passant des paramètres par référence à la fonction.
Exemples:
void incInt(int *y) { (*y)++; // Increase the value of 'x', in main, by one. }
Également en utilisant des variables globales, mais ce n'est pas recommandé.
Exemple:
int a=0; void main(void) { //Anything you want to code. }
la source
void main(void)
Oh comment ça brûle!main
est censé renvoyer un code d'état. Sous * nix, il est plus courant de le déclarer commeint main(int argc, char *argv[])
, je crois que Windows a des conventions similaires.Une approche consiste à utiliser des macros. Placez-le dans un fichier d'en-tête
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__)
Cela permet de renvoyer jusqu'à quatre variables à partir d'une fonction et de les affecter à jusqu'à quatre variables. À titre d'exemple, vous pouvez les utiliser comme ceci:
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; }
Voici ce qu'il imprime:
(55, 3.9, 24.15)
La solution n'est peut-être pas aussi portable car elle nécessite C99 ou une version ultérieure pour les macros variadiques et les déclarations de variables for-statement. Mais je pense que c'était assez intéressant pour poster ici. Un autre problème est que le compilateur ne vous avertira pas si vous leur attribuez des valeurs incorrectes, vous devez donc faire attention.
Des exemples supplémentaires et une version basée sur la pile du code utilisant des unions sont disponibles sur mon référentiel github .
la source
__typeof__