zoukankan      html  css  js  c++  java
  • c++实现atoi()和itoa()函数(字符串和整数转化)

    (0)

    c++类型所占的字节和表示范围

    c 语言里 类型转换那些事儿(补码 反码)

    应届生面试准备之道

    最值得学习阅读的10个C语言开源项目代码

    一:起因

    (1)字符串类型转化为整数型(Integer)。还是字符串类型(String)转化为Double类型,这在java里面有非常好的内部函数。非常easy的事情;

    (2)可是在c里面没有Integer Double等包装类,由char[]数组转化为整数型就变得不那么简单了,atoi()  itoa()在widows以下有,可是网上说linux 下好像没有 itoa() 函数,用 sprintf() 好了。可是本人測试了一下sprintf()  sscanf()的效率非常低。

    (3)所以自己手动实现了一下atoi()(字符串转整数)  itoa(整数转字符串)两个函数,有哪里不正确的地方,大家指正。

    (4)我也幼稚过 请看 当初写的关于int --> string 的 blog

    (插入———— begin)

    (0) 在区间(0,1)上任取三个数,则这三个数之和小于1的概率为?

    答案是1/6,怎么计算的,求具体解答?
    设所取的三个数分别为 x、y、z ,则 0<x<1,0<y<1,0<z<1 ,
    满足上述条件的点 P(x,y,z)构成一个棱长为 1 的正方体,体积为 V=1*1*1=1 ,
    满足 x+y+z=1 的点是分别过(1,0,0)、(0,1,0)、(0,0,1)的平面,
    而满足 x+y+z<1 的点位于正方体内、平面的下方,体积为 V1=1/3*1/2*1*1*1=1/6  (要是三个随意小于2的数呢?) 

    (1)先看一段程序

    // test for begin
    #define fuc(a) ((a)*(a))
    //test for end
    	// test for begin
    	int aa = 5;
    	cout << "fuc(a++): " << fuc(aa++) <<endl;//25
    	aa = 5;
    	cout << "fuc(++a): " << fuc(++aa) <<endl;//49
    	aa = 5;
    	cout << aa << aa++ << endl;//6,5
    	aa = 5;
    	cout << aa++ << aa << endl;// 5,5
    
    	int b[7] = {1,2,3,4,5,7,8};
    	int *ptr = (int*)(&b+1);// 如今的ptr指向数组长度的下一位置
    	printf("%d,%d
    ",*(b+1),*(ptr-1));// ptr-1指向b[len-1]最后一个元素
    	cout << &b << "," << ptr << "," << b << "," << (*ptr) << endl;
    
    	int d = 5;
    	int c =10;
    	int &ii = d;// 大哥啊,这是引用啊~~~哎~~~这都不会了,还笔试个毛啊。这都忘了,还面试个毛啊
    	int *jj = &c;
    	int *&kk = jj;// 从右往左读,指针的引用;
       	 //int*&p 是 指针的引用,它是一个 指针 的 别名 ,一般能够当成 指针 使用。

    cout << ii << endl; //test for end

    解析

    int *ptr=(int *)(&a+1)

    【理论知识】:首先须要搞明确a,&a.     a既是数据名,又是指向数组第一个元素的指针。

    sizeof(a)=20, 此时a的类型为int[5]数组。

    sizeof(*a)=4,由于有取值符*,表示把a当成一个指针(int*),而a指向数组的首地址,即a=&(a[0]),即sizeof(*a)=sizeof(*&(a[0]))=sizeof(a[0])=sizeof(int)=4。

    *(a+1)中把a当成一个指针,a+1=a+sizeof(int)。a+1指向a的下一个整形地址既&a[1]。因此*(a+1)=*(&a[1])=a[1]=2。

    (&a+1)先取变量a的地址,并依据a的地址获得下一个与a同类型的相邻地址。依据前面所说的a的类型为int[5]数组。

    &a+1=&a+sizeof(5*int),因此&a+1指向的地址为&a[5](数组a[5]的下一个地址)。(int*)(&a+1)把这个相邻地址显式类型转换为int类型的地址int*ptr=(int*)(&a+1);所以ptr指向&a[5],而且ptr是一个int类型的指针。

    ptr-1=ptr-sizeof(int),故ptr-1指向&a[4]。

    因此,*(ptr-1)的值即为a[4]=5。

    【个人理解】:
    a[5]即能够看成是一个一维数组,也能够看成是一个仅仅有一行的二维数组a[1][5]。
    所以a指向一维数组的首地址,即a=&a[0],a+1指向&a[1]。

    每次加的地址长度为sizeof(int).
    而&a指向二维数组的首地址,即&a=&a[0][5],&a+1指向&a[1][5]。每次加的地址长度为sizeof(5*int).

    (3)【题目】

    Given a singly linked list L: L0→L1→…→Ln-1→Ln,
    reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
    You must do this in-place without altering the nodes' values.

    【分析】
    题目思路比較直接:
    (1)找到链表的中间节点,把链表划分成2个子链表。假设原链表长度为奇数。那么第一个子链表的长度多1。
    (2)翻转第二个子链表;
    (3)交叉合并两个子链表。


    比如{1,2,3,4,5,6,7}
    (1)找到链表的中间节点为4,把链表划分成2个子链表:{1,2,3,4}和{5,6,7}。
    (2)翻转第二个子链表得到{7,6,5}
    (3)交叉合并{1,2,3,4}和{7,6,5}得到{1,7,2,6,3,5,4}

    //
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/5/30
    */
    #include "stdafx.h"
    
    
    struct ListNode
    {
        int value;
        ListNode *next;
    };
    
    // find middle node of list
    ListNode *FindMiddleNode(ListNode *head)
    {
        if(NULL == head)
            return NULL;
        ListNode *fast = head, *slow = head;
        while(fast != NULL && fast->next != NULL)
        {
            // move fast 2 steps
            fast = fast->next->next;
            if (fast == NULL)
                break;
            // move slow 1 step
            slow = slow->next;
        }
        return slow;
    }
    
    // reverse list
    ListNode *ReverseList(ListNode *head)
    {
        if(NULL == head || NULL == head->next)
            return head;
        ListNode *prev = NULL, *cur = head, *next = NULL;
        while(cur != NULL)
        {
            // save next
            next = cur->next;
            // reverse
            cur->next = prev;
            // update prev and cur
            prev = cur;
            cur = next;
        }
        return prev;
    }
    
    // cross merge list
    ListNode *CrossMergeList(ListNode *head1, ListNode *head2)
    {
        if(NULL == head1)
            return head2;
        else if (NULL == head2)
            return head1;
    
    
        ListNode *node1 = head1, *node2 = head2;
        while(node2 != NULL)
        {
            ListNode *temp1 = node1->next;
            ListNode *temp2 = node2->next;
            node1->next = node2;
            node2->next = temp1;
            // update node1 node2
            node1 = temp1;
            node2 = temp2;
        }
        return head1;
    }
    
    
    // reorder list
    ListNode *ReOrderList(ListNode *head)
    {
        if(NULL == head || NULL == head->next)
            return head;
    
    
        // find middle node of list
        ListNode *middle = FindMiddleNode(head);
        // split into 2 lists
        ListNode *head1 = head;
        ListNode *head2 = middle->next;
        // detach the 2 lists
        middle->next = NULL;
        // reverse list2
        head2 = ReverseList(head2);
        // cross merge 2 lists
        return CrossMergeList(head1, head2);
    }

    (插入——————end)

    二:实现

    (1)atoi()函数原型:int atoi(char *str)  头文件 stdlib.h

    函数用途:将字符串转换成一个整数值
    输入參数:str 待转换为整型数的字符串
    返回值:成功返回转换后的数值,失败则返回0.

    (2)代码实现

    int my_atoi(char s[])
    {
        int i,n,sign;
    
        for(i=0;isspace(s[i]);i++);   //跳过空白,isspace()这个函数在type.h头文件里;也能够s[i]==' '实现
    
        sign=(s[i]=='-')?

    -1:1; if(s[i]=='+'||s[i]=='-') //跳过符号位 i++; for(n=0;isdigit(s[i]);i++) n=10*n+(s[i]-'0'); //将数字字符转换成整形数字,isdigit()这个函数在type.h头文件里。也能够s[i]>='0' && s[i]<='9''实现; 0x30是 '0' return sign*n; }

    (3) itoa()函数的原型:char *itoa( int value, char *str,int radix)

    函数用途:将整数型值value转换成一个字符串
    输入參数:value待转换的整型数 。str
    目标字符串的地址,即返回值。radix:转换后的进制数,能够是10进制、16进制等。

    返回值:成功返回一个字符串.

    (4)代码实现

    /*
    Converts an int or long into a character string
    将一个整数转化为字符串
    */
    char* my_itoa(int n,char str[])
    {
        int i,j,len,sign;
    
        if((sign=n)<0)    //记录符号
            n=-n;         //使n成为正数
        i=0;
        do{
            str[i++]=n%10+'0';    //取下一个数字
        }while((n/=10)>0);      //循环相除
    
        if(sign<0)
            str[i++]='-';
        str[i]='';
        len = i;//
        for(j=len-1,i=0;j>i;j--,i++)        //生成的数字是逆序的,所以要交换
        {
            str[j] ^= str[i];
            str[i] ^= str[j];
            str[j] ^= str[i];
        }
        return str;
    }

    (5) 主函数測试

    #include "stdio.h"
    #include "ctype.h"
    #include "stdlib.h"
    int main()
    {
        int n;
        char str[32],*ans;
        ans = my_itoa(-123,str);
        printf("自编自导的整形转字符串函数my_itoa():%s %s
    ",ans,str);
        printf("系统自带的整形转字符串函数itoa():%s %s
    ",itoa(-1,str,16),str);
        printf("自编自导的字符串转整形函数my_atoi():%d
    ",my_atoi("  22qqq"));
        printf("系统自带的字符串转整形函数atoi():%d
    ",atoi("  -2qqq "));
        system("pause");
        return 0;
    }

    (6)測试结果:



    三:不足之处

    (1) itoa()函数的原型:char *itoa( int value, char *str,int radix),自己并未全然实现。仅仅是简单的实现了10进制的

    (2)以下会改进的,上面有不足之处,请大神不吝赐教

    (3) itoa()函数的原型:char *itoa( int value, char *str,int radix)。自己简单的实现。默认是实现了10进制的

    char __itoa[] = {'0','1','2','3','4','5','6','7','8','9',
                    'a','b','c','d','e','f'};
    const unsigned int MY_MAX = 0xFFFFFFFFu;
    char* my_itoa2(int n,char str[],int radix=10)
    {
        int i,j,len,sign;
        unsigned int tmp;
        i = 0;
        if(n<0)    //
        {
            tmp = MY_MAX + n + 1;// 这样貌似能够了,依照取反加一的方式进行的
            do{
                str[i++]=__itoa[tmp%radix];    //取下一个数字
            }while((tmp/=radix)>0);//循环相除
        }
        else
        {
            do{
                str[i++]=__itoa[n%radix];    //取下一个数字
            }while((n/=radix)>0);//循环相除
        }
    
        str[i]='';
        len = i;//
        for(j=len-1,i=0;j>i;j--,i++)        //生成的数字是逆序的,所以要交换
        {
            str[j] ^= str[i];
            str[i] ^= str[j];
            str[j] ^= str[i];
        }
        return str;
    }


  • 相关阅读:
    Android之Handler
    错误一览表
    Android ImageView 的scaletype属性详细介绍 转
    Adobe Flash/Dreamweaver/Fireworks CS3 软件不能安装问题
    MySQL修改表属性的SQL语句
    Apache与Tomcat整合
    mySQL常用SQL语句技法
    今天第一次写博客
    Tomcat+JSP经典配置实例
    整合Apache+Tomcat服务器2
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5154943.html
Copyright © 2011-2022 走看看