iconv函数详细解释

最近在使用iconv函数,感觉iconv的函数参数很奇怪。仔细研究了一下,发现iconv实际上一个返回多个值的函数。此函数利用函数参数,同时返回了好几个值,每个函数参数既是入参,也是出参。详细解释如下:

iconv的原型如下:
    size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft);


函数参数比较奇怪的地方有:
 1.inbuf 为什么是二级指针,而不是一级指针。
 2.inbytesleft为什么是指针,而不是普通变量。
 3.outbuf 为什么是二级指针,而不是一级指针。
 4.outbytesleft 为什么是指针,而不是普通变量
 

原来,函数执行后,由于各种原因(输出缓冲区太小,输入字符串不是一种编码,而是含有多种编码),可能只转换了部分编码。这时返回值为-1,这时会改变后四个参数的值。另外,即使全部转换成功,这四个参数的值也要发生变化。


作为入参
第一个参数cd是转换句柄。
第二个参数inbuf是输入字符串的地址的地址。
第三个参数inbytesleft是输入字符串的长度。
第四个参数outbuf是输出缓冲区的首地址
第五个参数outbytesLeft 是输出缓冲区的长度。


作为出参
第一个参数cd是转换句柄。
第二个参数inbuf指向剩余字符串的地址
第三个参数inbytesleft是剩余字符串的长度。
第四个参数outbuf是输出缓冲区剩余空间的首地址
第五个参数outbytesLeft 是输出缓冲区剩余空间的长度。

这下,同学们应该明白为什么后四个参数,为什么要多取一级地址了吧。

下面是几个例子:

int UTF8ToGBK(char* input, size_t& charInPutLen, char* output, size_t& charOutPutLen)
{
    
    int ret =0;
    iconv_t cd;
    cd = iconv_open("GBK","utf-8");
    ret = iconv(cd, &input, &charInPutLen, &output, &charOutPutLen);
    iconv_close(cd);
    return ret;
}
 
int UTF8ToGBK(const string& input, string& output)
{
    int ret =0;
    size_t charInPutLen = input.length();
    if( charInPutLen == 0)
        return 0;
    char *pSource =(char *)input.c_str();
    size_t charOutPutLen = 2*charInPutLen;
    char *pTemp = new char[charOutPutLen];
    memset(pTemp,0,2*charInPutLen);
    
    iconv_t cd;
    char *pSource =(char *)input.c_str();
    char *pOut = pTemp ;
    cd = iconv_open("utf-8", "GBK");
    ret = iconv(cd, &pSource, &charInPutLen, &pTemp, &charOutPutLen);
    iconv_close(cd);
    output = pOut;
    delete []pOut;//注意这里,不能使用delete []pTemp, iconv函数会改变指针pTemp的值
    return ret;
}
 
int  GBKToUTF8(char* input, size_t charInPutLen, char* output, size_t &charOutPutLen)
{
    int ret = 0;
    iconv_t cd;
    cd = iconv_open("utf-8", "GBK");
    ret = iconv(cd, &input, &charInPutLen, &output, &charOutPutLen);
    iconv_close(cd);
    return ret;
}
 
 
int  GBKToUTF8(const string& input, string& output)
{
    int ret = 0;
    size_t charInPutLen = input.length();
    if( charInPutLen == 0)
        return 0;
    
    size_t charOutPutLen = 2*charInPutLen+1;
    char *pTemp = new char[charOutPutLen];
    memset(pTemp,0,charOutPutLen);
    iconv_t cd;
    char *pSource =(char *)input.c_str();
    char *pOut = pTemp;
    cd = iconv_open("utf-8", "GBK");
    ret = iconv(cd, &pSource, &charInPutLen, &pTemp, &charOutPutLen);
    iconv_close(cd);
    output= pOut;
    delete []pOut; //注意这里,不能使用delete []pTemp, iconv函数会改变指针pTemp的值
    return ret;
}

--------------------- 
原文:https://blog.csdn.net/smartfox80/article/details/51181700 
版权声明:本文为博主原创文章,转载请附上博文链接!

### C语言中 `iconv` 函数的使用方法 #### 1. 基本概念 `iconv` 是一种用于字符集转换的标准库函数,在 C/C++ 中广泛应用于不同编码之间的转换。它主要由三个核心部分组成:`iconv_open()`、`iconv()` 和 `iconv_close()`。 - **`iconv_open(const char *tocode, const char *fromcode)`**: 创建一个转换描述符,指定源编码 (`fromcode`) 和目标编码 (`tocode`)。 - **`iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)`**: 执行实际的编码转换操作。 - **`iconv_close(iconv_t cd)`**: 关闭并释放之前创建的转换描述符资源。 这些函数通常被用来处理多种字符集间的互转,比如 UTF-8 转 GBK 或者 Unicode 等[^2]。 --- #### 2. 示例代码解析 下面是一个完整的示例程序,展示如何使用 `iconv` 进行编码转换: ```c #include <stdio.h> #include <stdlib.h> #include <iconv.h> #include <string.h> int ConvertCode(char *from_charset, char *to_charset, char *inbuf, size_t inlen, char *outbuf, size_t outlen) { iconv_t cd; char **pin = &inbuf; char **pout = &outbuf; // 初始化转换器 cd = iconv_open(to_charset, from_charset); if (cd == (iconv_t)(-1)) { perror("iconv_open failed"); return -1; } // 清空输出缓冲区 memset(outbuf, 0, outlen); // 开始转换 size_t result = iconv(cd, pin, &inlen, pout, &outlen); if (result == (size_t)(-1)) { switch (errno) { case E2BIG: printf("Error: Output buffer is too small.\n"); break; case EILSEQ: printf("Error: Invalid multibyte sequence encountered.\n"); break; case EINVAL: printf("Error: Incomplete multibyte character at the end of input.\n"); break; } iconv_close(cd); return -1; } // 结束时关闭转换器 iconv_close(cd); return 0; } void main() { char input[] = "hello你好"; char output[128] = {0}; // 将输入字符串从 UTF-8 编码转换为 GBK 编码 if (ConvertCode("UTF-8", "GBK", input, strlen(input), output, sizeof(output)) != 0) { fprintf(stderr, "Conversion failed!\n"); exit(EXIT_FAILURE); } printf("Input : %s\nOutput: %s\n", input, output); } ``` 此代码实现了将一段文本从 UTF-8 编码转换到 GBK 编码的功能,并打印原始数据和转换后的结果[^4]。 --- #### 3. 注意事项 - 输入缓冲区 (`inbuf`) 和输出缓冲区 (`outbuf`) 都必须分配足够的内存空间,不能定义为只读常量字符串。例如,以下写法是错误的: ```c char *inbuf = "abc"; // 错误 char *outbuf = "123"; // 错误 ``` - 如果输出缓冲区过小,则可能导致转换失败,具体表现为 `E2BIG` 错误。因此建议预先估算所需的空间大小或者多次调用 `iconv` 来逐步完成大文件的转换。 - 动态链接可能带来安全隐患,如果加载了恶意编写的共享库,可能会篡改主程序的行为。所以在生产环境中应特别小心管理依赖关系[^3]。 --- #### 4. 应用场景扩展 除了简单的单次转换外,还可以结合流式接口实现更复杂的任务,例如逐块读取大型文件的内容进行实时编码变换;也可以嵌套多个连续的 `iconv` 操作链路支持跨多级中间状态下的最终映射效果等等[^1]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值