1 . 使用函数统计指定数字的个数
int i;
int count=0;
if(number<0)number=-number;
do{
i=number%10;
if(i==digit)count++;
number/=10;
}while(number!=0);
return count;
- 要考虑到负数取余出来仍然为负数,所以在取余操作之前应该将负数变为正数再进行操作
- 若输入的数为0,若采用的是while那么将不会进入循环,所以采用do-while,至少循环一次,要将0考虑到
2 . 判断一个不知道次数数是不是水仙花数
- 补充:水仙花数定义:仙花数是指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和等于它本身。例如:153=13+53+33。
- 首先判断次数
j=number;//用来最后比较判断是否是水仙花
t=number;//用来判断次数
while(t!=0){
t/=10;
m++;//存放number的次数
}
- 然后循环次数并累加判断是不是水仙花数
while(number!=0){
item=1;//每算一次就要初始化一次哦
for(i=1;i<=m;i++){
item*=number%10;//裁判没有调用math函数,所以用循环来
};
sum+=item;
number/=10;
}
if(j==sum)return 1;
return 0;
若是水仙花数,那么if成立,就会返回1,若没有执行if语句段就代表不是水仙花数,则返回0.
3.输出n行空心的数字金字塔。
输出样例:
1
2 2
3 3
4 4
555555555
int j,i;
for(i=1;i<=n;i++){
for(j=1;j<=n-i;j++){
printf(" ");
}
for(j=1;j<=2*i-1;j++){
if(j==1||j==2*i-1||i==n)printf("%d",i);
else printf(" ");
}
printf("\n");
}
- 重点在于找到规律
- 首先外循环循环打印每一行
- 内循环首先是打印每一行前面的空格,然后将每一行对应应该有字符的位置打印出来
- 特别注意每一行应该打印字符位置,应该是第一个与最后一个位置,对应符号就是j==1||j==2*i-1
- 注意每行打印完最后要换行哦
4.使用函数求特殊a串数列和
- 明确,aaa的第x位相当于a*10的x-1次方,如第二位就是a*10的2-1次方也就是a0
- aaaa就是用a的每一位进行相加就行了
- 算出n位a的值
int fn(int a,int n){
int sum=0;
int i;
for(i=0;i<n;i++){
sum+=a*pow(10,i);
}
return sum;
}
- 在这里n位a,因为每一位与10的次方的关系都是减一,所以循环中干脆就减一,按照10的次数来书写循环条件,并进行累加。
- 将a进行累加
int SumA(int a,int n){
int i,j;
int sum=0;
for(i=1;i<=n;i++){
sum+=fn(a,i);
}
/*for(j=1;j<=n;j++){
int item=0;
for(i=0;i<j;i++){
item+=a*pow(10,i);
}
sum+=item;
}*/
return sum;
}
- 因为上面我们已经定义了求n位a的方法,所以在累加的时候可以直接调用函数,用一个for循环达到累加,若不理解的话也可看注释掉的代码,它又算了一遍n位a再进行的累加。
5 . 使用函数输出指定范围内的完数
- 明确判断一个数是不是另一个数的因子的办法是进行取余,而不是相除!!!
- 如果取余==0那么就说明它是该数的因子,反之就不是
- 若是要顺序输出因子,很简单的,只要按照顺序方式求出因子即可,本来我们判断一个数的因子就是由小到大依次判断
printf("%d = 1",m);
for(i=2;i<m;i++){
if(m%i==0)printf(" + %d",i);
}
上述代码就是循环输出m的因子和
6 . 使用函数输出一个整数的逆序数
这个题目最开始我甚至是想先计算它的位数再逆序除啊乘啊把它算出来,后来我发现复杂化了
- 可以联系字符转换为数字,因为是连续的一个过程,所以其实我们在通过取余依次取数的时候就是在记录位数咯
int reverse(int number){
int re=0;
int sign=1;
//打错特错:if(number<10)return number;那么当number为负数时也会返回原来的值
if(number<0){
number*=-1;
sign=-1;
}
while(number!=0){
int t;
t=number%10;
number/=10;
re=re*10+t;
}
re*=sign;
return re;
}
还是不可以忘记负数的情况要单独考虑哦
7 . 移动字母
将输入字符串的前3个字符移到最后
- 主要要考虑到覆盖的问题
- 先将前三个赋给另一个数组
- 根据规律将后面的字符往前移动
- 将后面的移动完后再将前三个赋给后面
void Shift(char s[]){
//将要移动的字母存入新数组
char move[3];
int i;
for(i=0;i<3;i++){
move[i]=s[i];
}
//先移动按照规律
for(i=3;s[i]!='\0';i++){
s[i-3]=s[i];
}//此时的i就是数组s的长度哦,并且,要抓住仅仅是移动是不改变数组的总长度的
//再将前面的三个赋到最后面
for(int j=0;j<3;j++){
s[i-j-1]=move[2-j];//一定要注意i是s总长度,是包括字符串结束符的,所以要先减去1
}
}
8 . 拆分实数的整数与小数部分
- 不要复杂,联想所学知识,有一个强制类型转换哇,所要保留的整数部分就是可以强制类型转换出来的int
- 再用原来的数减去int就可以得到小数部分啦
- 该方法也可以用来判断这个数是不是整数哦,如果所得到的小数部分不等于0就说明不是
9 . 8-3 数组循环右移
- 循环右移问题核心问题就是覆盖和特殊移动
- 关于覆盖有两种方法:
- 法一:重现建一个数组用来存放移动的数据,最后将新数组从0开始全部赋给原数组以达到目的
- 法二:通过循环移动的方式:也就是将移动的位数作为外循环,每循环一次移动一位,在循环内部进行边界判定,到达边界与没到达边界是不同效果。事实上在移动过程中,为了防止覆盖,可以建立一个临时变量先将数组中最后一个数存入该临时变量,以此腾位,循环往后移动一位,再将临时变量赋给第一个位置以此达到循环移动的效果。
- 比较法一与法二:事实上,法一的时间效率比法二高,空间效率比法二低,但一般是用空间换时间,所以这里我采用法一的方式
- 提示:后面有个恺撒加密
//主要看临界值,也就是该位置向右移动m个位置后是否大于数组总长度
void ArrayShift( int a[], int n, int m ){
//遍历数组进行循环右移并分情况讨论
m%=n;
int i;
int b[n];
for(i=0;i<n;i++){
if(i+m>n-1)b[m-n+i]=a[i];
else b[i+m]=a[i];
}
for(i=0;i<n;i++){
a[i]=b[i];
}
}
无论怎样,最开始都应该进行取余操作,没必要循环!!!
10 . 报数
报数游戏是这样的:有n个人围成一圈,按顺序从1到n编好号。从第一个人开始报数,报到m(<n)的人退出圈子;下一个人从1开始报数,报到m的人退出圈子。如此下去,直到留下最后一个人。
本题要求编写函数,给出每个人的退出顺序编号。存到out数组中
注意:这是普通报道几就退出的进阶,该题目的要求是记录每个数退出的顺序,也就是一直报数,直到最后一个人退出。
- 明确题目要求后,为了避免已经退出的人的干扰,首先我们可以定一个退出标志,若该人退出,那么就将该元素存入-1,只有存入的不是-1时才报数,若存入的是-1直接跳过,进入下一个数报数。
- 因为题目要求所有数都退出,也就是从1到最后n。
- 以出列dequeue为外循环,直到dequeue=n也就是第n个出列的数也出列才结束循环
- 内循环一直循环报数,当报数到m的时候break打破循环(报数清0哦,并存入退出标志),将dequeue存入out对应元素标志它是第几个退出的,内循环打破也就意味外循环+1进入下一个数出列。
- 特别注意:这是一个当dequeue没有到n时一直进行的判断,也就是说数会遍历好几轮,所以在内循环的最前面需要判断index是否到n到n代表前面全都报数了,这个时候我们就需要从头开始报数,当然这里也有一个判断就是该数是否存入退出标志,若存了直接跳过
- continue用的很巧妙哦
//外循环是报到哪个数,就是报n个数,也就是n个人都退出//内循环通过判断,continue来跳循环
void CountOff(int n,int m,int out[]){
int a[1000]={0};
int index=0;
int count=0;
/*for(int i=1;i<=n;i++){
a[i-1]=i;
}//将每个进行赋值,应该没这个必要吧,反正只用判断是否出队也就是不等于出对标志就行*/
for(int dequeue=1;dequeue<=n;dequeue++){
while(1){
index=index==n?0:index;//用来判断是不是报数报到了第n个,是的话就说明要进行下一轮
if(a[index]==-1){
index++;
continue;//如果该数已经出列,那么直接到下一个index
}
count++;
if(count==m){
a[index]=-1;
index++;
count=0;
out[index-1]=dequeue;//注意因为数组下标与退出顺序是减一的关系,因为数组从下标0开始存嘛,然后退出是从1开始的
break;//当报数退出后那么退出while循环
}
index++;
}
}
}
11 . 使用函数实现字符串部分复制
- 特别注意一点:从第m个字符开始复制是从下标 m-1 开始复制,因为数组有个0,而第m个是从1开始的。
12 . 删除字符
- 既然是删除,那么删除后的字符串长度肯定短于删除前的字符串长度
- 通过遍历覆盖的方式就可以达到删除的效果并且还是在原字符组中
- 这里特别强调一下,需要在最后加上字符串结束符,因为不加的话最后输出的也就是没有被覆盖翻新的仍然会打印出来
void delchar(char *str,char c){
int i=0,k=0;
while(str[i]!='\0'){
if(str[i]!=c){str[k]=str[i];k++;}
i++;
}
str[k]='\0';
}
13 . 判断满足条件的三位数
本题要求实现一个函数,统计给定区间内的三位数中有两位数字相同的完全平方数(如144、676)的个数
区间(101,m)m为未知数
- 首先,明确题目要求,先判断是不是完全平方数,不好判断,那么我们就遍历该区间内的完全平方数,从大于101的完全平方数开始,也就是11的平方
for(i=11;i<=sqrt(m);i++);
因为m不确定所以就开方判断
- 其次在for循环遍历中通过pow求出平方来还原它原本的数
int x=pow(i,2);
- 最后通过取余进行判断,不一定要英文翻译个十百,也可以通过拼音的形式,ge= ,shi=。只要大家能看懂就行,可读性就上来了咯。