国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C > 正文

C語言實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換函數(shù)的實(shí)例詳解

2020-01-26 13:58:12
字體:
供稿:網(wǎng)友

C語言實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換函數(shù)的實(shí)例詳解

前言:

寫一個(gè)二進(jìn)制,八進(jìn)制,十六進(jìn)制轉(zhuǎn)換為十進(jìn)制的函數(shù)

要求:

  1. 函數(shù)有兩個(gè)參數(shù),參數(shù)(1)是要轉(zhuǎn)換為十進(jìn)制的進(jìn)制數(shù),參數(shù)(2)是標(biāo)示參數(shù)(1)是什么進(jìn)制(2,8,16標(biāo)示二進(jìn)制,八進(jìn)制,十六進(jìn)制)。
  2. 要有報(bào)錯(cuò)信息,比如參數(shù)是1012,但參數(shù)(2)是2,顯然是進(jìn)制數(shù)表示有錯(cuò)誤。

系統(tǒng)表 pg_proc 存儲(chǔ)關(guān)于函數(shù)的信息

內(nèi)部函數(shù)在編譯之前需要先定義在 pg_proc.h 中,src/include/catalog/pg_proc.h

CATALOG(pg_proc,1255) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81) BKI_SCHEMA_MACRO{ NameData proname; /* procedure name */ /* 函數(shù)名,sql 中 select 函數(shù)名(); */ Oid  pronamespace; /* OID of namespace containing this proc */  /* 模式OID */ Oid  proowner; /* procedure owner */ /* 用戶OID */ Oid  prolang; /* OID of pg_language entry */ float4 procost; /* estimated execution cost */  /* 估計(jì)執(zhí)行成本 */ float4 prorows; /* estimated # of rows out (if proretset) */ /* 結(jié)果行估計(jì)數(shù) */ Oid  provariadic; /* element type of variadic array, or 0 */ regproc protransform; /* transforms calls to it during planning */ bool proisagg; /* is it an aggregate? */ /* 是否為聚集函數(shù) */ bool proiswindow; /* is it a window function? */  /* 是否為窗口函數(shù) */ bool prosecdef; /* security definer */  /* 函數(shù)是一個(gè)安全定義器,也就是一個(gè)“setuid"函數(shù) */ bool proleakproof; /* is it a leak-proof function? */  /* 有無其他影響 */ bool proisstrict; /* strict with respect to NULLs? */ /* 遇到 NULL 值是否直接返回 NULL */ bool proretset; /* returns a set? */ /* 函數(shù)返回一個(gè)集合 */ char provolatile; /* see PROVOLATILE_ categories below */ int16 pronargs; /* number of arguments */ /* 參數(shù)個(gè)數(shù) */ int16 pronargdefaults; /* number of arguments with defaults */ /* 默認(rèn)參數(shù)的個(gè)數(shù) */ Oid  prorettype; /* OID of result type */ /* 返回參數(shù)類型OID */ /* * variable-length fields start here, but we allow direct access to * proargtypes */ oidvector proargtypes; /* parameter types (excludes OUT params) */ /* 存放函數(shù)參數(shù)類型的數(shù)組 */#ifdef CATALOG_VARLEN Oid  proallargtypes[1]; /* all param types (NULL if IN only) */ char proargmodes[1]; /* parameter modes (NULL if IN only) */ text proargnames[1]; /* parameter names (NULL if no names) */ pg_node_tree proargdefaults;/* list of expression trees for argument     * defaults (NULL if none) */ Oid  protrftypes[1]; /* types for which to apply transforms */ text prosrc BKI_FORCE_NOT_NULL; /* procedure source text */ /* 函數(shù)處理器如何調(diào)用函數(shù),實(shí)現(xiàn)函數(shù)的函數(shù)名 */ text probin;  /* secondary procedure info (can be NULL) */ text proconfig[1]; /* procedure-local GUC settings */ aclitem proacl[1]; /* access permissions */#endif} FormData_pg_proc;

在 proc.h 添加函數(shù)定義:

/* myfunc */DATA(insert OID = 6663 ( x_to_dec PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "25 23" _null_ _null_ _null_ _null_ _null_ x_to_dec _null_ _null_ _null_ ));DESCR("x_to_dec.");OID = 6663  /* OID 唯一,不能與其他定義 OID 重復(fù) */x_to_dec  /* sql 中 select x_to_dec(); */2 0 23 "25 23"  /* 傳遞兩個(gè)參數(shù); 默認(rèn) 0; 返回值類型 OID = 23; 參數(shù)1類型 OID = 25, 參數(shù)2類型 OID = 23 */x_to_dec  /* 自定義函數(shù)名 */

這里的傳遞參數(shù)類型和返回值類型都用的了 OID

系統(tǒng)表 pg_type 存儲(chǔ)數(shù)據(jù)類型的信息

postgres=# select oid,typname from pg_type where typname = 'text' or typname = 'int4'; oid | typname -----+--------- 23 | int4 25 | text(2 rows)

在 src/backend/utils/adt/myfuncs.c 實(shí)現(xiàn)自定義的函數(shù)

首先創(chuàng)建函數(shù)的整體部分:

Datum  /* Datum 類型是PG系統(tǒng)函數(shù)大量引用的類型,其定義為:typedef uintptr_c Datum */x_to_dec (PG_FUNCTION_ARGS)  /* 函數(shù)名; 參數(shù) */{  /* 獲取參數(shù) */ text *arg1 = PG_GETARG_TEXT_P(0); int32 arg2 = PG_GETARG_INT32(1);  /** 實(shí)現(xiàn)功能 **/  /* 返回 */ PG_RETURN_INT32(sum);}

這里的 PG_GETARG_XXXX() 和 PG_RETURN_XXXXX() 在 src/include/fmgr.h

知道了如何獲取參數(shù)以及返回返回值,接下來是具體的實(shí)現(xiàn):

Datum x_to_dec (PG_FUNCTION_ARGS){ int n = 0, i = 0, sum = 0, t = 0; text *arg1 = PG_GETARG_TEXT_P(0); int32 arg2 = PG_GETARG_INT32(1); char *str = text_to_cstring(arg1); n = strlen(str); switch(arg2) { case 2:  for(i = n - 1; i >= 0; i--)  {  if((str[i] - '0') != 1 && (str[i] - '0') != 0)  {   ereport(ERROR,   (errcode(ERRCODE_INVALID_PARAMETER_VALUE),   errmsg("Please enter the correct binary number, such as '110011'.")));  }  sum += (str[i] - '0') * ((int)pow(2, n - 1 - i));  }  break; case 8:  for(i = n - 1; i >= 0; i--)  {  if(!(str[i] >= '0' && str[i] <= '7'))  {   ereport(ERROR,   (errcode(ERRCODE_INVALID_PARAMETER_VALUE),   errmsg("Please enter the correct octal number, for example '34567'.")));  }  sum += (str[i] - '0') * ((int)pow(8, n - 1 - i));  }  break; case 16:  for(i = n - 1; i >= 0; i--)  {  if( !(str[i] >= '0' && str[i] <= '9') )  {   if(str[i] >= 'A' && str[i] <= 'F')   {   // Uppercase to lowercase   str[i] = str[i] + 32;   } else if ( !(str[i] >= 'a' && str[i] <= 'f') ) {   ereport(ERROR,    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),    errmsg("Please enter the correct hexadecimal number, for example '9f'.")));   }  }  if(str[i] <= '9')  {   t = str[i] - '0';  } else {   t = str[i] - 'a' + 10;  }  sum = sum * 16 + t;  }  break; default:  ereport(ERROR,  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),  errmsg("Out of range! The second parameter, please enter: 2, 4, 16."))); } PG_RETURN_INT32(sum);}

其中用到了text_to_cstring(arg1) ,類型轉(zhuǎn)換的相關(guān)函數(shù)定義在 src/backend/utils/adt/varlena.c

/* * text_to_cstring * * Create a palloc'd, null-terminated C string from a text value. * * We support being passed a compressed or toasted text value. * This is a bit bogus since such values shouldn't really be referred to as * "text *", but it seems useful for robustness. If we didn't handle that * case here, we'd need another routine that did, anyway. */char *text_to_cstring(const text *t){ /* must cast away the const, unfortunately */ text  *tunpacked = pg_detoast_datum_packed((struct varlena *) t); int  len = VARSIZE_ANY_EXHDR(tunpacked); char  *result; result = (char *) palloc(len + 1); memcpy(result, VARDATA_ANY(tunpacked), len); result[len] = '/0'; if (tunpacked != t) pfree(tunpacked); return result;}

結(jié)果:

postgres=# select x_to_dec('111',2); x_to_dec ----------    7(1 row)postgres=# select x_to_dec('aA',16); x_to_dec ----------   170(1 row)postgres=# select x_to_dec('aA',1);ERROR: Out of range! The second parameter, please enter: 2, 4, 16. 

以上就是進(jìn)制轉(zhuǎn)換的實(shí)例,如有疑問請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 石台县| 太谷县| 西充县| 临海市| 乐陵市| 黑水县| 察雅县| 桃园市| 黄山市| 高雄市| 孟津县| 淳安县| 玛曲县| 闽侯县| 香河县| 勃利县| 浦北县| 德庆县| 通河县| 讷河市| 彭水| 盈江县| 张掖市| 荃湾区| 开阳县| 商丘市| 达拉特旗| 改则县| 太湖县| 祁连县| 澳门| 齐齐哈尔市| 惠来县| 江源县| 金堂县| 岳阳县| 穆棱市| 承德市| 府谷县| 双牌县| 星座|