Sonuç intve sonuç üreten bir işleve sahipsem string, her ikisini de işlevden nasıl döndürürüm?
Anlayabildiğim kadarıyla, işlev adından önceki türe göre belirlendiği gibi yalnızca bir şeyi döndürebilirim.
Sonuç intve sonuç üreten bir işleve sahipsem string, her ikisini de işlevden nasıl döndürürüm?
Anlayabildiğim kadarıyla, işlev adından önceki türe göre belirlendiği gibi yalnızca bir şeyi döndürebilirim.
Yanıtlar:
Senin ne olduğunu bilmiyorum string, ama kendi hafızasını yönettiğini varsayacağım.
İki çözümünüz var:
1: structİhtiyacınız olan tüm türleri içeren bir döndür.
struct Tuple {
int a;
string b;
};
struct Tuple getPair() {
Tuple r = { 1, getString() };
return r;
}
void foo() {
struct Tuple t = getPair();
}
2: Değerleri iletmek için işaretçiler kullanın.
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);
}
Hangisini kullanmayı seçeceğiniz, büyük ölçüde hangi anlambilimden daha çok hoşlandığınız konusunda kişisel tercihinize bağlıdır.
char *ve a size_tolarak iletirim NULL.
getPairdaha sonra başvurulardan vazgeçiyor . Ne yaptığınıza bağlı olarak (OP, bu gerçekten bir C sorusu olup olmadığını asla açıklığa kavuşturmadı), tahsis bir endişe olabilir, ancak genellikle C ++ arazisinde değildir (geri dönüş değeri optimizasyonu tüm bunları kaydeder) ve C alanında, veriler kopyalar genellikle açıkça (aracılığıyla strncpyveya her neyse) gerçekleşir.
Option 1: Bir int ve string içeren bir yapı bildirin ve bir struct değişkeni döndürür.
struct foo {
int bar1;
char bar2[MAX];
};
struct foo fun() {
struct foo fooObj;
...
return fooObj;
}
Option 2: İkisinden birini işaretçi aracılığıyla geçirebilir ve işaretçi aracılığıyla gerçek parametrede değişiklikler yapabilir ve diğerini her zamanki gibi döndürebilirsiniz:
int fun(char **param) {
int bar;
...
strcpy(*param,"....");
return bar;
}
veya
char* fun(int *param) {
char *str = /* malloc suitably.*/
...
strcpy(str,"....");
*param = /* some value */
return str;
}
Option 3: 2. seçeneğe benzer şekilde. Her ikisini de işaretçi aracılığıyla geçirebilir ve işlevden hiçbir şey döndüremezsiniz:
void fun(char **param1,int *param2) {
strcpy(*param1,"....");
*param2 = /* some calculated value */
}
int fun(char *param, size_t len)
strcpyÖrneğin kullandığımıza benzer bir şey .
Sonuç türlerinizden biri bir dize olduğundan (ve C ++ değil, C kullandığınız için), işaretçileri çıktı parametreleri olarak iletmenizi öneririm. Kullanım:
void foo(int *a, char *s, int size);
ve şöyle diyelim:
int a;
char *s = (char *)malloc(100); /* I never know how much to allocate :) */
foo(&a, s, 100);
Genel olarak, farklı tahsis stratejilerine mümkün olduğunca açık olabilmeniz için tahsisatı fonksiyonun içinde değil , çağıran fonksiyonda yapmayı tercih edin .
İki farklı yaklaşım:
Bence 1 numaranın neler olduğu konusunda biraz daha açık olduğunu düşünüyorum, ancak çok fazla dönüş değeriniz varsa sıkıcı olabilir. Bu durumda, 2. seçenek oldukça iyi işliyor, ancak bu amaç için özel yapılar oluşturmanın bazı zihinsel yükleri olsa da.
string, varsaymak güvenli olabilir C ++ ...
Parametreleri işleve başvurarak ileterek.
Örnekler:
void incInt(int *y)
{
(*y)++; // Increase the value of 'x', in main, by one.
}
Ayrıca global değişkenler kullanılarak, ancak tavsiye edilmez.
Misal:
int a=0;
void main(void)
{
//Anything you want to code.
}
void main(void)OH NASIL YAKAR!
mainbir durum kodu döndürmesi gerekiyor. * Nix altında, int main(int argc, char *argv[])Windows'un benzer kurallara sahip olduğuna inanıyorum.
Bir yaklaşım, makro kullanmaktır. Bunu bir başlık dosyasına yerleştirinmultitype.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__)
Bu, bir işlevden en fazla dört değişken döndürmeyi ve bunları en fazla dört değişkene atamayı mümkün kılar. Örnek olarak, bunları şu şekilde kullanabilirsiniz:
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;
}
Bu, yazdırdığı şey:
(55, 3.9, 24.15)
Çözüm, değişken makrolar ve deyim için değişken bildirimleri için C99 veya sonrasını gerektirdiğinden taşınabilir olmayabilir. Ama buraya yazacak kadar ilginç olduğunu düşünüyorum. Diğer bir konu da derleyicinin yanlış değerleri atarsanız sizi uyarmamasıdır, bu yüzden dikkatli olmanız gerekir.
Ek örnekler ve birleşim kullanan kodun yığın tabanlı sürümü github depomda mevcuttur .
__typeof__
stringyapmak "Ben C ++ kullanıyorum ve bu demekstd::stringsınıf" veya "Ben C kullanıyorum ve bu bir olanchar *işaretçi veyachar[]dizi."