一、头文件的功能用法
1.#include <math.h>
sqrt()-------对括号里面的数据开平方
pow()-------对括号里面的数据平方,比如pow(3,7)就是算3的7次方
2.#include <string.h>
strlen(数组名)------计算字符串或者数组的长度
sizeof()------用来计算你所使用的操作数所占的空间字节大小
strcmp()------strcmp比较两个字符串的大小,一个字符一个字符比较,按ASCLL码比较
strcat()------strcat追加拷贝,追加到目标空间后面,目标空间必须足够大,能容纳下源字符串的内容
strcpy()------strcpy是覆盖拷贝,将source全覆盖拷贝到destination,会把’\0’也拷过去,且必须考虑destination的空间够不够(destination的空间必须>=source的空间)
二、基本的框架和输入和输出格式
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
printf("%d",n);
return 0;
}
例题:求三个数的最大值
#include <stdio.h>//主要是引入中间变量max
int main(void)
{
int a,b,c,max;
scanf("%d,%d,%d",&a,&b,&c);
if(a>b)
max=a;
else
max=b;
if(c>max)
max=c;
printf("max=%d",max);
return 0;
}
输出字符的ASCLL码
#include <stdio.h>//直接用%c输入字符,%d输出字符即可
int main()
{
char a;
scanf("%c",&a);
printf("%d",a);
return 0;
}
直接用%c输入字符,%d输出字符即可
反过来%d输入一个数字,然后用%c输出也可以输出相应的字符
同理甚至可以数字之间的相互转化,输入十进制,输出八进制(%o),十六进制(%x)的数字
二、弱智小点
1.运算符🔍
- +加、-减、*乘、/除、%取余、i++先用再加、++i先加再用
三、结构复习
- 选择排序和结构排序的应用
分支结构:
if()//如果要作用于多句话,就要加花括号,因为这个笨比只能管紧接着的一句话
else if()
else if()
else()
四、排序复习
1.各种排序方式
- 冒泡排序
左边大于右边交换位置一趟排下来最大的在左边
//冒泡排序
void BubbleSort(int* arr, int n)
{
int end = n;
while (end)
{
int flag = 0;
for (int i = 1; i < end; ++i)
{
if (arr[i - 1] > arr[i])
{
int tem = arr[i];
arr[i] = arr[i - 1];
arr[i - 1] = tem;
flag = 1;
}
}
if (flag == 0)
{
break;
}
--end;
}
}
- 选择排序
每次从待排序列中选出一个最小值,然后放在序列的起始位置,直到全部待排数据排完
//选择排序
void swap(int* a, int* b)
{
int tem = *a;
*a = *b;
*b = tem;
}
void SelectSort(int* arr, int n)
{
//保存参与单趟排序的第一个数和最后一个数的下标
int begin = 0, end = n - 1;
while (begin < end)
{
//保存最大值的下标
int maxi = begin;
//保存最小值的下标
int mini = begin;
//找出最大值和最小值的下标
for (int i = begin; i <= end; ++i)
{
if (arr[i] < arr[mini])
{
mini = i;
}
if (arr[i] > arr[maxi])
{
maxi = i;
}
}
//最小值放在序列开头
swap(&arr[mini], &arr[begin]);
//防止最大的数在begin位置被换走
if (begin == maxi)
{
maxi = mini;
}
//最大值放在序列结尾
swap(&arr[maxi], &arr[end]);
++begin;
--end;
}
}
- 更多排序
2.经典例题
见超链接排序🔍,还有动图帮助理解
五、循环复习
1.各种循环结构
- for循环(最简单滴)
for(初始化表达式 ; 循环控制语句 ; 增值表达式)
{
语句序列
}1.首先就是执行 int i = 0 (这句话只会在刚开始循环时执行一遍,后面就不会执行了)
2.然后执行循环控制语句(i<n)
如果循环控制语句为真(此时 i<n),执行循环体(就是那句输出语句)
如果循环控制语句为假(此时 i>=n),结束本次循环
3.执行增值表达式(i++)
4.继续从2.开始往下执行(直到循环控制语句为假,退出循环)
其实初始化表达式 ; 循环控制语句 ; 增值表达式这仨大爷也不是非要全部写完的,具体看你自己咯
通俗一点就是
for(从几开始数 ;数到几结束 ;数增加或减少)
{
我们重复干的事
}
代码示例如下
int n=3; // 规定循环多少次
for(int i=0;i<n;i++)
{
printf("我爱你\n");//我爱你,重要的事情说三遍,嘿嘿
}
- while循环
while(循环控制表达式)//即你想要的控制循环的条件
{
语句序列
}
代码示例如下
int 寿命=100;
while(寿命>0)
{
printf("爱你\n");
寿命--;
}//意思就是只要我不die,就会一直爱你
- do-while循环
do
{
语句序列
}while(循环控制表达式);
与while循环的区别在于:while循环在执行语句之前会先判断一下是否符合循环条件,如果不符合就不会执行,但是do-while比较逆天,就算不符合条件,他也会厚着脸皮执行一遍且只有一遍。看代码示例去理解嘛,反正你条件在后面,我第一遍没招惹你,为什么不让我运行。
代码示例如下
int 寿命=0;
do
{
printf("爱你\n",n);
寿命--;
}while(n>0);//都不需要我活着,die了也在爱你
- 退出循环
有循环当然有退出循环嘛
break直接退出所有循环
continue退出当前的一次循环
代码示例如下
for(int i=1;i<=10;i++)
{
if(i==6)
break;
printf("爱你\n",i);//原本是打算爱你十年,但是你出轨了,再也不要爱你了
}
for(int i=1;i<=10;i++)
{
if(i==6)
continue;
printf("%d\n",i);//原本是打算爱你十年,但是第六年你出轨了,所以第六年不爱你,以后几年又接着爱你,神级舔,呜呜呜
}
2.经典例题
- 小球自由落体运动
一球从M米高度自由下落,每次落地后返回原高度的一半,再落下。 它在第N次落地时反弹多高?共经过多少米? 结果保留两位小数
#include<stdio.h>
int main(void)
{
/*********Begin*********/
int i;
float a,b,sum;
scanf("%f %f",&a,&b);
sum = a;
for(i=1;i<=b;i++)
{
a /= 2;
if(i==b)
{
break;
}
sum += 2 * a;
}
printf("%.2f %.2f",a,sum);
/*********End**********/
return 0;
}
- 求最大公约数和最小公倍数
输入两个正整数m和n,求其最大公约数和最小公倍数
#include<stdio.h>
int main()
{
int m, n, num1, num2, temp;
scanf("%d %d", &num1, &num2);
m=num1;
n=num2;
while(num2!=0)
{
temp=num1%num2;
num1=num2;
num2=temp;
}
printf("最大公约数是:%d\n", num1);
printf("最小公倍数是:%d\n", m*n/num1);
return 0;
}
- 字符串中各类字符数的统计
输入一行字符,分别统计出其中英文字母、数字、空格和其他字符的个数。
#include<stdio.h>
int main(void)
{
/*********Begin*********/
char c;
int letters=0,space=0,digit=0,other=0;
while((c=getchar())!='\n'){
if(c >= 'a' && c<='z' || c >= 'A' && c <= 'Z')
letters++;
else if(c>='0'&&c<='9')
digit++;
else if(c==' ')
space++;
else
other++;
}
printf("%d %d %d %d",letters,digit,space,other);
/*********End**********/
return 0;
}
- 求sn=a+aa+aaa+aaaa+…的值
键盘输入正整数a和n,编程 s=a+aa+aaa+aaaa+aa…a(n个a)的值。
#include<stdio.h>
int main(void)
{
/*********Begin*********/
int a = 0;
int n = 0;
int sum = 0;
int k = 0;
scanf("%d %d", &a, &n);
for (int i = 1; i <= n; i++)
{
k = 10 * k + a;
sum = sum + k;
}
printf("%d", sum);
/*********End**********/
return 0;
}
- 一次性输入多个值相加也可以用循环来做
for(i=1;i<=a;i++)
{
scanf(" %lf",&b);
c=c+b;
}
- 求阶乘之和(嵌套循环)
#include<stdio.h>
int main(void)
{
/*********Begin*********/
int a,b,c,sum=0;
scanf("%d",&a);
if(a<0)
{
printf("0\n");
}
else if(a==0)
{
printf("1\n");
}
else
{
for(int i=1;i<=a;i++)
{
c=1;
for(int b=1;b<=i;b++)
{
c *= b;
}
sum += c;
}
printf("%d",sum);
}
/*********End**********/
return 0;
}
- 寻找完数
一个数如果恰好等于它的因子之和,这个数就称为"完数"。 例如,6的因子为1、2、3,而6=1+2+3,因此6是"完数"。 编程序找出1000之内的所有完数。
#include<stdio.h>
int main()
{
int i,j;
int sum=0;
for(i=1;i<1000;i++)
{
for(j=1;j<i;j++)
{
if(i%j==0)
{
sum+=j;
}
}
if(i==sum)
{
printf("%d\n",i);
}
sum=0;
}
return 0;
}
- 分数求和(注意一下符号就行了,奇数偶数)
编写程序计算 1 - 1/2 + 1/3 - 1/4 + … +1/99 - 1/100 的值,并显示出来(保留结果为小数点后三位)
#include <stdio.h>
int main(){
double sum = 1.0;
for(int i=2;i<=100;i++){
if(i%2==0){
sum = sum - 1.0/i;
}else{
sum = sum + 1.0/i;
}
}
printf("%.3f",sum);
return 0;
}
六、函数复习
1.函数的创建
ret_type fun_name(para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数
其实函数就是有个函数定义的格式然后里面的内容就按平时那样写就行了函数不能嵌套定义
2.形参和实参
形参即函数名括号里面的部分,是设计函数的时候给设置的参数,相当于留了个空位,等待实参代入。
实参就是实际使用该函数的时候所带入的变量,当然,不只是变量,表达式、常量、函数等也都可以。
函数的递归和迭代
(1)什么是迭代
迭代实际上就是重复,如果只讨论我们比较熟悉的程序设计操作,迭代在程序中就表示循环。
(2)函数递归和迭代的优缺点
函数递归中我们一层一层调用函数,它的优点是所需代码量少,简洁。但缺点主要有两个,一方面,大量重复的计算拖慢了程序的运行速度;另一方面,函数每一次被调用的时候都需要在栈区开辟相应的空间,当递归过深时可能会出现栈溢出。(栈区的空间已经被用完了,程序无法继续进行了)
当我们使用迭代时,循环不需要大量调用函数,重复的计算会少很多,这个程序的运行速度会加快不少,只是这个程序的代码量会大很多。
代码示例
递归程序:
#include<stdio.h>
int fib(int m)
{
int ret = 0;
if (m<=2)
{
ret = 1;//第一二项为1
}
else
{
ret = fib(m - 1) + fib(m - 2);//三项及三项以后,后一项等于前两项的和
}
return ret;
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d",fib(n));
return 0;
}
迭代程序:
#include<stdio.h>
int fib(int m)
{
if (m < 2)//前两项为1
{
return 1;
}
else//后两项为前两项之和
{
int i = 0;
int a = 1;
int b = 1;
int c = 0;
for (i=m; i>2; i--)
{
c = a + b;
a = b;//把原来的第二个数变成新计算中的第一个数
b = c;//把算出的结果变为新计算的第二个数
}
return c;
}
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d",fib(n));
return 0;
}
4.函数的调用
- 传值调用
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。所以,我们在不改变函数实参的时候可以使用传值调用。比如,我们写一个程序计算两个整数的和:
#include<stdio.h>
int add(int x,int y)//直接是设置的两个值的形参
{
return x+y;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int c= add(a,b);//直接把实参的值带入形参当中进行运算
printf("%d\n",c);
return 0;
}
- 传址调用
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
#include<stdio.h>
void swap(int* pa, int* pb)
{
int temp = 0;
temp = *pa;
*pa = *pb;
*pb = temp;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("交换前:a=%d,b=%d\n", a, b);
swap(&a, &b);
printf("交换前:a=%d,b=%d\n", a, b);
return 0;
}
- 写一个函数,每次调用就会把次数加一
#include<stdio.h>
void test(int* p)//在主程序内定义一个变量储存调用的次数,因为需要改变变量的值,所以进行传址调用
{
printf("hehe\n");
(*p)++;//解引用找到变量再加1,注意这个括号不能忘
//否则,*p++就表示每次这个指针先向后移动4个字节,然后解引用
}
- 接受一个整型值,按顺序打印每一位数字
#include <stdio.h>
void print(int n)
{
if(n>9)
{
print(n/10);//未明
}
printf("%d ", n%10);
}
int main()
{
int num = 1234;
print(num);
return 0; //我们如果想要得到一个数字的每一位,就需要我们先%10得到最后一位,后/10除去最后一位,因为/10最后一位为余数,可以继续向前查找,直到这个数字成为一个一位数停止程序(因为如果这里是个一位数,a/10的值就是0,我们并不想打印0的每一位),所以在这里我们定义一个函数print(),它可以按顺序打印每一个值
- 应用递归计算斐波那契数列的第n项
斐波那契数列:1 1 2 3 5 8 13 …(规律:第一二项为1,后一项等于前两项的和)
#include<stdio.h>
int fib(int m)
{
int ret = 0;
if (m<=2)
{
ret = 1;//第一二项为1
}
else
{
ret = fib(m - 1) + fib(m - 2);//三项及三项以后,后一项等于前两项的和,递归的使用
}
return ret;
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d",fib(n));
return 0;
}
- List item
七、数组复习
1.一维数组
-一维数组的创建
type_t arr_name [const_n];//类型 数组名字 [常量],记得是常量不是变量奥,也可以不指定数组的大小。
算了直接看代码示例叭
//代码1
int arr1[10];
char arr2[10];
float arr3[1];
double arr4[20];
//代码2
//用宏定义的方式
#define X 3
int arr5[X];
- 一维数组的初始化
int arr1[5] = {1,2,3,4,5};//指定数组大小
int arr3[] = {1,2,3,4};//不指定数组大小
int arr2[6] = {1,2,3};//数组的实际输入个数是可以小于等于这个常量的
char arr5[] = {'a','b','c'};//字符数组不指定字符数组大小
char arr7[6] = "zxc";//字符数组大小大于字符串中的字符数
- 数组内容的写入
1.get(数组名)
2.循环输入
代码示例
1.get(函数名)
char ch[100];
get(ch);//这样就可以在键盘上面向数组里面输入你要的东西啦
2.循环输入
for(int i=1;i<=n;i++){
scanf("%d",&m[i]);
}
- 数组的输出
for(int i=a-1;i>=0;i--)
{
printf("%c",ch[i]); //利用循环把数组里面的元素进行输出
}
2.二维数组
- 二维数组的创建
二维数组创建时,行数可以忽略不写。并且所有维度的数组其第一个方括号的内容可忽略。
int arr[3][4];//[行数][列数]
char arr[][5];
double arr[2][4];
- 二维数组的初始化
花括号中的一个花括号代表一个一维数组的初始化。当里面无花括号分组时,按照顺序从第一个开始逐个进行初始化。余下的未赋值的元素用0初始化。
//数组初始化
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};
- 二维数组的使用(输入)
- 待完善
二维数组的使用也是通过下标的方式,用双重循环嵌套进行索引使用
#include <stdio.h>
int main()
{
int arr[3][4] = { 0 };
int i = 0;
for (i = 0; i < 3; i++)//第一个循环,就是第几行的数据
{
int j = 0;
for (j = 0; j < 4; j++)
{
arr[i][j] = i * 4 + j;
}
}
for (i = 0; i < 3; i++)//第二个循环,第几行的第几个数据
{
int j = 0;
for (j = 0; j < 4; j++)
{
printf("%d ", arr[i][j]);//二维数组的输出也是通过循环的方式哦
}
}
return 0;
}
二维数组本质上也是一维数组,只不过内部元素放的是一维数组而已啦,比如这个。
for(i=0;i<n;i++)
{
scanf("%s",&s[i]);
}
3.经典例题
- 字符统计
对于给定的一个或者多个字符串,统计其中数字字符出现的次数
#include<stdio.h>
int main(void)
{
int n,i,j,count;
char s[10][50];
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%s",&s[i]);
}
for(i=0;i<n;i++)
{
count=0;
for(j=0;s[i][j]!='\0';j++)
if(s[i][j]>='0'&&s[i][j]<='9')
count++;
printf("%d\n",count);
}
return 0;
}
- 字符插入
输入两个字符串a和b,将b串中的最大字符插入到a串中最小字符后面。
思路:就是先分别找出a串中的最小字符和b串中的最大字符,要想把b串中的最大字符插入到串的最小字符之后,就是用for循控制先打印a串到最小字符那里,然后打印b串,最后打印a串的剩余部分就OK了
#include <stdio.h>
#include <string.h>
int main(void)
{
/*********Begin*********/
char a[100],b[100];
int min = 0,max=0,m,n;
gets(a);
gets(b);
m=strlen(a);
n=strlen(b);
for(int i=0;i<m;i++){
if(a[i]<a[min]){
min=i;
}
}
for(int i=0;i<n;i++){
if(b[i]>b[max]){
max=i;
}
}
for(int i=0;i<=min;i++){
printf("%c",a[i]);
}
printf("%c",b[max]);
for(int i=min+1;i<n;i++){
printf("%c",a[i]);
}
/*********End**********/
return 0;
}
- 字符串排序
(strcmp和strcpy字符串函数的使用)
输入3行,每行n个字符串,按由小到大的顺序输出
样例输入:
cde
afg
abc
样例输出:
abc
afg
cde
#include<stdio.h>
#include<string.h>
int main(void)
{
/*********Begin*********/
char a[1000],b[1000],c[1000],d[1000];
gets(a);
gets(b);
gets(c);
if(strcmp(a,b)>0){
strcpy(d,a);
strcpy(a,b);
strcpy(b,d);
}
if(strcmp(b,c)>0){
strcpy(d,b);
strcpy(b,c);
strcpy(c,d);
}
if(strcmp(a,b)>0){
strcpy(d,a);
strcpy(a,b);
strcpy(b,d);
}
puts(a);
puts(b);
puts(c);
/*********End**********/
return 0;
}
- 二分查找
将n个从小到大排序的整数(n<1000000)从1~n进行编号,并一个待查找的整数m,请使用二分法进行查找。
输入
输入包括3行,第一行为整数n,第二行包括n个整数,以空格分隔,第三行为整数m。
输出
如果能够在序列中找到整数m,则输出编号(如果存在多个编号,返回编号最小的),如果不存在,则输出None
#include<stdio.h>
int main(void)
{
/*********Begin*********/
int n,m,s,b,mid,i;
scanf("%d",&n);
int a[n];
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
scanf("%d",&m);
s=0;
b=n-1;
while(s<=b)
{
mid=(b+s)/2;
if(m>a[mid])
{
s=mid+1;
}
else if(m<a[mid])
{
b=mid-1;
}
else if(m==a[mid])
{
printf("%d",mid+1);return 0;
}
}
printf("None");
/*********End**********/
return 0;
}
- 求鞍点
找出具有m行n列二维数组Array的“鞍点”,即该位置上的元素在该行上最大,在该列上最小,其中1<=m,n<=10
一个二维数组并不一定存在鞍点,此时请输出None
#include<stdio.h>
int main(void)
{
/*********Begin*********/
int m,n,i,j,k,a=0,b,max;
scanf("%d %d",&m,&n);
int len[m][n];
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&len[i][j]);
}
}
for(i=0;i<m;i++)
{
max=len[i][0];
a=0;
for(j=0;j<n;j++)
{
if(len[i][j]>=max)
{
max=len[i][j];
b=j;
}
}
for(k=0;k<m;k++)
{
if(max>len[k][b]&&k!=i)
{
// printf("%d %d len=%d\n",k,j,len[k][j]);
a=1;
}
}
if(a==0)
{
printf("Array[%d][%d]=%d\n",i,b,max);
}
}
/*********End**********/
return 0;
}
- 删除最大值
输入10个互不相同的整数并保存在数组中,找到该最大元素并删除它,输出删除后的数组
#include <stdio.h>
int main ()
{
int a[10];
int i,max,j;
max=0;
for (i=0;i<10;i++)
{
scanf ("%d",&a[i]);
}
for (i=0;i<10;i++)
{
if (max<a[i])
{
max=a[i];
j=i;
}
}
for (i=j;j<9;j++)
{
a[j]=a[j+1];
}
for (i=0;i<9;i++)
printf ("%d ",a[i]);
return 0;
}
- 杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
打印出杨辉三角图形的10行。格式见题目描述部分。每个整数后面接一个空格来分隔开整数
#include <stdio.h>
int main()
{
int n=10;
int a[100][100];
for(int i=0;i<n;i++)
{
a[i][0]=1;
a[i][i]=1;
} //将第一个和最后一个初始化为零
for(int i=2;i<n;i++)
{
for(int j=1;j<i;j++)
{
a[i][j]=a[i-1][j-1]+a[i-1][j];
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<=i;j++)
{
printf("%d",a[i][j]);
if(j<i){
printf(" ");
}
}
printf("\n");
}
return 0;
}
八、指针复习
九、文件复习
十、经典例题
1.闰年判断:从键盘输入任意年份year,判别该年份是否闰年
#include<stdio.h>
int main(void)
{
int year;
scanf("%d",&year);
if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
printf("%d 是闰年!",year);
else
printf("%d 不是闰年!",year);
return 0;
}
2.不使用第三个变量,实现两个数的对调
#include<stdio.h>
int main(void)
{
int a,b;
scanf("%d%d",&a,&b);
printf("a=%d b=%d\n",a,b);
a = a + b;
b = a - b;
a = a - b;
printf("a=%d b=%d\n",a,b);
return 0;
}
3.宏定义🔍
4.二分查找🔍