题目(摘自谭克强版C语言): 输入一个字符串,内有数字和非数字字符,如a123x456as789x123,将其中连续的数字作为一个整数,依次存放到数组a中,例如存放123在a[0]中,并统计共有多少个这样的整数,并且输出。
算法:我在网上找了这个题的算法,基本上都是按照老谭的那样算的,说实话我没太看懂老谭的代码,感觉很乱,他的思路到是可以借鉴。所以我写了自己的算法,高手路过还请多多指点。老谭是从前往后遍历的去寻找数字,为此他付出了很大的代价去寻找元素位置与连续数字位数之间的关系,导致代码死多,都不想看。为了方便期间,我选择逆序遍历,逆序的好处显而易见。比如上面的字符串,首先肯定是先将数字字符转换成整型(因为要放在整型数组里啊),我从最后一位3开始访问,无论如何它都是个位(不管下一位是不是数字),如果下一位是数字,那就换算成十位(即乘以10),再求sum,继续判断第三位,第三位乘100,再相加,就是123了;而如果从前往后的话不能这么简单的去换算,因为你不知道这个连续数字有几位,因而无法确定个位十位等(当然,这可以利用元素的位置和连续数字的位置之间的关系得出,但我觉得麻烦)。算法基本就这样,不过还得注意一点就是,因为是逆序,我原本的想法是将字符串的最后一个'\0'放在最前面,即其余元素全部向后移动一位,但是考虑到万一数据很大,那不是复杂度太大了么,于是我选择构造新的字符串,即在输入字符串的时候要求第一位输入一个任意字符,然后将最后一个字符'\0'(这个字符是在最后一位3的下一位,是系统自动分配的)赋值给它,这样就貌似''翻转''了字符串。所以我这个程序输入得格式是,任意一个字符+真正输入的字符。代码如下:
#include <stdio.h> #include <string.h> void main() { char num[50]; //要输入的字符串 char*p; //指向字符串 int a[50],*pa; //要存放的目的数组 int len; //用户输入的字符串的长度 int i,j; //用以遍历 int n=0; //记录连续数字的位数 int integer; //记录转换后的整型 int e10; //10 int sum=0; //求和 int l=0; //记录新数组的实际个数 printf("请输入一个字符串:\n"); gets(num); len=strlen(num); num[0]=num[len]; //先将'\0'置换到首位,用以逆向遍历 p=num+len-1; //指向最后一个元素 pa=a; //指向要赋值的数组 while(*p!='\0') { if (*p>='0' && *p<='9') { n++; //位数加1 integer=*p-48; //转换为整型 if (n>0) //至少要为1位数 { e10=1; for (j=1;j<n;j++) { e10 *=10; } integer=integer*e10; } sum=sum+integer; if (*(p-1)=='\0') //这个情况很特殊,是说连续数字出现在第二个位置上(第一个是'\0') { *pa=sum; l++; } p--; } else //这个else很重要 { if (n>0) //避免访问倒数第一个非数字出现错误赋值 { *pa=sum; //当前访问到了非数字,说明之前的是数字,把之前的存入数组 sum=0; //访问到了非数字,赶紧将sum清0,不要影响下次赋值 pa++; //指向下一个数组元素,以方便下次赋值 l++; //新数组元素的个数加1 n=0; //将位数重新赋0,如果下一个还是数字,以方便记录位数,很重要 p--; //访问下一位 } } } pa=a+l-1; //倒序 printf("字符串里的有%d个整数\n",l); printf("它们是:\n"); for(j=0;j<l;j++) {printf("%d,",*pa--);} }
有时候觉得C语言也很蛋疼,没有String类,像这种问题放在其他高级语言里,用个substring就方便多了,不过底层语言也有底层语言的好处,毕竟要有坚实的基础才能爬的更高么。