寒假进阶-C学习小记
因为本人原先基础不牢(这是一个悲伤的故事)所以我决定重新学习C。
for循环
for循环我比较弱的一点就是循环的嵌套,然后重新学了一遍之后就做了一道题,过程很艰难因为浮点数的比较出了问题(做完之后告诉我是蓝桥杯的题,太难了我)那就先看题吧:
啤酒每罐2.3元,饮料每罐1.9元。小明买了若干啤酒和饮料,一共花了82.3元。
我们还知道他买的啤酒比饮料的数量少,请你计算他买了几罐啤酒。
我的解决代码:
#include <stdio.h>
int main(){
int beer,drink;
int m;
for(beer=0;beer<35;beer++){
for(drink=0;drink<43;drink++){
if(beer>drink){
continue;
}
m=beer*23+drink*19;
if(m==823){
printf("%d",beer);
}
}
}
return 0;
}
最开始我是用浮点数写的后来发现不行,我就直接暴力破解直接搞成整数(整数很方便但是遇到其他题就不一定了),自己归纳了这道题的小知识:
1、浮点数的比较:一般不用==,浮点数的比较要引入一个极小数eps来进行修正
一 等于运算符
由于浮点数比较时有误差,所以如果一个数 a 落入[b-eps,b+eps]的区间中间,就应当判定a==b成立,经验表明:eps取1e-8是一个比较合适的数字——对大多数的情况既不会漏判,也不会误判,因此可以将eps定义成常量1e-8;
const double eps=1e-8;
#define Equ(a,b) ((fabs((a)-(b)))<(eps))
二 大于运算符(>)
如果一个数 a 要大于 b ,那么必须在误差 eps 的扰动范围外大于b ,因此只有大于 b+eps 的数才能判定为大于 b (也即a-b>eps)
#define More(a,b) (((a)-(b))>(eps))
三 小于运算符(<)
如果一个数 a 要小于 b ,那么必须在误差 eps 的扰动范围外小于b ,因此只有小于 b-eps 的数才能判定为小于 b (也即a-b<-eps)
#define Less(a,b) (((a)-(b))<(-eps))
四 大于等于运算符(>=)
由于大于等于运算符可以理解为大于运算符和等于运算符的结合,于是让一个数 a 在误差扰动范围内能够判定其大于或者等于b,因此大于 b-eps 的数都应判定为大于等于b(也即a-b>-eps)
#define MoreEqu(a,b) (((a)-(b))>(-eps))
五 小于等于运算符
由于小于等于运算符可以理解为小于运算符和等于运算符的结合,于是让一个数 a 在误差扰动范围内能够判定其小于或者等于b,因此小于 b+eps 的数都应判定为小于等于b(也即a-b<eps)
#define LessEqu(a,b) (((a)-(b))<(eps))
2、嵌套循环条件的控制
嵌套循环要注意嵌套循环中的变量的范围,以这道题来看啤酒和饮料的变量所处的循环位置关系,啤酒比饮料少,如果把饮料的循环放前面就会出现问题循环次数变多了。所以注意范围!!!!
函数
检测自己会不会函数基础的东西还是要做题,所以先来看题吧!
1、使用函数求特殊a串数列和:给定两个均不超过9的正整数a和n,要求编写函数求a+aa+aaa++⋯+aa⋯a(n个a)之和。
函数接口定义:
int fn( int a, int n );
int SumA( int a, int n );
其中函数fn须返回的是n个a组成的数字;SumA返回要求的和。
#include <stdio.h>
int fn( int a, int n );//1
int SumA( int a, int n );//2
int main(){
int a,n;
scanf("%d %d", &a, &n);
printf("fn(%d, %d) = %d\n", a, n,fn(a,n));
printf("s = %d\n", SumA(a,n));
return 0;
}
//函数1 计算数字
int fn(int a,int n){
int c=0;
for(int i=0;i<n;i++){
c=c+a;
a=a*10;
}
return c;
}
//函数2 求和
int SumA(int a,int n){
int sum=0;
for(int i=0;i<=n;i++){
sum=sum+fn(a,i);
}
return sum;
}
知识小点1
血泪教训函数调用记得先在前面定义函数,调用函数时记得带变量名。还有涉及的一小点循环就是循环顺序是依次循环,所以代码语句的顺序很重要(因为我最开始搞反了所以我懂)!!!!!!!
来来来,下一题数组的知识涉及一点,但还是对函数的考查多一点
2、数组循环右移
本题要求实现一个对数组进行循环右移的简单函数:一个数组a中存有n(>0)个整数,将每个整数循环向右移m(≥0)个位置,即将a中的数据由(a0a1⋯an−1)变换为(an−m⋯an−1a0a1⋯an−m−1)(最后m个数循环移至最前面的m个位置)。
函数接口定义:
int ArrayShift( int a[], int n, int m );
其中a[]是用户传入的数组;n是数组的大小;m是右移的位数。函数ArrayShift须将循环右移后的数组仍然存在a[]中。
#include <stdio.h>
#define MAXN 10
int ArrayShift( int a[], int n, int m );
int main(){
int a[MAXN], n, m;
int i;
scanf("%d %d", &n, &m);
for ( i = 0; i < n; i++ ) scanf("%d", &a[i]);
ArrayShift(a, n, m);
for ( i = 0; i < n; i++ ) {
if (i != 0) printf(" ");
printf("%d", a[i]);
}
printf("\n");
return 0;
}
//函数实现以上功能
int ArrayShift(int a[],int n,int m){
for(int i=0;i<m;i++){
int b=a[n-1];
for(int c=n-2;c>=0;c--){
a[c+1]=a[c];
}
a[0]=b;
}
}
知识小点2
1、数组内部元素的下标是从0开始的,最开始定义输入元素时就要考虑循环的范围,数组大小不能用变量定义需要用常量。
2、然后这道题给了一个初始代码有个#define MAXN 10指的就是数组a[]中最多只能输入十个元素,如果数组元素个数保持在一定范围就可以利用提前定义一个最大元素个数。
指针
首先明确指针是指地址,是一个常量,指向地址,其次指针也有类型,类型是其指向的内存空间数据的类型,表示从首地址开始取多少字节。定义指针目的是通过指针访问内存单元。
但是最开始我是把指针和指针变量概念混在一起了(其实现在还有一点晕来着不过好多了),指针变量指的是取值为地址的变量,指针变量要先进行定义说明并且必须要赋予具体的值,指针变量赋值只能赋予地址。
指针类型:1、整型指针:int*
2、float指针:float*
3、char指针:char*
4、类/结构体指针:Student*、User *
C语言中,定义指针变量时,在变量名前 写一个 * 星号,这个变量就变成了对应变量类型的指针变量。必要时要加( ) 来避免优先级的问题。
保存其他变量的地址,使用& 运算符取得一个变量的地址。
贴一个指针入门代码吧
#include <stdio.h>
//数据交换
void swap(int *a,int *b){
int m;
m= *a;
*a= *b;
*b=m;
}
int main(){
int a,b;
scanf("%d %d",&a,&b);
printf("%d %d\n",a,b);
swap(&a,&b);//函数调用实现数据交换
printf("%d %d\n",a,b);
return 0;
}
这里要注意一下调用函数时要用取地址的符号&
先写到这里吧,有点乱。等我学完结构体再继续写我的学习小记。
最后说一句翁恺太催眠了,不知道被他催眠了多少次…