程序员面试题精选---“itoa函数”和“atoi函数”

题目:输入一个表示整数的字符串,把该字符串转换成整数并输出。例如输入字符串"345" ,则输出整数345 分析:这道题尽管不是很难,学过C/C++ 语言一般都能实现基本功能,但不同程序员就这道题写出的代码有很大区别,可以说这道题能够很好地反应出程序员的思维和编程习惯,因此已经被包括微软在内的多家公司用作面试题。建议读者在往下看之前自己先编写代码,再比较自己写的代码和下面的参考代码有哪些不同。
首先我们分析如何完成基本功能,即如何把表示整数的字符串正确地转换成整数。还是以"345" 作为例子。当我们扫描到字符串的第一个字符'3' 时,我们不知道后面还有多少位,仅仅知道这是第一位,因此此时得到的数字是3 。当扫描到第二个数字'4' 时,此时我们已经知道前面已经一个3 了,再在后面加上一个数字4 ,那前面的3 相当于30 ,因此得到的数字是3*10+4=34 。接着我们又扫描到字符'5' ,我们已经知道了'5' 的前面已经有了34 ,由于后面要加上一个5 ,前面的34 就相当于340 了,因此得到的数字就是34*10+5=345
分析到这里,我们不能得出一个转换的思路:每扫描到一个字符,我们把在之前得到的数字乘以10 再加上当前字符表示的数字。这个思路用循环不难实现。
由于整数可能不仅仅之含有数字,还有可能以'+' 或者'-' 开头,表示整数的正负。因此我们需要把这个字符串的第一个字符做特殊处理。如果第一个字符是'+' 号,则不需要做任何操作;如果第一个字符是'-' 号,则表明这个整数是个负数,在最后的时候我们要把得到的数值变成负数。
接着我们试着处理非法输入。由于输入的是指针,在使用指针之前,我们要做的第一件是判断这个指针是不是为空。如果试着去访问空指针,将不可避免地导致程序崩溃。另外,输入的字符串中可能含有不是数字的字符。每当碰到这些非法的字符,我们就没有必要再继续转换。最后一个需要考虑的问题是溢出问题。由于输入的数字是以字符串的形式输入,因此有可能输入一个很大的数字转换之后会超过能够表示的最大的整数而溢出。
现在已经分析的差不多了,开始考虑编写代码。首先我们考虑如何声明这个函数。由于是把字符串转换成整数,很自然我们想到:
int StrToInt(const char* str);
这样声明看起来没有问题。但当输入的字符串是一个空指针或者含有非法的字符时,应该返回什么值呢?0 怎么样?那怎么区分非法输入和字符串本身就是”0” 这两种情况呢?
接下来我们考虑另外一种思路。我们可以返回一个布尔值来指示输入是否有效,而把转换后的整数放到参数列表中以引用或者指针的形式传入。于是我们就可以声明如下:
bool StrToInt(const char *str, int& num);
这种思路解决了前面的问题。但是这个函数的用户使用这个函数的时候会觉得不是很方便,因为他不能直接把得到的整数赋值给其他整形变脸,显得不够直观。
前面的第一种声明就很直观。如何在保证直观的前提下当碰到非法输入的时候通知用户呢?一种解决方案就是定义一个全局变量,每当碰到非法输入的时候,就标记该全局变量。用户在调用这个函数之后,就可以检验该全局变量来判断转换是不是成功。
下面我们写出完整的实现代码。参考代码:
enum Status {kValid = 0, kInvalid};
int g_nStatus = kValid;

///
// Convert a string into an integer
///
int StrToInt(const char* str)
{
       g_nStatus = kInvalid;
      
long long num = 0;

      if(str != NULL)
       {
            const char* digit = str;

            // the first char in the string maybe '+' or '-'
            bool minus = false;
            if(*digit == '+')
                   digit ++;
            else if(*digit == '-')
             {
                   digit ++;
                   minus = true;
             }

            // the remaining chars in the string
            while(*digit != '/0')
             {
                  if(*digit >= '0' && *digit <= '9')
                   {
                         num = num * 10 + (*digit - '0');

                        // overflow  
                        
if(num > std::numeric_limits<int>::max())
                         {
                               num = 0;
                               break;
                         }

                         digit ++;
                   }
                  // if the char is not a digit, invalid input
                  else
                   {
                         num = 0;
                        break;
                   }
             }

            if(*digit == '/0')
             {
                   g_nStatus = kValid;
                  if(minus)
                         num = 0 - num;
             }
       }

       return static_cast<int>(num);
}

讨论:在参考代码中,我选用的是第一种声明方式。不过在面试时,我们可以选用任意一种声明方式进行实现。但当面试官问我们选择的理由时,我们要对两者的优缺点进行评价。第一种声明方式对用户而言非常直观,但使用了全局变量,不够优雅;而第二种思路是用返回值来表明输入是否合法,在很多 API 中都用这种方法,但该方法声明的函数使用起来不够直观。
最后值得一提的是, C 语言提供的库函数中,函数atoi 能够把字符串转换整数。它的声明是 int atoi(const char *str) 。该函数就是用一个全局变量来标志输入是否合法的。

 

----------------------------------------------------------------------------------------------------

C语言提供了几个标准库函数,可以将任意类型(整型、长整型、浮点型等)的数字转换为字符串。以下是用itoa()函数将整数转 换为字符串的一个例子:

# include <stdio.h>
# include <stdlib.h>

void main (void)
{
int num = 100;
char str[25];
itoa(num, str, 10);
printf("The number ’num’ is %d and the string ’str’ is %s. /n" ,
num, str);
}

itoa()函数有3个参数:第一个参数是要转换的数字,第二个参数是要写入转换结果的目标字符串,第三个参数是转移数字时所用 的基数。在上例中,转换基数为10。10:十进制;2:二进制...
itoa并不是一个标准的C函数,它是Windows特有的,如果要写跨平台的程序,请用sprintf。
是Windows平台下扩展的,标准库中有sprintf,功能比这个更强,用法跟printf类似:

char str[255];
sprintf(str, "%x", 100); //将100转为16进制表示的字符串。

下列函数可以将整数转换为字符串:
----------------------------------------------------------
函数名 作 用
----------------------------------------------------------
itoa() 将整型值转换为字符串
itoa() 将长整型值转换为字符串
ultoa() 将无符号长整型值转换为字符串

一   atoi      把字符串转换成整型数
例程序:
#include <ctype.h>
#include <stdio.h>
int atoi (char s[]);

int main(void )
{   
char s[100];
gets(s);
printf("integer=%d/n",atoi(s));
return 0;
}
int atoi (char s[])
{
int i,n,sign;
for(i=0;isspace(s[i]);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’);//将数字字符转换成整形数字
return sign *n;
}
二         itoa       把一整数转换为字符串
例程序:
#include <ctype.h>
#include <stdio.h>
void        itoa (int n,char s[]);
//atoi 函数:将s转换为整形数
int main(void )
{   
int n;
char s[100];
printf("Input n:/n");
scanf("%d",&n);
          printf("the string : /n");
          itoa (n,s);
return 0;
}
void itoa (int n,char s[])
{
int i,j,sign;
if((sign=n)<0)//记录符号
        n=-n;//使n成为正数         i=0;
do{
        s[i++]=n%10+’0’;//取下一个数字
}while ((n/=10)>0);//删除该数字
if(sign<0)
        s[i++]=’-’;
s[i]=’/0’;
for(j=i;j>=0;j--)//生成的数字是逆序的,所以要逆序输出
        printf("%c",s[j]);
}

 

------------------------------------------------------------------------------------

自己写的atoi函数----(注意:自己定义的atoi函数和库的atoi函数一样的时候,抛出异常时会引起异常退出,个人认为是异常没有不知道被那个函数抛出,所以coredump)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <iostream>
#include <string>
#include <exception>
using namespace std;
                                                                               
const unsigned int SIGN_BIT = 0x1 << 31;
 
bool isDigit(const char ch)
{
        if (ch <= '9' && ch >= '0')
        {
                return true;
        }
 
        return false;
}
 
int atoi_i(const char *str)
{
        assert(str != NULL);
 
        while (' ' == *str){ str++; }
 
        int result = 0;
        bool signFlag = false;
        if ('+' == *str)
        {
                if (false == isDigit(*++str)) throw "input format error!";
        }
        else if ('-' == *str)
        {
                if (false == isDigit(*++str)) throw "input format error!";
                signFlag = true;
        }
        else if (*str > '9' || *str < '0')
        {
                throw "input format error!";
        }
 
        do
        {
                result = result * 10 + *str++ - '0';
                if ((result & SIGN_BIT) != 0)
                {
                        throw "overflow error!";
                }
        }
        while (isDigit(*str));
 
        if (true == signFlag)
        {
                result = -result;
        }
 
        return result;
}
 
int main(int argc, char *argv[])
{
        char input[1024];
        while (1)
        {
                try
                {
                        cout << "Input Array:";
                        cin >> input;
                        printf("exchange:%d/n", atoi_i(input));
                }
                catch (const char *p)
                {
                        cout <<"Error Info:" << p << endl;
                }
                catch ( ... )
                {
                        cout << "test" << endl;
                }
        }
        return 0;
}
-----------------------------------------------------------------------------------

itoa函数(自己)

#define SWAP(X,Y) (X) = (X) ^ (Y); (Y) = (X) ^ (Y); (X) = (X) ^ (Y)
char *itoa_i(int src, char *a)
{
    bool signFlag = false;
    if (src < 0)
    {
        src = -src;
        signFlag = true;
    }
                                                                           
    int k = 0;
    do
    {
        a[k++] = src % 10 + '0';
    }
    while((src /= 10) > 0);
                                                                               
  if (true == signFlag)
  {
    a[k++] = '-';
  }
  
  a[k] = '/0';
  for (int i = 0, j = k - 1; i < j; ++i, --j)
  {
    SWAP(*(a+i),*(a+j));
  }
  return a;
}
 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值