偶然看到cppblog精华区有一篇关于貌似是一道中兴笔试题的代码,文章请见
这里
个人觉得写得不是很有美感,正好又很无聊,于是在这位的代码基础上改了下算法:
0、原作者可能没有注意到他用的atoi库函数的某些特点;
1、充分利用atoi库函数的特性:原地可解析字符串,不必拷贝出来;
2、由于atoi这个库函数相当于已经实现了整数的前缀匹配,只要匹配从非数字到数字那一状态就可以了;
3、完全没必要给临时分配的数组初始化值,因为有index.
VS2008和DevC++下通过测试。
1#include <iostream>
2#include <algorithm>
3void output(char* str,int len)
4{
5 if(str==NULL||len<= 0)
6 return;
7
8 int * numList=new int[len],index=0,i;
9 char * isDigit=new char[len];//isDigit[i]存储着:str[i]是否为数字
10 for(i=0;(i!=len)
11 &&(isDigit[i]=(str[i]<='9'&&str[i]>='0'),1);i++);//建立isDigit数组目的是避免重复运算
12
13 if(isDigit[0]!=0)//避免取到isDigit[-1]
14 numList[index++]=atoi(str);
15 for(i=1;i!=len;i++)
16 if(isDigit[i-1]==0&&isDigit[i]!=0)//若是从上一个非数字字符跳到现在的数字字符,则从此处转换一次整数到numList列表
17 numList[index++]=atoi(str+i);
18
19 std::sort(numList,numList+index);//排序
20 std::copy(numList,numList+index,
21 std::ostream_iterator<int>(std::cout," "));
22 delete [] numList;
23 delete [] isDigit;
24}
25int main()
26{
27 char input[] = "33k&99+r5sw1f10gd4vc511gc3";
28 output(input,strlen(input));
29 return 0;
30}
为了榨取性能和空间,我进一步改得略微丑陋了些,但某些地方改得更美观- -bnr:
#include <iostream>
#include <algorithm>
void output(char* str,int len)
{
if(str==NULL||len<= 0)
return;
int * numList=new int[len],index=0,i;
bool * isDigit=new bool[len];//isDigit[i]存储着:str[i]是否为数字
for(i=0;i != len;i++)//建立isDigit数组目的是避免重复运算
isDigit[i] = str[i]<='9'&&str[i]>='0';
if(*isDigit++ != 0)//避免取到isDigit[-1]
numList[index++] = atoi(str++);
for(;*str !=0 ;++str,++isDigit)
if(!*(isDigit-1)&& *(isDigit))//若是从上一个非数字字符跳到现在的数字字符,则从此处转换一次整数到numList列表
numList[index++] = atoi(str);
std::sort( numList , numList+index);//排序
for(i=0;i != index;++i)
std::cout<<numList[i]<<" ";
delete [] numList;
delete [] (isDigit-len);
}
int main()
{
char input[] = "33k&99+r5sw1f10gd4vc511gc3";
output(input,strlen(input));
return 0;
}