一:分解整数
题型1:整数求逆
整数求逆有以下几个注意点:
1.用x%10来得到这个数的个位数
2.用x/=10来丢掉这个数的个位数
3.用digit来临时存储当初的个位数
4.用ret=ret*10+digit来存储之前的数字
#include<stdio.h>
int main()
{
int ret, digit, x;
ret = 0;
x = 123456;//此处可以更改为scanf形式的变动型变量
while (x > 0)
{
digit = x % 10;//此处得到x的个位数
ret = ret * 10 + digit;//此处将所有得到的数存储起来
x /= 10;//此处将x的个位数去除
}
printf("%d", ret);
return 0;
}
题型二:分解整数
二:关于求解素数问题的几个方法
素数:除1以外,除了能被1和自己本身整除的数称之为素数。
题型1:判断一个数是否是素数
#include<stdio.h>
int main()
{
int i,x,isPrime;
scanf("%d",&x);
for(i=2;i<x;i++)
{
if(x%i==0)
{
isPrime=0;
break;
}
}
if(isPrime==0)
{
printf("%d不是素数",x);
}
else
{
printf("%d是素数",x);
}
return 0;
}
下列有另外一种方法:
#include<stdio.h>
int main()
{
int x,i;
for(i=0;i<x;i++)
{
if(x%i==0)
{
break;
}
}
if(i<x)
{
printf("%d不是素数",x);
}
else
{
printf("%d是素数",x);
}
}
总结:如果要判定一个数是否是素数,要特别注意计量数的增减情况,当增到怎么样的一个情况该跳出循环?这是我们设计判定型程序时所需要考虑的,同时我们也应该要学到,引入一个逻辑量(一般是以isPrime作为标识,而且一般对其赋值为0或者1)以此来代表这个命题是否是成立的。
题型二:给定一个数,输出它以前的所有的素数。
如何写出x以内的所有的素数?
#include<stdio.h>
int main()
{
int x, i, isPrime;
for (x = 1;x <= 100;x++)
{
int isPrime = 1;
for (i = 2; i < x; i++)
{
if (x % i == 0)
{
isPrime = 0;
}
}
if (isPrime==1)
{
printf("%d\t", x);
}
}
return 0;
}
三:求解前n项和
本题利用较多的是循环结构
题型1:正项正序求和
//写一个正项求和的程序
#include<stdio.h>
int main()
{
int i, n;
double sum = 0.0;//要注意的是最后计算得到的sum是带有小数点的,要用浮点数进行转换
n = 50;
for (i = 1; i <= n; i++)
{
sum += 1.0 * 1 / i;//核心加法
}
printf("f(%d)=%f", n, sum);
return 0;
}
题型二:摆动正负项正序求和
#include<stdio.h>
int main()
{
int i, n;
double sum = 0.0;
double cont = 1.0;//引入改变符号的变量
n = 50;
for (i = 1; i <= n; i++)
{
sum +=cont* 1 / i;
cont = -cont;//此处注意顺序,是要在循环结束之前对改变符号的变量进行反赋值
}
printf("f(%d)=%f", n, sum);
return 0;
四:求最大公约数
法一:枚举法(中心思想是设置一个循环变量来记录可被a与b整除的数)两个或多个整数中共有约数中较大的那一个
//写一个求最大公约数的程序,本程序为了充分理解枚举这种方法的中心思想,暂且不使用逻辑运算符进行编写
#include<stdio.h>
int main()
{
int a, b, i, ret, min;//避免warning,将所有变量进行初始化赋值
min = 0;
a = 12;
b = 24;
ret = 0;
if (a < b)//设定递减边界
{
min=a;
}
else
{
min=b;
}
for (i = 1; i <= min; i++)//主程序,注意,如果此处在最后一步加入break;则可以输处最小公约数,当然当i=1时,这样做并没有什么意义
{
if (a % i == 0)
{
if (b % i == 0)
{
ret = i;
}
}
}
printf("%d和%d的最大公约数为%d", a, b, ret);
return 0;
}
法二:辗转相除法
原理如下:首先对这两个数进行比较大小,将较大的值提前,做一步较大的数对较小的数的取余,得到余数
得到余数之后,再将原来较小的数放到前面的位置,把余数放到后面的位置,一直循环,直到那个较小的数变为了0.
/*用更辗转相除法计算两个数的最大公倍数。
原理如下:首先对这两个数进行比较大小,将较大的值提前,做一步较大的数对较小的数的取余,得到余数
得到余数之后,再将原来较小的数放到前面的位置,把余数放到后面的位置,一直循环,直到那个较小的数变为了0.
a b t
18 12 6
12 6 0
6 0 输出a
*/
#include<stdio.h>
int main()
{
int a, b, t;
a = 24;
b = 12;
t = 0;
while (b != 0)
{
t = a % b;
a = b;
b = t;
printf("a=%d,b=%d,t=%d\n", a, b, t);
}
printf("因此最大公约数为%d",a);
return 0;
}
五:给定数的位数求其所有不重复排列的所有组合
本题是对循环的考查。
#include<stdio.h>
int main()
{
int a = 4;
int i, j, k;//对本题用到的变量大于三个的,一般可以用ijk或者是xzy作为代表元素
int cnt = 0;//在这里为了应付空格等特殊要求,要定义一个次数变量
i = a;
while (i <= a + 3)//排列组合的技巧,三位顺序
{
j = a;
i++;
while (j <= a + 3)
{
k = a;
j++;
while (k <= a + 3)
{
k++;
if (i != j && j != k && i != k)//避免相同的数出现
{
cnt++;
printf("%d%d%d", i, j, k);
if (cnt % 6 == 0)
{
printf("\n");
}
else
{
printf(" ");
}
}
}
}
}
return 0;
}
根据本题的解题情况来看,思路是这样的,首先确定第一位数,然后限定第二位数,再限定第三位数,执行完之后,在对第一位数加一(这一步应该是在确定了第一位数进行的),然后以此列举出这些数字。
六:打印九九乘法表
本题难度比较小,直接给出答案
#include<stdio.h>
int main()
{
int i, j, cnt;
for (i = 1; i <= 9; i++)
{
for (j = 9; j >= 1; j--)
{
printf("%d*%d=%d", i, j, i * j);
if (i * j < 10)
{
printf(" ");
}
else
{
printf(" ");
}
}
printf("\n");
}
return 0;
}
七:数组
例题1:写一个程序,输入不确定[0,9]范围内的整数,统计每一种数字出现的次数,输入-1表示结束。
#include<stdio.h>
int main()
{
int x, i;
int count[10];//定义数组的长度
for(i=0;i<10;i++)
{
count[i] = 0;
}//对数组进行初始化,使得数组中每一个元素都是0
scanf_s("%d", &x);// 读入需求整数
while (x!=-1)//注意结束的条件是输入一个-1作为判定
{
if (x >= 0 && x <= 9)
{
count[x]++;//由于每个数都已经被初始化,只有出现过的i对应的count[i]的值才会发生改变.
}
scanf_s("%d", &x);
}
for (i = 0; i < 10; i++)
{
printf("%d:%d\n", i, count[i]);
}
}
算法:搜索
在一组给定的数据中,要如何找出某个数是否存在?
1.如何确定有几个元素?
sizeof(a[0])中给出的是单个元素的大小,而sizeof(a)给出的是整个数组所占字节
于是sizeof(a)/sizeof(a[0])=n,n即该改数组中所含的元素的个数,这样编写的代码是安全的,越界的行为不会发生。
2.创建一个含x个数递增的数组
#include<stdio.h>
int main()
{
int a[100];
int i;
for (i = 0;i <100; i++)
{
a[i] = i + 1;
//printf("%d\t", a[i]);
}
return 0;
}
/*找出key在数组中的位置
*@param key 要找的数字
*@param a 要找的数组
*@param length 数组a的长度
*return 如果找到 则返回key的位置;找不到则返回-1.
*/
#include<stdio.h>
int search(int key, int a[], int length)//编写search调用函数
{
int isPrime = -1;//给出一个判断变量
int i;
for (i = 0; i < length; i++)
{
if (a[i] ==key)//在这步中遍历数组,找到key的位置
{
isPrime= i;//找到key后,将其存储到判断变量中
break;
}
}
return isPrime;//将判断变量返回给loc
}
int main(void)
{
int i;
int a[100];//创建一个100以内的递增的数组
for (i = 0; i < 100; i++)
{
a[i] = i ;
}
int n;
int x;
int loc;
printf("please input a number(max=100)");
scanf_s("%d", &x);
n = sizeof(a)/sizeof(a[0]);//计算出数组的长度
loc=search(x, a, n);
if (loc!=-1)
{
printf("%d在数组中的第%d个",x,loc);
}
else
{
printf("not found");
}
return 0;
}
算法:构造素数表
思路如下:
欲计算x以内的素数表
1.令x=2(开辟一个数组prime[n],初始化其所有的元素为0,prime[x]=1表示的是这个数是素数)
2.将2x、3x、4x、直至ax<n的数标记为非素数
3.令x为下一个没有被标记为非素数的数,重复2,直到所有x以内的数都已经尝试完毕。(如果x是素数,则对于(i=2;ix<n;i++),令prime[ix]=0)
4.令x++,如果x<n,重复3,否则结束
//代码待补充
冒泡排序
冒泡排序的基本思想是:相邻的元素两两比较,将较大的数字排在后面,直到将所有的数字都排序完毕。
现有一组数据,打乱了顺序,采取方法将其按顺序排好。
#include <stdio.h>
int main()
{
double arr[] = { 1.78, 1.77, 1.82, 1.79, 1.85, 1.75, 1.86, 1.77, 1.81, 1.80 };
//共有十个数据
int i, j;
for (i=0;i<10;i++)
{
if (i != 9)
{
printf("%.2f,", arr[i]);//%.2f表示的是精确到小数点后两位,避免带太多0
}
else
{
printf("%.2f", arr[i]);
}
}
printf("\n");
for (i = 8; i >= 0; i--)
{
for (j = 0; j <= i; j++)
{
if (arr[j] < arr[j + 1])//依次遍历,直到没有满足条件的为止。
{
double temp;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
}
}
}
for (i = 0; i < 10; i++)
{
if (i != 9)
{
printf("%.2f ", arr[i]);
}
else
{
printf("%.2f ", arr[i]);
}
}
return 0;
}
多维数组的遍历
多维数组的遍历和一维数组的遍历一样,同样也是需要用到循环 这里给出代码
#include<stdio.h>
int main()
{
int arr[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
int i, j;
int sum = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j <3; j++)
{
if (i % 2 == 0 && j % 2 == 0)
{
sum += arr[i][j];
}
}
}
sum += arr[1][1];
printf("对角线元素之和为%d\n", sum);
return 0;
}
有关字符串的问题
1.获取字符串的长度
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//写一个函数返回字符串的长度
int GetStrLength(char[]);
//封装fgets,用来接收字符串的字符数组,接收的字符总数
void GetString(char[], int count);
void GetString(char str[], int count)
{
//使用fgets函数接收字符串,并把最后一位的\n替换为\0
fgets(str, count, stdin);
//查找\n
//这里使用一个语法糖
char* find = strchr(str, '\n');
//得到了换行符的指针
if (find)
{
*find = '\0';
}
}
int GetStrLength(char str[])
{
int count = 0;
//count用于累计字符串的长度
int i;
while (str[count] != '\0')
{
if (str[count] == '\n')
{
str[count] = '\0';
break;
}
count++;
}
return count;
}
int main()
{
char names1[50];
GetString(names1, 50);
printf("pass!\n");
int len = GetStrLength(names1);
//如果此处用fgets时会把\n算进去,所以这里编写一个函数将\n去掉
printf("字符串的长度为%d\n", len);
/*
//体会两种定义字符串的方式
int i;
char names1[] = { 'j','a,','c','k','\0' };
char names2[50] = { "jack" };
printf("请输入新名称:\n");
fgets(names2, 10, stdin);
//从标准输入流中输入10个字节到数组names2中
printf("数组中的字符串的元素为:\n");
//调试检验输入的元素
//注意:fgets最终得到的最后一个元素是\n 下面讲述如何用指针的方法将\n变成退出符
for (i = 0; i < 50;i++)
{
printf("%c\n", names2[i]);
}*/
return 0;
}
2.字符串的内置函数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void GetString(char str[], int count)
{
//使用fgets函数接收字符串,并把最后一位的\n替换为\0
fgets(str, count, stdin);
//查找\n
//这里使用一个语法糖
char* find = strchr(str, '\n');
//得到了换行符的指针
if (find)
{
*find = '\0';
}
}
int main()
{
char word1[] = { 'j','a','c','k','\0' };
char word2[] = { "hacker" };
char word3[] = { "你好,华农!" };
char word4[50];
printf("word1数组的长度为:%d\n", strlen(word1));
//strlen()函数的作用是量出字符串的长度
printf("请输入字符串:\n");
GetString(word3, 50);
//使用编写好的函数
strcpy_s(word4, word3);
//strcopy()把word3的值赋给了word4
printf("word3:%s\nword4:%s\n", word3, word4);
return 0;
}
算法:过滤掉字符串中的多余空格
思想:
1.输入字符串
2.检查字符串中的前一位和后一位是不是空格,如果是空格,则删除。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char str1[100];
char str2[100];
int i,j;
j=0;
gets(str1);
for(i=0;i<strlen(str1);i++)
{
if(!((str1[i]==' ')&&str1[i+1]==' '))//说明有多余的空格
{
str2[j]=str1[i];
j++;
}
}
str2[j]='\0';
//小问题是如果第一个也是空格,那么就会去除不了,那么这里对其进行推位即可
if(str2[0]==' ')
{
for(i=0;i<strlen(str2);i++)
{
str2[i]=str2[i+1];
}
}
printf("%s",str2);
return 0;
}
打印菱形的方法
本题设计算法:
1.把菱形看成两部分,上半部分的规律和下半部分的规律一样,需要分类讨论。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"math.h"
//由键盘输入正数n(n<30),要求输出如下2*n+1行的菱形图案
//菱形右边不留多余空格
//假设菱形以中间最长条为分界,上部分则有N个
//那么就会有规律:以3为例子,当i=0时,第一行是3-0个空格,2*0+1个星号
//二:3-1 2*1+1
//算法如:1.分出两部分
//2.使用双重for循环,i控制行数,j控制列数。
int main()
{
//打印上半部分
int i,j;
int n;
scanf("%d",&n);
for(i=0;i<n;i++)
{
for(j=0;j<n-1-i;j++)
{
printf(" ");
}
for(j=0;j<2*i+1;j++)
{
printf("*");
}
printf("\n");
}
for(i=0;i<n-1;i++)
{
for(j=0;j<=i;j++)
{
printf(" ");
}
for(j=0;j<2*(n-1-i)-1;j++)
{
printf("*");
}
printf("\n");
}
}
打印符合条件的图形
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"math.h"
//由键盘输入正数n(n<30),要求输出如下2*n+1行的菱形图案
//菱形右边不留多余空格
//假设菱形以中间最长条为分界,上部分则有N个
//那么就会有规律:以3为例子,当i=0时,第一行是3-0个空格,2*0+1个星号
//二:3-1 2*1+1
//算法如:1.分出两部分
//2.使用双重for循环,i控制行数,j控制列数。
int main()
{
//打印上半部分
int i,j;
int k;
int h;
int n;
scanf("%d",&n);
for(i=0;i<n;i++)
{
for(j=0;j<n-1-i;j++)
{
printf(" ");
}
for(k=1;k<=i+1;k++)
{
printf("%d",k);
}
for(h=k-2;h>=1;h--)
{
printf("%d",h);
}
printf("\n");
}
/*
n=4
1 3个空格 i=0 j=3 3=4-1-i 顺:1 逆:0
121 2个空格 i=1 j=2 2=4-1-i 2 1
12321 1个空格 i=2 j=1 1=4-1-i 3 2
1234321 0个空格 i=3 j=0 0=4-i-i 4 3
12321
121
1
*/
for(i=0;i<n-1;i++)
{
for(j=0;j<=i;j++)
{
printf(" ");
}
for(k=1;k<=n-j;k++)
{
printf("%d",k);
}
for(h=k-2;h>=1;h--)
{
printf("%d",h);
}
printf("\n");
}
}
把矩阵转换为对应的关系
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"math.h"
int main()
{
int a[3][4];
int b[4][3];
int i,j;
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
scanf("%d",&a[i][j]);
b[j][i]=a[i][j];
}
}
for(i=0;i<4;i++)
{
for(j=0;j<3;j++)
{
if(j==2)
{
printf("%d\n",b[i][j]);
}
else
{
printf("%d ",b[i][j]);
}
}
}
return 0;
}
高精度算法
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//题目要求:由键盘输入两个位数很长的整数(一行一个,最多不超过80位)
//试计算并输出这两个数的和。
//设计:1.将长数以字符串的方式读入
//2.将字符串进行倒序
//3.倒序的数字开始相加,如果到十,则进一位,如果没到十,则直接相加保存
//4.再次倒序打印出结果
//tip:如果最后一位为0,用while清零法清掉
//给出的输入样例:1234567890123456789353534532453453453434534
// 987654321098765324534534534534532
//输出为:1234567891111111110452299856987987987969066
//注意字符串到整形的转换是这样的
//从字符串类型变到整形是字符串-48或者直接-'\0'
int main()
{
char a[1010]={0};
char b[1010]={0};
int a1[1010]={0};
int b1[1010]={0};
int c1[1010]={0};
scanf("%s%s",a,b);
//读入两个数字
int la;
int lb;
int i;
int len;
la=strlen(a);
lb=strlen(b);
for(i=0;i<la;i++)
{
a1[la-i-1]=a[i]-'0';//将字符串类型的ascii转为为整形
}
for(i=0;i<lb;i++)
{
b1[lb-i-1]=b[i]-'0';
}
if(la>lb)
{
len=la;
}
else
{
len=lb;
}
for(i=0;i<len;i++)
{
c1[i]+=a1[i]+b1[i];//模拟竖式的运算过程
if(c1[i]>=10)
{
c1[i+1]++;
c1[i]-=10;
}
}
while(c1[len]==0&&len>=1)
{
len--;
//第m位为0,那么就跳过了,这是倒过来输出的
}
for(i=len;i>=0;i--)
{
printf("%d",c1[i]);
}
return 0;
}
寻找字符串
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 100
//编写一个程序用来找到一个字符串在另外一个字符串中的位置
//思路:首先判断一个元素与另外一个中的元素是否相同?
//如果相同,那么str1与str2的下标就同时增加
//指向下一个元素(继续检索),如果这时候检索到不相同,那么跳出循环,并使得循环变量又初始化为0
//如果相同,那么进行检索,直到某一个元素为空,
//1.如果str1先为空,那么证明str2不是str1的子字符
//2.如果str2先为空,那么证明str2是str1的子字符,而且可以完全匹配
//在2的基础上,可以知道i为str1查找字符串的下标,j为str2的长度,,那么i-j即为字符串出现的位置
int main()
{
int i,j;
int flag=-1;
char str1[N]="";
char str2[N]="";
gets(str1);
gets(str2);
for(i=0,j=0;str1[i]!=NULL;i++)
{
while(str1[i]==str2[j])
{
i++;j++;
if(str2[j]==NULL)
{
flag=i-j;
}
}
j=0;
}
printf("%d",flag+1);
}
简易时钟原理
#include<stdio.h>
/*编写程序,输入三个整数变量hour(小时)、minute(分钟)、second(秒)
**代表一个时间,
**输出该时间20秒以后的时间。
*/
int main()
{
int sec,min,hour;
char c;
scanf("%d%c%d%c%d",&hour,&c,&min,&c,&sec);
//printf("%d %d %d",x,y,z);
if(sec+20<60)
{
printf("%02d:%02d:%02d",hour,min,sec+20);
//这个写法是左对齐补零
}
if(sec+20>=60)
{
sec=sec+20-60;
min++;
if(min>=0&&min<59)
{
printf("%02d:%02d:%02d",hour,min,sec);
}
if(min>=60)
{
min-=60;
hour++;
if(hour>=0&&hour<24)
{
printf("%02d:%02d:%02d",hour,min,sec);
}
if(hour==24)
{
hour-=24;
printf("00:00:%02d",hour,min,sec);
}
}
}
return 0;
}
输出对应的字符
#include <stdio.h>
//编写一个函数,挑选一个字符串中的所有元音字母构成并返回一个新的字符串
//写出一个方法读出字符串长度,并把最后一位换为\0
int main()
{
char s[81];
char s2[81];
fgets(s,81,stdin);
int i=0,j=0;int k=0;
for(i=0;i<81;i++)
{
if(s[i]=='A'||s[i]=='a'||s[i]=='i'||s[i]=='I'||s[i]=='o'||s[i]=='O'||s[i]=='E'||s[i]=='e')
{
s2[j]=s[i];
j++;
}
}
for(i=0;i<81;i++)
{
if(((s2[i]>='A'&&s2[i]<='Z')||(s2[i]>='a'&&s2[i]<='z'))!=1)
{
for(k=i;k<81;k++)
{
s2[k]='\0';
}
}
}
printf("%s",s2);
return 0;
}
学生成绩管理系统
/*输入10个学生5门课的考试成绩,分别用函数实现以下功能:
(1) 计算一个学生的平均分。
(2) 计算每门课程的平均分。
(3) 找出每门课程的最高分。
显示结果,显示两位小数。
//二维数组代表的是a[3][4]代表的是三行四列
*/
#include <stdio.h>
void average(double a[][5], int n)
{
double sum=0;
int i=0,j=0;
for(i=0;i<n;i++)
{
sum=0;
for(j=0;j<5;j++)
{
sum+=a[i][j];
}
printf("%.2f ",sum/5.0);
}
printf("\n");
}
void average2(double a[][5], int n) //计算的是每一门课的平均分
{
double sum=0;
int i=0,j=0;
for(i=0;i<5;i++)
{
sum=0;
for(j=0;j<n;j++)
{
sum+=a[j][i];
}
printf("%.2f ",sum/n);
}
printf("\n");
}
void top(double a[][5], int n)
{
int i=0,j=0;
double max=0;//二维数组中的冒泡排序较为复杂,用桶排序更好
for(j=0;j<5;j++)
{
max=a[0][j];
for(i=1;i<n;i++)
{
if(max<a[i][j])
{
max=a[i][j];
}
}
printf("%.2f ",max);
}
printf("\n");
}
int main()
{
double a[10][5];
int i, j;
for(i=0; i<10; i++)
for(j=0; j<5; j++)
scanf("%lf", &a[i][j]);
average(a,10);
average2(a,10);
top(a,10);
return 0;
}
好数
#include <stdio.h>
#include <stdlib.h>
//最大的数为19
//给定一个n,从n开始到1,逐个判断这个数是否是好数,找到第一个好数,就输出结束
//如何判断好数,从最大的3的n次方开始整除,如果商大于等于2,那么则不是好数
//否则:余数不为0,取余数进行除下一个3的n-1次方直到1
int count(int n)
{
int i;
int ret=1;
for(i=0;i<n;i++)
{
ret*=3;
}
return ret;
}
int main()
{
int i,x,answer=0,temp=0;
scanf("%d",&x);
for(i=x;i<10000;i++)
{
int n=7;
if(i/count(n)<2)
{
temp=i%count(n);
while(n>=0&&temp!=0)
{
temp=temp%count(n);
n--;
if(temp==count(n)&&temp/count(n)<2)
{
answer=i;
goto loop;
}
}
}
}
loop:printf("%d",answer);
return 0;
}