码风:每个结构的{}要缩进,不能都放到同一列,更别什么都顶格写。
循环结构
while(判断语句)
{
代码块;
…
}
若判断语句为真,则进入代码块,运行完代码块后返回判断语句再次进行判断。 为假则跳过这一循环结构。
do
{
代码块;
…
}while(判断语句);
必定先执行一次代码块,然后进入判断语句,为真再循环一次代码块,为假跳过语句。
for(初始化语句;判断语句;改变值语句)
{
代码块;
…
}
先会执行初始化语句,只会在一开始进入for循环执行一次,然后执行判断语句,若为真则运行,否则跳过,为真就进入代码块,代码块走完后运行改变值语句,然后继续判断语句依次循环直到判断语句不满足。
int i=0;
while(i<10)
{
i++;
printf("%d\n",i);
}
打印结果应该是1 2 3 4 5 6 7 8 9 10
这就是一个很基础的打印1~10的值
也可以写成
int i=0;
while(i++<10)
printf("%d ",i);
int i;
for(i=1;i<=10;i++)
printf("%d",i);
这也是一个打印1~10的值
值得一提的是for圆括号里是三个语句用两个分号隔开,所以可以在语句1处写int i=1; 就不需要在外面定义i了
这里也牵出了一个知识点,
如果在main()中定义一个变量,如果没有对它进行初始化(赋初始值)或者没有对他进行输入操作,那么它输出就是一个随机的地址上的值。
讲到这里我们也可以来提一下全局变量和局部变量
全局变量定义在#include<>与main()之间的区域,就是不在任何函数里的定义,全局变量默认初始化为0,并且在所有地方都可以调用。
局部变量就是我们在main()主函数中或者在其它函数中,或者其它结构中定义的变量,它的作用范围是有限的,如我们for(int i=0;i<10;i++) 这句子里i就是个局部变量,它的作用范围只有for这个语句及它的代码块内,当不在这范围内i就处于未定义的状态,不能被调用。
同理main()里定义的变量就不能在别的函数中去使用
那么是不是说定义全局变量就一定比局部变量好呢?
并不是,全局变量的存储类型默认是static(静态)的,意思就是会开一片空间专门放这个全局变量,并且不会自己删除掉,意味着这会消耗我们的空间。
而局部变量,存储类型默认是auto(动态)在一个小范围的地方作用完后直接释放空间。所以我们需要对于不同的情况采取不同的定义。
除此之外循环语句是可以进行嵌套的,
一个for循环就是一重循环,两个就是二重循环以此类推
举个栗子:
for(int i=1;i<=9;i++)
{
for(int j=1;j<=i;j++)
{
printf("%d*%d=%d",i,j,i*j);
}
}
这就是一个99乘法表的代码,它的运行是
先运行最外层,i=1,判断1<9,进循环,走内层循环,j=1,判断1<=1成立,进循环,打印,然后j++,继续判断2<=1不成立,出内层循环,i++,然后判断外层for循环2<=9,进内循环… 就这样 以此类推…
这个自己带个小点的数值推一下就知道怎么实现的了。
这里讲讲易错点:
以这个斐波那契数列的代码打样
#include<stdio.h>
int main()
{
int f1,f2,n,ans;
scanf("%d",&n);
f1=f2=1;
printf("%3d %3d",f1,f2);
for(int i=3;i<=n;i++)
{
ans=f1+f2;
f1=f2;
f2=ans;
printf("%3d ",ans);
if(i%5==0) printf("\n");
}
return 0;
}
1.首先 #include<stdio.h> 这个别拼错,写成< >不要用" " ,双引号是引用的意思,我们用< >规范些。
2.int main()这后面没有;
3.后面一定要跟{ } 并且}后面统统没有; }后面跟分号的情况只有在学到结构体后才会出现。
4.定义的变量如果不用于输入或者不用于赋值的话一定要赋初始值,赋NULL或者0都可以。
5.scanf里变量名前有&,printf不用写&
6.for while if 这种结构如果代码有多行的时候一定要打{ } 包起来
7.for()内部是三个语句 用的是;隔开 for if while圆括号后面都没有;
8.所有关键字都是英文,不要打成中文。
eg.1
国王将金币作为工资,发放给忠诚的骑士。第一天,骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天(第七、八、九、十天),每天收到四枚金币……;这种工资发放模式会一直这样延续下去:当连续 n 天每天收到 n 枚金币后,骑士会在之后的连续 n+1 天里,每天收到 n+1 枚金币。
请计算在前 k 天里,骑士一共获得了多少金币。
输入格式
一个正整数 k,表示发放金币的天数。
输出格式
一个正整数,即骑士收到的金币数。
输入输出样例
输入
6
输出
14
输入
1000
输出
29820
#include<iostream>
using namespace std;
int main()
{
int ans=0,day=0,n;
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)//仅仅控制ans加几次i
{
if(day>=n) break;
ans+=i;
day++;
}
cout<<ans<<endl;
return 0;
}
eg.2
现在有 n(n≤1000) 位评委给选手打分,分值从 0 到 10。需要去掉一个最高分,去掉一个最低分(如果有多个最高或者最低分,也只需要去掉一个),剩下的评分的平均数就是这位选手的得分。现在输入评委人数和他们的打分,请输出选手的最后得分,精确到 2 位小数。
输入输出样例
输入
5
9 5 6 8 9
输出
7.67
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int minn=100,maxx=0;
double avg;
int n,x;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>x;
avg+=x;
if(x>maxx) maxx=x;
if(x<minn) minn=x;
}
printf("%.2lf",(avg-minn-maxx)/(n-2));
return 0;
}
eg.3
已知正整数n是两个不同的质数的乘积,试求出两者中较大的那个质数。
输入格式
一个正整数n。
输出格式
一个正整数p,即较大的那个质数。
输入输出样例
输入
21
输出
7
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
for(int i=2;i<=n;++i)
if(n%i==0) {cout<<n/i;return 0;}
}
数组
一维数组:
开一段连续的空间存放值
定义方法:数据类型 数组名[数组下标];
如:int a[5];
数组定义了5个空间
但是存数值用的是a[0] a[1] a[2] a[3] a[4]这5个空间
所以我们定义一个数组[n] 使用它使它的作用范围使a[0]~a[n-1]
定义时初始化
int a[5]={1,2,37,54,32};
如果有具体的初始化时需要赋的值
也可以写成int a[]={1,2,37,54,32};
编译器会自动帮你开你赋值所需要的空间
注:如果只定义(int a[4];)没有赋初始值并且没有通过输入来赋值
那么数组中存放的是随机数
int a[4]={1,2}; 这样写a[0]是1,a[1]是2,其余是0
数组赋值如果不是通过初始化赋值就一般是通过循环来赋值
输出也是通过循环来 while for都可以
int a[10];
for(int i=0;i<10;i++)
cin>>a[i];
for(int i=0;i<10;i++)
cout<<a[i]<<' ';
定义a[10] 那么它的数组是a[0]~a[9]
所以我们i要从0~9 不能到10,到10就越界访问了
eg.4
输入10名选手成绩,求最高分和最低分
#include<iostream>
using namespace std;
int main()
{
int a[10],minn,maxx;
for(int i=0;i<10;i++)
cin>>a[i];
minn=maxx=a[0];
for(int i=1;i<10;i++)
{
if(a[i]<minn) minn=a[i];
if(a[i]>maxx) maxx=a[i];
}
cout<<"最高分:"<<maxx<<endl<<"最低分:"<<minn;
return 0;
}
eg.5
给出一个正整数 n(n≤100),然后对这个数字一直进行下面的操作:如果这个数字是奇数,那么将其乘 3 再加 1,否则除以 2。经过若干次循环后,最终都会回到 1。
经过验证很大的数字都可以按照这样的方式比变成 1,所以被称为“冰雹猜想”。例如当 n 是 20,变化的过程是 [20, 10, 5, 16, 8, 4, 2, 1]。
根据给定的数字,验证这个猜想,并从最后的 1 开始,倒序输出整个变化序列。
输入输出样例
输入
20
输出
1 2 4 8 16 5 10 20
#include<iostream>
using namespace std;
int n,i=1;
int a[110];
int main()
{
cin>>n;
while(n!=1)
{
a[i++]=n;
if(n%2==0) n/=2;//16
else n=n*3+1;//10 5
}
a[i]=1;
for(int j=i;j>=1;j--)
cout<<a[j]<<' ';
return 0;
}
二维数组:
定义方法:int a[4][3];
同样也可以初始化
int a[4][3]={1,2,3,4,5,6,7,8,9,10,11,12};
最多存4*3个数 多了就越界了
a[i][j] 若i表示行 j表示列
i:0~3
j:0~2
规则和一维数组都差不多
一般使用二重循环对二维数组进行赋值
输出也是二重循环
for(int i=0;i<4;i++)
for(int j=0;j<3;j++)
cin>>a[i][j];
for(int i=0;i<4;i++)
for(int j=0;j<3;j++)
cout<<a[i][j]<<' ';
eg.6
计算N*M阶的矩阵求和
N=3,M=2
#include<iostream>
using namespace std;
#define N 3
#define M 2
int main()
{
int a[N][M]={1,3,5,7,9,11};
int b[N][M]={2,4,6,8,10,12};
int c[N][M];
for(int i=0;i<N;i++)
for(int j=0;j<M;j++)
{
c[i][j]=a[i][j]+b[i][j];
cout<<c[i][j]<<' ';
}
return 0;
}
字符数组和字符串:
单个的称为字符 多个字符称为字符串
如:‘h’ 字符 “hello” 字符串
其实和整型的数组没什么区别
定义方法:
char a[10];
可以存10个字符,数组下标范围 0~9
char a[5]={‘h’,‘e’,‘l’,‘l’,‘o’};一个字符一个空间 单个字符用单引号包起来 ’ ’
char a[]={‘h’,‘e’,‘l’,‘l’,‘o’}; 也可以这么写 在有确切的初始化的内容时
char a[10]={‘e’,‘d’,‘g’,‘n’,‘b’};
加入咱们开了10个空间,但只初始化了五个值进去
那么剩下的五个都是’\0’字符
以字符串的方式初始化
char a[5]={“hello”};
和char a[5]={‘h’,‘e’,‘l’,‘l’,‘o’};一个意思
字符串赋值用" "双引号包起来
需要注意的是:在给字符数组赋字符串常量时,系统会自动在末尾加’\0’
这个是字符串的结束标志
这里提一个知识点
字符串的赋值方法:
char a[14]=“hello world”;
只有在一开始定义的时候初始化才能赋值
如果你先定义,再用=赋值 ,是不行的
比如:
char a[14];
a[14]=“hello world”; 这样是错误的,这意思是在数组下标为14的位置赋值一个字符,但是咱们赋值的是字符串 就会报错
a[]=“hello world”;这种写法也会报错
这时候我们就需要用strcpy函数赋值了,有兴趣可以自己网上搜一搜。
也可以用gets函数输入。
如果用scanf输入的话
scanf("%c",&a[i]);在循环中表示把每一个字符输入进每一个数组
scanf("%s",a);不用写在循环里,直接输入字符串 并且不加&,不写数组下标,而直接写数组名。
printf("%s",a);同理。
那我们这顺便讲讲string(字符串)
使用string需要输头文件
string 就是字符串的数据类型 和int double一个意思
可以用来定义变量
#include<cstring>
#include<iostream>
using namespace std;
int main()
{
string a="hello world";
string b,c;
c="算法协会 yyds";
cin>>b;
cout<<a<<' '<<b<<' '<<c;
return 0;
}
用string这个类型就可以实现先定义 后赋值了
string c;
c=“算法协会 yyds”;
它也可以输出单个字符。string可以以字符串输入输出也可以作为字符数组
cout<<a[0]<<a[1];就是输出a中第一个字符和第二个字符。
所以string也可以以数组的方式来使用。