时间:2021-05-20
C语言实现进制转换函数的实例详解
前言:
写一个二进制,八进制,十六进制转换为十进制的函数
要求:
系统表 pg_proc 存储关于函数的信息
内部函数在编译之前需要先定义在 pg_proc.h 中,src/include/catalog/pg_proc.h
CATALOG(pg_proc,1255) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81) BKI_SCHEMA_MACRO{ NameData proname; Oid pronamespace; Oid proowner; Oid prolang; float4 procost; float4 prorows; Oid provariadic; regproc protransform; bool proisagg; bool proiswindow; bool prosecdef; bool proleakproof; bool proisstrict; bool proretset; char provolatile; int16 pronargs; int16 pronargdefaults; Oid prorettype; /* * variable-length fields start here, but we allow direct access to * proargtypes */ oidvector proargtypes; #ifdef CATALOG_VARLEN Oid proallargtypes[1]; char proargmodes[1]; text proargnames[1]; pg_node_tree proargdefaults;/* list of expression trees for argument * defaults (NULL if none) */ Oid protrftypes[1]; text prosrc BKI_FORCE_NOT_NULL; text probin; text proconfig[1]; aclitem proacl[1]; #endif} FormData_pg_proc;在 proc.h 添加函数定义:
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 x_to_dec 2 0 23 "25 23" x_to_dec这里的传递参数类型和返回值类型都用的了 OID
系统表 pg_type 存储数据类型的信息
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 实现自定义的函数
首先创建函数的整体部分:
Datum x_to_dec (PG_FUNCTION_ARGS) { text *arg1 = PG_GETARG_TEXT_P(0); int32 arg2 = PG_GETARG_INT32(1); /** 实现功能 **/ PG_RETURN_INT32(sum);}这里的 PG_GETARG_XXXX() 和 PG_RETURN_XXXXX() 在 src/include/fmgr.h
知道了如何获取参数以及返回返回值,接下来是具体的实现:
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) ,类型转换的相关函数定义在 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){ 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;}结果:
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.以上就是进制转换的实例,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文实例讲述了C语言实现将字符串转换为数字的方法。分享给大家供大家参考。具体实现方法如下:C语言提供了几个标准库函数,可以将字符串转换为任意类型(整型、长整型、
用C语言实现将十进制转化为二进制,并统计转换后的二进制码中1的个数。#includeintbinaryNum[16];//存放转换后得到的二进制码intcoun
本文实例讲述了C语言实现BMP转换JPG的方法。分享给大家供大家参考。具体实现方法如下:/***********************************
C语言实现时区转换函数的实例时区转换函数功能:把时区1的时间转换成时区2的时间参数:arg1--输入时间arg2--时区1(也是arg1当前时间所在的时区)ar
本文实例讲述了C语言实现字母大小写转换的方法。分享给大家供大家参考。具体实现方法如下:/**将大写字母转换为小写字母*/#includeintlower(int