C语言基础
2.1数据类型

基本类型

float和doubt的区别
doubt比float表达的更加精确,大小范围也不一样(这个以后再说)


1.整型常量 int
2.浮点型常量 float
浮点数(实数)有两种表现形式:1.十进制小数形式。由整数部分、小数点、小数部分组成。
2.指数形式。eg:123e3代表123*103;e可以用E替换。tips:e之前必须有数字,后面必须为整数。
(规范化的指数形式):e之前的小数部分中,小数点左边只有一位非零的数字。
浮点数在用指数形式输出的时候,是按规范化的指数形式输出的。
3.字符型常量char
范围
①普通字符
用单引号括起来的一个字符;
② 转义字符
以 / 开头的字符。

注意:‘和/
注:字符集和ASCII码是互通的。
4符号常量
用#define 指令指定一个符号名称代表一个常量;习惯上都是大写字母。
一行只能定义一个符号常量
#define X 11.28
#include <stdio.h>
#define P printf
#define R "please input numbers:\n"
int main()
{
P(R);
return 0;
}
5.字符串常量
用双引号括起来。
可以用语句输出,如printf("China");
2.2变量的定义
- 变量名:每个变量都应该有一个名字
- 变量值:变量在内存中占用一定的存储单位,在该存储变量中存放变量的值。
c语言所有的变量在使用前必须先定义,即说明变量的类型,也就是先定义后使用。
类型说明符 变量名
变量在定义的时候需要注意几个问题
1.命名只能由字母,数字,下划线,三种字符组成。
第一个字必须是字母或者下划线,不可以是数字。
c语言严格区分大小写,即大写字母和小写字母是两个不同的字符。
不可以用关键字命名。

2.变量的数据类型决定了它的存储类型。

说明:
- int型数据取值范围是4字节,有的编译系统中是2
- 浮点型数据在内存中是按照指数形式存储的,小数部分和指数部分分别存放,在4 或 8 字节中。一般而言,小数部分位数多,数据表示的有效数字多,精度就高;而指数部分位数多,则表示的数据范围更大。
- char型数据在内存中存储的形式为该字符对应的ASCII值,即一个整数。
float 用来存放小数,小数在c语言中称为浮点数。在输出的时候用%f 来输出,类似于%d来输出整数。
2.3变量的赋值
int a=2;
相当于
int a;
a=2;
变量的初始化:变量在定义的同时可以赋初值。
%c表示输出类型为字符类型,系统将存储的二进制数表按照ASCII码表转化为相应的字符,然后输出。
%d表示输出类型是十进制整数,系统直接将二进制数转换为十进制整数输出。
%f实型变量,表示输出实数,以小数形式输出,默认情况下保留小数点6位。
%u输出格式符,表示无符号的十进制形式的整数。
%ld表示输出long型数据。
%f代表单精度浮点型数据(float)
%lf代表双精度浮点型数据(double)。(具体区别以后再说
%.15f或者%.15f是指 保留小数点后15位数字
%2d是将数字按宽度为2,采用右对齐方式输出,若数据位数不到2位,则左边补空格
%02d,和%2d差不多,只不过左边补0
%.2d和%02d一样
2.4 循环
while循环
while的基本使用方法
先判断表达式是否成立,如果成立,就执行体内的语句,如果不成立,一次也不循环。
在循环结构的设计中,特别需要注意的是避免死循环
循环无数次
#include <stdio.h>
int main()
{
while (1>0)
{
printf("Hello");
}
return 0;
}
while 和if 一样,如果 后面也只有一个语句,那么{}可以省略
补充知识
暂停语句 sleep()
一对圆括号内的数值单位是毫秒。
#include <stdio.h>
#include <Windows.h>
int main()
{
printf("3");
Sleep(5000);
printf("3");
Sleep(5000);
printf("3");
Sleep(5000);
return 0;
}
上面注意两个地方:
- 头文件<Windows.h>
- Sleep S大写
- Windows W大小写都可以
清屏语句 syatem("cls")
加在printf的前面的内容,在打印新的内容之前把屏幕上的清除干净。
#include <stdio.h>
#include <windows.h>
int main()
{
system("cls");
printf("3");
Sleep(1000);
system("cls");
printf("2");
Sleep(1000);
system("cls");
printf("1");
Sleep(1000);
return 0;
}
内外循环
之后会非常多的用到这个,简单的说一下思路,就是矩阵的想法,控制行标和列标
for循环
基本形式:
for(表达式1;循环条件;表达式2)
{
循环体语句;
}
执行顺序:
1.先求解表达式1
2.判断表达式(条件)是否成立
3.如果成立,执行循环体内语句
4.求解表达式2
5.重复 2-4 过程,直到表达式不成立,结束循环
6.继续执行后续语句
a=a+1可以简写成a++
用for循环更加简便一些
比如,这是while 循环
#include <stdio.h>
int main()
{
int a;
a=1;
while(a<=10)
{
printf("%d",a);
a=a+1;
}
return 0;
}
把他改写成for循环
#include <stdio.h>
int main()
{
int a;
for(a=1;a<=10;a=a+1)
{
printf("%d",a);
}
return 0;
}
do while循环
基本形式为:
do
{
循环体语句;
} while{表达式};
执行顺序如下:
- 执行循环体内的语句
- 判断表达式(条件)是否成立
- 如果成立,重复 1.2 的过程 这个和while 语句 反着
- 直到表达式不成立,结束循环
- 继续执行后续语句
break语句和continue语句
上面三种循环都是当循环条件不满足的时候结束循环。
如果循环条件多于一个或者中途退出循环时,这时候可以考虑标题这两种循环。
break语句
break语句通常用在switch语句和循环语句中,当break语句用于switch语句时,可以使程序跳出switch语句而执行switch后面的语句;判断条件恒真的循环语句中,如果没有break语句,则将成为一个死循环而无法退出。
break语句除了可以用在switch语句中,还可以用在while、do while、for 语句中去。在循环体中遇见break,立即结束循环,跳出循环体,执行循环体后面的语句。
通常break语句总是与if语句连在一起,即满足条件时便跳出循环。
break语句的基本形式为:
break;
continue语句
continue语句只能用在循环语句中。在循环体中遇见continue语句,立即跳过本次循环的循环体中剩余的语句而强制执行下一次循环。通常continue语句总是与if条件语句一起使用,以加速循环。即在循环体遇见continue语句,则循环体中continue语句后面的语句不执行,直接进入下一次循环的判定。
continue语句的基本形式为:
continue;
continue语句只能用于循环结构的内部,一般同if配合使用。
continue语句是不可以在单独的switch语句中使用,但可以在一个循环内的switch语句中使用。
while(表达式)
{
操作1;
if(表达式2)
{
操作2;
continue;
}
操作3;
}
2.5类型转换
2.5.1自动类型转换

2.5.2强制类型转换
一般形式为:
(类型说明符)表达式
需要说明的是,在强制类型转换时,得到一个所需类型的中间变量,原来变量的类型并没有发生变化,比如:int x=5,y=2 (float)x/y ,(float)x的值为5.000000,x的类型仍然是整型。
2.6运算符和表达式
1.基本的算数运算符

2.自增运算符和自减运算符

3.算术表达式
2.6.2关系运算符 和 关系表达式
1.关系运算符

一个等于号表示的是赋值,两个等于号表示的是判断是否相等。
2.关系运算符的优先级和结合性

3.关系表达式
其实,在c语言中,当对于某一个数进行讨论真假的时候,任何非零值为真,0值为假,因此,关系运算的结果仅可能产生两个值:1表示真,0表示假。
2.6.3逻辑运算符和逻辑表达式
1.逻辑运算符(&& || !)
前面两个就不说了,关键是最后一个。
非运算可以理解成是取反
2.逻辑运算符优先级和结合性

实际上,逻辑运算符两侧的运算对象不但可以是0或非0的整数,也可以是任何类型的数据,如字符型、实型或是指针型等。系统最终以0或非0来判断它们属于“真”还是“假”。例如, 'a'&&b'的值为1,是因为和b的ASCI值都不为0,两个非0的数据进行与运算,结果为1。
2.6.4 赋值运算符和赋值表达式
1.基本赋值运算符“=”
(右结合性,就是把右边的数赋值给左边)
赋值运算符优先级比算术运算符、关系运算符、逻辑运算符都要低,结合性是右结合性(从右往左算)。
2.复合赋值运算符

3.赋值表达式
变量+表达式
2.6.5逗号运算符和逗号表达式(左结合性,优先级别最低)
2.6.6条件运算符和条件表达式
条件运算符是c语言中唯一的三目运算符需要三个运算数或者表达式构成条件表达式。
一般形式为:表达式1?表达式2:表达式3
先看表达式1有没有成立,如果成立的话,值就是表达式2 ;不成立的话,值就是表达式2
本节总结

2.7选择结构 switch语句(非常适用于多支路的使用)
基本形式:
switch(整形表达式/字符型表达式)
{
case 常量表达式1:语句1;break;
case 常量表达式1:语句1;break;
....
case 常量表达式1:语句1;break;
default: 语句 n+1;
}

break语句专门用于跳出switch语句
数组
所谓数组,是指将那些具有相同类型的、数量有限的若干个变量通过有序的方法组织起来的一种便于使用的形式。数组属于一种构造类型,其中的变量被称为数组的元素。数组元素的类型可以是基本数据类型,也可以是特殊类型和构造类型。
[ ]表示长度
下标从0 开始
int , float,double,char
要赋值,初始化
简略写法如图

后面没有赋值的话,就等于0。
一维数组的下标
数组的下标实际上是关于数组第一个元素的偏移量。

#include<stdio.h>
int main()
{
int a[8]={ 80,90,85,84,70,75,76,83};
int i,max=0,min=100;
for(i=0;i<8;i++)
{
if (a[i]>max)
{
max=a[i];
}
else if(a[i]<min)
{
min=a[i];
}
}
printf("最高分为:%d\n最低分为:%d\n",max,min);
return 0;
}
注意一开始max,min的取值;
一维数组
5.1 一堆数组的定义和引用
5.1.1 一堆数组的定义
数组名后的[] 是数组的标志,不能用其他符号代替。
一维数组的定义形式为:
类型说明符 数组名[元素个数]
元素个数也称为数组的长度,必须是一个固定的值。
5.1.2 一堆数组元素的引用
数组元素引用的一般形式为:
数组名[下标]
下标可以是整型常量、整型变量、整型表达式,范围是从0 开始,小于等于“元素个数-1”。
数组的下标实际上是关于数组第一个元素的偏移量
结论:一维数组最后一个元素的下标为(长度-1)
二维数组
存储数组的数组。
a[m][n]: m行n列

grade 每一个都是三个,两行,三列(我懂就好,你们看的就自己体会)
省略的话只能省略行数,不能省略列数
#include <stdio.h>
int main()
{
int grade[4][3]={82,77,76,90,87,56,87,48,75,86,86,66};
int i,j;
int n;
for(i=0;i<=4;i++){
for(j=0;j<=3;j++)
{
if (grade[i][j]<60){
printf("第%d位的学生成绩不合格",i+1);//i,j要从1开始,不然前面有个第0位
continue;
}
}
}
return 0;
}
数组名是这个数组的首地址
首地址:一段内存中第一个存储单元的地址
字符数组
如果char a[10];则定义了一个数组a,里面存储10个char类型的元素,则a也可称为字符数组。
输出的时候也是不再是%d了变成了c%,
字符串
字符串的存储
1,
在输入字符串的时候,如果是%s,就不用&了
因为字符数组本身表示的就是地址,无须在数组名加地址符&
2,
使用%s的printf 函数,将从字符数组的起始位置开始输出,直至遇到第一个'\0'停止,并不输出\0;因此有了这个符号之后,字符数组的长度就不重要了。
char c[6]={"hello"};//双引号表示里面的内容时字符串,大括号可以省略
字符数组的长度可以大于字符串的长度
字符串比单个字符形式初始化书写更简单,
字符串的输入和输出函数
输入函数:gets()
输出函数:puts()
输出函数:puts()
puts{字符数组名};或者puts{字符串常量};
函数puts()一次只能输出一个字符串
puts(s1);put(s2);
可以使用转义符
scanf里面不可以
输入函数:gets()
一次只能输出一个字符串
gets(s1);get(s2);
gets()可以读入包含空格和tab的全部字符
含有空格和tab的全部字符要用这个函数输入
字符串的操作函数
它的头文件是string.h
程序中凡是用到本节的函数要在程序的开头添加#include<string.h>
1.strlen(字符串)
测试字符串长度的函数,他的返回值是字符串字符的个数,不包括'\0'在内。
这个输出的是字符串长度。
char str[10]={"hello"};
printf("%d",strlen(str));
2.strcat (字符数组1,字符串2)
strcat()函数的作用是将字符串2中的内容复制连接在字符数组1的后面,其返回值为字符数组1的地址。
#include<stadio.h>
#include<string.h>
int main()
{
char s1[15]="hello",s2[]="world";
strcat(s1,s2);
printf("s1:%s\ns2:\n",s1,s2);
return 0;
}\\运行结果就是
s1:helloword
s2:world
s1 不能是字符串常量,而且容量必须要大,以至于可以容纳s2里面的内容。
字符串常量:
定义:用双引号(“”)括起来的0个或者多个字符组成的序列
存储:每个字符串尾自动加一个 ‘\0’ 作为字符串结束标志
strcpy(字符数组1,字符串2)
哦,我大概好想知道了,就是这个函数是直接把s2复制到s1里面,s1里面的内容没有了,但是呢不能说s1=s2
strcmp(字符串1,字符串2)
功能:比较字符串s1和s2
当s1<s2时,返回为负数 注意不是-1
当s1==s2时,返回值= 0
当s1>s2时,返回正数 注意不是1
即:两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇'\0'为止。如:"A"<"B" "a">"A" "computer">"compare"特别注意:strcmp(const char *s1,const char * s2)这里面只能比较字符串,不能比较数字等其他形式的参数。
strlwr(字符串)
strlwr()用于将字符串中的字符转换为小写,其原型为:char *strlwr(char *str);
也就是说,strlwr() 不会创建一个新字符串返回,而是改变原有字符串。所以strlwr()只能操作字符数组,而不能操作指针字符串,因为指针指向的字符串是作为常量保存在静态存储区的,常量不能被修改。
注意:strlwr()和 strupr() 不是标准库函数,只能在windows下(VC、MinGW等)使用,Linux GCC中需要自己定义。
strupr(字符串)
strupr,函数的一种,将字符串s转换为大写形式。
原型:
extern char *strupr(char *s);
功能:
将字符串s转换为大写形式
注意:
不能使用常量指针作为参数
C语言#include<math.h>
1.绝对值
第一种,输入的是 整数 int 类型
abs(n)
#include<stdio.h>
#include<math.h>
int a=100,b;
b=abs(a);
第二种,输入的是 浮点数 float 类型
fabs(n)
#include<stdio.h>
int main()
{
float n;
scanf("%f",&n);
printf("%.2f",fabs(n));
return 0;
}
2.开根号
sqrt
#include<stdio.h>
#include<math.h>
int main()
{
float x1,y1,x2,y2,d;
scanf("%f%f%f%f",&x1,&y1,&x2,&y2);
if(0<=x1,x2,y1,y2<=100)
printf("%.2f",sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
return 0;
}
3.pow 平方
#include<stdio.h>
#include<math.h>
int main()
{
double a,b,c;//定义实型变量a,b,c;a也可以定义为整型变量。这和类型强制转换有关系。
scanf("%lf %lf",&a,&b);//键盘输入存款年数a,和本金b
c=pow(1.0225,a);//计算按照利率存一定年数后,钱数和本金间的关系
printf("%.6lf",c*b);//输出在银行存款收益
return 0;//正常退出
}
4.log10(数字)
明确log10(数字),会得出数字的位数少一
,以及强制类型转换的使用例如:9,log10(9)之后为零点几,强转时会将小数点后直接舍去,不同于格式化输出double,没有四舍五入。
5.指数形式
预编译处理
无参数的宏定义
#define M (x*x+2*x)
用#undef结束命令
有参数的宏定义
#define M(x) (x*x+2*x)
宏名和形参表之间不能有空格 也不必作类型定义
文件包含命令
条件编译命令
函数
函数的基本概念
函数的作用域
变量的名称可以一样,但是作用的范围,作用的域是不一样的
两个函数是两个不同的内从块
两个变量名称相同 但是不在同一个内存上
swap 交换
#include<stdio.h>
void swap(int i,int j)
{
int temp;
temp=i;
i=j;
j=temp;
printf("i=%d,j=%d",i,j);
}
main()
{
int i=2,j=4;
swap(i,j);
printf("i=%d,j=%d\n",i,j);
}
指针
指针就是变量,用来存放地址的变量(存放在指针中的值都当成地址处理)
指针的基本介绍
p:address //这个是指 地址
*p : value at address// 而这个是 指向的 那个变量的值
给指针赋初值,允许赋0,即int *p=0;系统认为0表示的是内存地址
或者int *p=NULL;NULL表示空指针
指针虽然可以赋0,但不能将一个整数赋给指针变量,如int *p=3000是错误的。
#include <stdio.h>
int main()
{
int a;
int *p;
p=&a;
printf("%d\n",p);
printf("%d\n",*p);
return 0;
}
指针代码示例
#include <stdio.h>
int main()
{
int a;
int *p;
p=&a;
printf("%d\n",p);
printf("%d\n",*p);
printf("%d\n",p+1);
printf("%d",*p+1);
return 0;
}

字节大小 int :4 char :1 float : 4
这确实还挺重要的//
#include <stdio.h>
int main()
{
int a;
a=10;
int *p;
p=&a;
printf("%d\n",p);
printf("%d\n",*p);
printf("%d\n",p+1);
printf("%d\n",*p+1);
printf("size of int is %d\n",sizeof(int));
return 0;
}

指针的类型
指针是强类型的,需要一个特定类型的指针变量来寻访特定类型变量的地址。
int* //指向整型类型的指针,用来存放整形数据的地址,只想字符类型的指针来存放字符型数据的地址,等等等。
我们不仅仅使用指针来存储内存地址,同时也用它来解引用那些地址的内容,这样就可以访问和修改这些地址对应的值了
引入了void类型
指向指针的指针
int **q=&p;
int ***r=&q;
***r=10;
**q=*p+2;
后面的printf尽量有括号。
在变量前面放两个**,现在q可以存放p的地址了
<弹幕评论:前面定义变量的三个和后面三个不一样,一个是存储二级指针,一个是对地址解引用三次>
在声明语句中和执行语句中的*是不一样的
函数传值VS传引用
有空详细补一下结构体

浙公网安备 33010602011771号