问题提出

《C Programming Language》书中在递归这一节预留了两个使用递归实现的函数,其中itoa函数是用来将一个整数转换为一个字符串。书中已有使用循环实现的版本,但是直接得到的是反序的结果,需要最后调用reverse函数。而递归版本则可以避免这个问题。 
首先使用原接口void itoa(int n, char s[])进行实现,发现递归调用的时候总是错误,输出的结果只能得到整数n的最高位和最低位的数字。代码如下:

 void itoa(int n, char* s)
{
if (n < )
{
*s = '-';
s++;
}
if (abs(n) / )
itoa(abs(n) / , s++);
*s = abs(n) % + '';
}

基本思想:使用字符指针s进行移动,递归调用的过程中进行指针的自增。但是使用gcc编译后运行结果并不正确。只能输出整数n的最高位和最低位的两个数字。 
错误原因:经过仔细调试,发现字符指针参数每次递归调用时,传入的s++这个变量时进行了复制,也就是在后续的递归调用中对指针s的自增操作不会反映到第一次调用的指针s上去,因此,第一次调用这个函数并最终调用*s = abs(n) % 10 + '0';这一语句时,指针s指向的是字符数组的第二个位置。就将整数n的最低位放在第二个位置,而整数n的最高位一直进行递归调用并将参数指针变量复制(一直指向第一个位置),也就放在了第一个位置。最后返回的结果就只有两个数字。

已有的方案

针对上述遇到的问题,在网上搜索了这个问题。使用最多的就是使用局部静态变量保存字符数组的下标,参考http://blog.csdn.net/long_xing/article/details/2212450。但是,另外一篇博客中的实现存在逻辑错误,提前给字符数组赋“\0”,参见http://blog.csdn.net/roma823/article/details/6546719

自己实现

经过一段时间的思考,最终想到的办法就是二级字符指针,因为使用字符指针函数参数时,递归调用传入的字符指针使用了复制,这应该是编译器对字符指针(相当于字符串),在进行传递参数时使用复制指针(也就是复制字符串)这种实现,与普通意义上的指针参数调用时直接操作源指针的思想有所区别。因此在使用一个二级字符指针,每次传递的是指向字符串的同一个指针,这样就不会出现递归调用过程中对指针的自增操作对上一级调用函数无效的情况,代码如下:

 void itoa(int num, char** s)
{
if (num < )
{
**s = '-';
(*s)++;
}
if (abs(num / ) > )
{
itoa(abs(num / ), s);
(*s)++;
}
**s = abs(num % ) + '';
}

上述版本使用了abs库函数,可以转换最大负整数。测试如下:

 int main()
{
char s[], *ps = s;
itoa(, &ps); //测试正整数
*(++ps) = '\0';
printf("%s\n", s); ps = s;
itoa(-, &ps); //测试最大的负整数(32 bits)
*(++ps) = '\0';
printf("%s\n", s); return ;
}

itoa函数的递归实现(二级指针实现)的更多相关文章

  1. C语言一级指针与二级指针

    指针的概念 指针就是地址, 利用这个地址可以找到指定的数据 指针就是地址, 那么在使用的时候, 常常会简单的说 指针变量为指针 指针变量就是存储地址的变量 int *p1;// 申请了一个变量, 即在 ...

  2. 真正明白C语言二级指针(转载)

    指针是C语言的灵魂,我想对于一级指针大家应该都很熟悉,也经常用到:比如说对于字符串的处理,函数参数的“值,结果传递”等,对于二级指针或者多级指针,我想理解起来也是比较容易的,比如二级指针就是指向指针的 ...

  3. C 真正理解二级指针

    本文转载自CSDN博主liaoxinmeng,做数据结构时遇到指针方面的问题,想了许久,因此我觉得很有必要复习一下二级指针及其使用 正文如下: 指针是C语言的灵魂,我想对于一级指针大家应该都很熟悉,也 ...

  4. 真正明白c语言二级指针

    指针是C语言的灵魂,我想对于一级指针大家应该都很熟悉,也经常用到:比如说对于字符串的处理,函数参数的“值,结果传递”等,对于二级指针或者多级指针,我想理解起来也是比较容易的,比如二级指针就是指向指针的 ...

  5. 对线程等待函数pthread_join二级指针参数分析

    分析之前先搞明白,这个二级指针其实在函数内部是承接了上个线程的返回值. 看man手册,发现返回值是个普通指针.人家用二级指针来承接,可能准备干大事.这个可以自己搜索一下.原因嘛,二级指针是保存了这个地 ...

  6. C#中调用C++的dll的参数为指针类型的导出函数(包括二级指针的情况)

    严格来说这篇文章算不上C++范围的,不过还是挂了点边,还是在自己的blog中记录一下吧. C++中使用指针是家常便饭了,也非常的好用,这也是我之所以喜欢C++的原因之一.但是在C#中就强调托管的概念了 ...

  7. C-指针,二级指针,二维数组作为函数参数使用,C语言链表(详解)

    一级指针 int *p;            //表示定义一个int型(4字节)的指针p &p                 //表示p自身的地址位置 p                  ...

  8. (C++)函数参数传递中的一级指针和二级指针

    主要内容: 1.一级指针和二级指针 2.函数指针传递的例子 3.什么时候需要传递二级指针? 4.二级指针在链表中的使用 1.一级指针和二级指针 一级指针:即我们一般说的指针,就是内存地址: 二级指针: ...

  9. FreeRTOS信号量的封装函数参数是二级指针

    1. 先看正确的封装方式,问题所在,为什么要用2级指针 void cissys_lockcreate(void** mutex) { //创建信号量,应该是互斥锁 *mutex = ((Semapho ...

随机推荐

  1. HIDKomponente使用读写Hid设备一瞥

    HIDKomponente 是delphi中使用的第三方Hid控件库,可以检测.控制连接到电脑的Hid设备.一般情况下多为usb设备.HIDKomponente的使用实际上很简单,只是因为第一次使用, ...

  2. DOS 命令 attrib:修改文件属性

    有时候系统中病毒之后会把自己的所有文件的属性改为隐藏只读格式,如果手动修改的话太麻烦并且浪费时间,不如用 Attrib 命令试试. 步骤: 1:开始->运行,在里面输入 cmd,打开命令行界面: ...

  3. ajax调用webService中的方法

    页面代码 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Index.aspx. ...

  4. SOAP 及其安全控制--转载

    原文地址:http://my.oschina.net/huangyong/blog/287791 目录[-] 1. 基于用户令牌的身份认证 2. 基于数字签名的身份认证 3. SOAP 消息的加密与解 ...

  5. TCP连接的建立与关闭

    TCP是主机对主机层的传输控制协议:建立连接要三个握手,断开连接要四次挥手. 位码即TCP标志位,有6种标示:SYN(synchronous建立联机),ACK(acknowledgement 确认), ...

  6. mysql中的存储过程和事务隔离

    ※存储过程存储过程是保存在数据库上的一段可执行代码.1.定义存储过程的语法是:Create procedure sp_name (参数..)Begin SQL语句End;2.调用它的方法:Call s ...

  7. Matlab plotyy函数的使用及问题总结

    MATLAB函数,用来绘制双纵坐标图. 调用格式: 1.plotyy(X1,Y1,X2,Y2):以左.右不同纵轴绘制X1-Y1.X2-Y2两条曲线. 2.plotyy(X1,Y1,X2,Y2,FUN1 ...

  8. 收回动态VHD的未使用空间

    随着虚拟机的运行,虚拟机磁盘所占空间越来越大,而实际使用并没有那么大,考虑回收未使用部分. 收回动态VHD的未使用空间(压缩VHD) 有一种方法是ghost,两个vhd文件对拷.本文不是那个方法 本文 ...

  9. 解决 Zabbix agent on [HOSTNAME] is unreachable for 5 minutes

    今天中午发现zabbix陆续出现Zabbix agent on [HOSTNAME] is unreachable for 5 minutes问题,开始是只是寥寥几台,没太在意,吃了顿饭回来发现一大堆 ...

  10. 牛客OJ——[编程题]A+B和C__如何输入多组测试数据(测试OK)

    几个要注意的地方: (1)Java OJ,必须将类名写成Main (2)关于如何输入多组测试数据,用二维数组去存储是一个方法,直接在while里面做也可以          但是如果  (3)关于整形 ...