Se eu tenho uma função que produz um resultado inte um resultado string, como faço para retornar os dois de uma função?
Até onde sei, só posso retornar uma coisa, conforme determinado pelo tipo que precede o nome da função.
Se eu tenho uma função que produz um resultado inte um resultado string, como faço para retornar os dois de uma função?
Até onde sei, só posso retornar uma coisa, conforme determinado pelo tipo que precede o nome da função.
Respostas:
Não sei qual stringé o seu , mas vou presumir que ele administra sua própria memória.
Você tem duas soluções:
1: Retorne um structque contém todos os tipos de que você precisa.
struct Tuple {
int a;
string b;
};
struct Tuple getPair() {
Tuple r = { 1, getString() };
return r;
}
void foo() {
struct Tuple t = getPair();
}
2: Use ponteiros para passar 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);
}
Qual você escolhe usar depende muito da preferência pessoal quanto à semântica que você mais gosta.
char *a size_tpara o comprimento, a menos que seja absolutamente vital para a função alocar sua própria string e / ou retornar NULL.
getPairentão desreferencia . Dependendo do que você está fazendo (OP nunca esclareceu se esta é realmente uma questão C), a alocação pode ser uma preocupação, mas geralmente não está no terreno C ++ (a otimização do valor de retorno salva tudo isso) e no terreno C, os dados as cópias geralmente acontecem explicitamente (via strncpyou qualquer outro).
Option 1: Declara uma estrutura com um int e uma string e retorna uma variável de estrutura.
struct foo {
int bar1;
char bar2[MAX];
};
struct foo fun() {
struct foo fooObj;
...
return fooObj;
}
Option 2: Você pode passar um dos dois via ponteiro e fazer alterações no parâmetro real por meio do ponteiro e retornar o outro como de costume:
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: Semelhante à opção 2. Você pode passar via ponteiro e não retornar nada da função:
void fun(char **param1,int *param2) {
strcpy(*param1,"....");
*param2 = /* some calculated value */
}
int fun(char *param, size_t len)
strcpypor exemplo.
Como um de seus tipos de resultado é uma string (e você está usando C, não C ++), recomendo passar ponteiros como parâmetros de saída. Usar:
void foo(int *a, char *s, int size);
e chamá-lo assim:
int a;
char *s = (char *)malloc(100); /* I never know how much to allocate :) */
foo(&a, s, 100);
Em geral, prefira fazer a alocação na função de chamada , não dentro da própria função, para que você possa estar o mais aberto possível para diferentes estratégias de alocação.
Duas abordagens diferentes:
Acho que o nº 1 é um pouco mais óbvio sobre o que está acontecendo, embora possa se tornar tedioso se você tiver muitos valores de retorno. Nesse caso, a opção nº 2 funciona muito bem, embora haja alguma sobrecarga mental envolvida na criação de estruturas especializadas para esse propósito.
string, pode ser seguro assumir C ++ ...
Passando parâmetros por referência à função.
Exemplos:
void incInt(int *y)
{
(*y)++; // Increase the value of 'x', in main, by one.
}
Também usando variáveis globais, mas não é recomendado.
Exemplo:
int a=0;
void main(void)
{
//Anything you want to code.
}
void main(void)OH, COMO QUEIMA!
maindeve retornar um código de status. Em * nix, é mais comum declará-lo como int main(int argc, char *argv[]), acredito que o Windows tem convenções semelhantes.
Uma abordagem é usar macros. Coloque isso em um arquivo de cabeçalhomultitype.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__)
Isso possibilita retornar até quatro variáveis de uma função e atribuí-las a até quatro variáveis. Como exemplo, você pode usá-los assim:
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;
}
Isto é o que imprime:
(55, 3.9, 24.15)
A solução pode não ser tão portátil porque requer C99 ou posterior para macros variáveis e declarações de variáveis para instruções. Mas acho que foi interessante postar aqui. Outro problema é que o compilador não irá avisá-lo se você atribuir a eles os valores errados, então você deve ter cuidado.
Exemplos adicionais e uma versão baseada em pilha do código usando uniões estão disponíveis em meu repositório github .
__typeof__
stringque você quer dizer "Eu estou usando C ++ e esta é astd::stringclasse" ou "Eu estou usando C e este é umchar *ponteiro ouchar[]matriz."