C语言

笔记 / 2021-03-09

第一章程序设计和C语言

1.计算机程序:一组计算机能够识别的和执行的指令。

计算机语言

2.计算机语言

  • (1)机器语言:就是0和1组成的计算机可以识别的指令。
    • 优点:计算机可以直接识别。
    • 缺点:不易读,不易修改,编程繁琐。。。
    • 机器指令:10111100010101011
    • 机器语言:机器指令的集合。
  • 符号语言(汇编语言)
    • 101111000 1010 1011
    • ADD 10 11
    • 缺点:不同计算机之间不通用的,依赖计算机硬件
    • X86(台式机 笔记本)
    • ARM(手机)
    • X86:ADD 10 11;
    • ARM:ADDX 10 11;
  • (2)高级语言:使用接近人类的语言进行程序设计。
    • 第一个高级语言:FORTRAN
    • C语言 Java C# PHP PYTHON
    • 优点:接近人类。
    • 高级语言--->编译程序--->机器语言
    • 高级语言经历了:非结构化语言(Basic),结构化语言(C语言),面向对象语言(Java C# PHP PYTHON C++)

C语言标准

3.C语言的标准:C89标准和C99标准
4.C语言是面向过程的语言。

第一个C语言程序

#include<stdio.h>
// include包含一个头文件
//stdio  input  output 标准输入输出 
//行注释 C99
/*
	段注释 C89
*/ 
//void main(){     }   c89
int main(){//main()主函数,程序的入口  
//int 返回主函数执行是否成功 0---》成功  非0--》失败 
	printf("hello world!");
	//输出语句,将内容输出到屏幕上 
	//;-->表示一条语句的结束 
	return 0;//0---》成功  非0--》失败
}

C语言的程序结构

  • 1.一个C语言程序是由一个或者多个源文件(.c .h)组成的。
  • 2.一个C语言程序是由一个或多个函数组成的,其中必须包含一个main()函数,而且只能有一个main()函数。
  • 3.C语言程序总是从main()函数开始执行的。
  • 4.每条C语言程序后必须有分号。
  • 5.C语言程序本身不包含printf()函数,是通过stdio.h引入进来的。

C语言程序的步骤和方法

  • (1)编写C语言的源程序文件(.c .cpp),称为数据文件。
  • 对源程序进行编译(.obj 目标文件),目的就是变为2进制文件
  • (3)进行连接(组合)。
  • (4)得到可执行文件(.exe)

编辑——>编译——>连接——>运行

第二章算法

1.程序 = 算法+数据结构
算法:解决问题的步骤和方法。
数据结构:数据类型和数据的组织形式。
int double float char

算法的特性

  • (1)有穷性:步骤一定是有限的。
  • (2)确定性:每一个步骤都是确定的。
  • (3)零个输入或多个输入
  • (4)一个输出或多个输出
  • (5)有效性:每一个步骤都是可以有效执行的。
    image.png

如何来描述算法:

  • 1.自然语言描述 人话
    image.png
  • 2.用程序流程图描述
    image.png
  • 3.N-S流程图描述
    image.png
  • 4.用伪代码描述
    image.png
    image.png
  • 5.用计算机语言描述
    image.png
    5! = 12345

第三章顺序程序设计

c语言的三种基本结构

  • (1)顺序结构:从上到写一条一条执行
  • (2)选择结构:if 和switch
  • (3)循环结构:while和for

数据的表现形式

1.数据的表现形式
image.png

  • 常量:不能变化的量。整数常量 实型常量
  • 字符常量 字符串常量 符号常量
  • 整数常量:100 99 30
  • 实型常量:12.3 12.3e3 12.3e+3 12.3e-3
  • 字符常量:'+' \n \101 \x41
  • 字符串常量:"helloworld"
  • 符号常量:#define PI 3.141592653

进制转换

1.十进制转二进制
2.八进制(0-7)转十进制
3.十六进制转为十进制
(0 1 2 3 4 5 6 7 8 9 A B C D E F)
A--10
B-11
C-12
D-13
E-14
F-15
#include <stdio.h>
#define PI 3.141592653 
int main(){
	//5.符号常量 
	printf("area = %f\n",3*3*PI);
	//1.整数常量 234  678 1900 
	int a = 100; 
	printf("a = %d\n",a);
	//2.实型常量12.5 12.5e3表示12.5乘以10的3次方 
	float b = 12.5;
	printf("b = %f\n",b);
	float c = 12.5e+3;
	printf("c = %f\n",c);
	float d  = 12.3e-3; //表示12.3 乘以10的负3次方
	printf("d = %f\n",d); 
	//3.字符常量:含义表示一个字符   \转义 
	char e = 'a';
	printf("e = %c\n",e);
	char f = '\t';//转义字符 \n 回车换行 "\\"
	printf("aaabc\taaa\n");//\t tab键的长度  
	char g = '\101';//八进制 65 
	printf("g = %c\n",g);
	char h = '\x41';//十六进制 65 
	printf("h = %c\n",h);
	//4.字符串常量
	char i[]  = "helloworld";//'a'和"a"
	return 0;
}
  • 变量:可以变化的量。
  • 内存:正在执行的程序。
  • 硬盘:保存长久的数据。
  • int a:在内存中开辟一个空间,开辟4Byte的空间.4Byte = 32bit 1bit保存一个二进制数. int类型通常情况下,开辟4Byte的空间.
  • TurboC int -->2Byte
  • Dev-C++ -->4Byte
  • 64位--->8Byte

变量

(1)整型变量

int:整型 --->4Byte
short:短整型--->2Byte
long:长整型---->4Byte

#include <stdio.h>
int main(){
	int a = -2147483648; //21亿 
	//-2147483648---2147483647
	printf("a = %d\n",a) ;
	short b = 100;
	printf("b = %d\n",b) ;
	long c = 2147483647;
	printf("c = %d\n",c) ; 
	return 0;
}

short<=int<=long

(2)无符号数unsigned---->正

#include <stdio.h>
int main(){
	unsigned int a = 100; //a是无符号整数
	printf("a = %d\n",a);
	unsigned int b = -100;//////
	printf("b = %d\n",b);
	unsigned int c = 100;
	printf("c = %u\n",c);
	//int a = 30; 00000000 00000000 00000000 00011110
	//int a = -30;10000000 00000000 00000000 00011110
	//unsigned int a = -30;
	//10000000 00000000 00000000 00011110
	return 0;
}

(3)字符变量(特殊的整型)

char --->1Byte

#include <stdio.h>
int main(){
	char a  = 'a'; //字符变量a实际在内存中存储的是字符的ASCii码 
	printf("a = %c\n",a);
	printf("a = %d\n",a);//97+26-1-2 
	printf(" %d \n",('z'-2));
	char b = '\t';
	printf("b = %d\n",b);
	char c = '\101';
	printf("c = %d\n",c);
	char d = 66;
	printf("d = %d\n",d);
	printf("d = %c\n",d);
	return 0;
}

(4)浮点数(float double)

float:单精度浮点型(4Byte),小数点后6位有效
double:双精度浮点型(8Byte),小数点后15位有效.

#include <stdio.h>
int main(){
	//
	15.8;//double
	float a = 12.3f;//f或F//12.3--->double 
	printf("a = %.15f\n",a);
	double b = 12.5; 
	printf("b = %.15f\n",b);
	printf("b = %.2f\n",b);
	//%f--->输出浮点数,默认值为6位 
	return 0;
}

标识符(起名字)int a;变量 常量 函数 指针 数组....
命名规则:只能使用数字,字母,下划线_构造,第一个字符必须是字母或下划线.
int a; int abc123; int 123abc(error);

算术运算符 +(加法) -(减法) */%(求余) +(正号) -(负号)
赋值运算符 = 赋值顺序:从右到左

#include <stdio.h>
int main(){
	int a = 10;
	int b = 4;
//	int b,c,d;
//	b = c = d = 10; 
	int c;
	c = a+b;//优先级:算术运算符>赋值运算符 
	printf("c = %d\n",c);
	c = a-b;
	printf("c = %d\n",c);
	c = a*b;
	printf("c = %d\n",c);
	c = a/b;//int/int结果为int,不会四舍五入 
	printf("c = %d\n",c);
	c = a%b;//10/4 = 2...2 
	printf("c = %d\n",c);
	//当使用%符号时,%两边的数,必须是整型数 
	//1%3.2;error 
	return 0;
}

自增运算符

++和--运算符
++自增运算符
--自减运算符

#include <stdio.h>
int main(){
	int a = 10;
	int b;
	//b = a++;
	//1. 先将a的值赋值给b=10
	//2.再将a的值+1,a=11 
	b = ++a; 
	//1.先将a的值+1,a=11
	//2.再将a的值赋值给b = 11 
	//a++,先使用a的值,然后再将a的值+1
	//++a,先将a的值+1,再使用a的值 
	printf("a= %d\n",a); 
	printf("b= %d",b);
	return 0;
}
#include <stdio.h>
int main(){
	int a = 10;
	//printf("a = %d",a++);//1,打印  2.a++ 
	//i.使用a的值
	//ii.将a的值+1 
	//1.程序输出的结果为多少?10 
	//2.程序执行完成后,a的值为多少?11 
	printf("a = %d",++a);	
	printf("a = %d",a); 
	//1.程序输出的结果为多少?11 
	//2.程序执行完成后,a的值为多少?11 
	return 0;
}

不同类型数据间的混合运算

  • (1)+ - * /运算的两个数其中有一个为float或double类型,运算结果为double类型。5+3.4f ---->double 3.4f+2.3f---->double
  • (2)如果int类型与float或double类型运算,结果为double类型。
  • (3)字符类型(char)的数据与整型(int long short)进行运算,就是将字符的ASCII码与整型数据进行运算。

3/4+’a’+2.3-1.2/2
= 0+97+2.3-1.2/2
= 99.3-0.6
=98.7(double)

强制类型转换

#include <stdio.h>
int main(){
	float a = 12.03f;
	int b;
	b = (int)a;
	printf("b = %d",b);
	return 0;
}

赋值运算符 =

#include <stdio.h>
int main(){
//    int a,b,c;
//	a = b = c =10; //从右向左 
	//int a = b =c =10;error
	int a=10,b=10,c=10;
	//如果只定义变量,没有赋初值,变量为一个不确定的值 
	printf("a = %d\n",a); 
	printf("b = %d\n",b); 
	printf("c = %d\n",c); 
	return 0;
}

复合赋值运算符

+= -= = /= %=
a+=b ===》a = a+b
a-=b ====》a = a-b
a
=b =====>a = a*b
a/=b ====>a = a/b
a%=b ====>a=a%b

#include <stdio.h>
int main(){
	int a =1;
	int b = 2;
	a*=a+b;//a = a*(a+b)   a*=(a+b)
	printf("a = %d\n",a);
	return 0;
}

赋值过程中的类型转换

  • (1)将浮点数赋值给整型时,直接舍弃小数部分。
  • (2)将整型数据赋值给浮点型时,数值不变,以指数形式保存
  • (3)将一个double类型数据赋值给float类型数据时,数据有可能丢失精度。
  • (4)字符型数据赋值给整型变量,是将字符的ASCII码赋值给整型变量。
#include <stdio.h>
int main(){
	//1.浮点型----整型
	double a = 12.34;
	int b ;
	b = a; //直接舍去小数点后面的值,没有四舍五入 
	printf("b = %d\n",b);
	//2.整数--->浮点数
	int c = 10;//1.0*10的1次方 
	float d;//指数形式表示的数据比不用指数形式的范围要大 
	d = c; 
	printf("d = %f\n",d);
	printf("d = %e\n",d);
	//3.double(15)---float(6)
	double e = 12.345678912;
	float f ;
	f = e;
	//printf("e = %.10f\n",e);
	printf("f = %.10f\n",f);
	//4.char(1B)---int(4B) 
	char g = 'a';
	int h;
	h = g;
	printf("h = %d\n",h);
	//5.int---char
	int i = 301;
	char j;
	j = i;
	printf("j = %d\n",j);
	return 0;
}

printf()标准输出函数

#include <stdio.h>
int main(){
	//1.%d--->整型
	printf("No.1:%d\n",10); 
	printf("No.2:%6d\n",10); //靠右占6列 
	printf("No.3:%-6d---\n",10);//靠左占6lie
	//2.%c---->字符
	printf("No.4:%c\n",'a'); 
	printf("No.5:%3c\n",'\\');
	printf("No.6:%3c\n",'\101');
	//3.%s---->字符串
	printf("No.7:%s\n","hello world!");
	//4.%f(6位)---->浮点数
	printf("No.8:%f\n",12.3);
	printf("No.9:%20.10f\n",12.3); 
	printf("No.10:%-20.10f\n",12.3);
	//5.%e--->标准指数
	printf("No.11:%e\n",123.58);
	printf("No.12:%e\n",0.003752);
	//6.%o--->八进制表示
	printf("No.13:%o\n",18); 
	//7.%x---->十六进制
	printf("No.14:%x\n",18);  
	//8.%u---->无符号数
	printf("No.15:%u\n",18); 
	return 0;
}

scanf()---->输入函数

#include <stdio.h>
int main(){
	int a,b,c;
	printf("请输入值\n");
	scanf("+a=%d,b=%d,c=%d",&a,&b,&c);//&-->取地址
	//通过键盘输入的值,保存到变量a所在内存地址
	//所对应的空间。 
	printf("a=%d,b=%d,c=%d",a,b,c);
	return 0;
}

输入格式:%d%d%d,每个整型数据间要加(空格 回车 tab)

#include <stdio.h>
int main(){
	int a,b,c;
	printf("请输入值\n");
	scanf("%d%d%d",&a,&b,&c);//&-->取地址
	//通过键盘输入的值,保存到变量a所在内存地址
	//所对应的空间。 
	printf("a=%d,b=%d,c=%d",a,b,c);
	return 0;
}

输入格式:%c%c%c,每个字符要紧紧的挨在一起输入。

#include <stdio.h>
int main(){
	char a,b,c;
	printf("请输入值\n");
	scanf("%c%c%c",&a,&b,&c);//&-->取地址
	//通过键盘输入的值,保存到变量a所在内存地址
	//所对应的空间。 
	printf("a=%c,b=%c,c=%c",a,b,c);
	return 0;
}
#include <stdio.h>
int main(){
	double a;
	scanf("%lf",&a);
	printf("a = %f\n",a); 
	return 0;
}
#include <stdio.h>
int main(){
	//输入1234567
	//a = 123 
	int a;
	scanf("%3d",&a);
	printf("a = %d\n",a); 
	return 0;
}

字符输入输出函数

putchar()输出单个字符

#include <stdio.h>
int main(){
	char ch1 = 'a';
	printf("ch1 = %c\n",ch1);
	putchar(ch1);
	putchar('b');
	putchar('\n');
	putchar('\102');
	return 0;
}

getchar()输入单个字符

#include <stdio.h>
int main(){
	char a,b,c;
	//scanf("%c",&a);
	a = getchar();
	b = getchar();
	c = getchar();
	putchar(a); 
	putchar(b);
	putchar(c);
	return 0;
}

举例:
给三角形的三条边(a,b,c),求三角形的面积。

#include <stdio.h>
#include<math.h> 
int main(){

	double a,b,c;
	scanf("%lf%lf%lf",&a,&b,&c);
	double s = (a+b+c)/2;
	double area;
	area = sqrt(s*(s-a)*(s-b)*(s-c));//求平方根 
	printf("area = %.15f",area);
//	
	return 0;
}

求一元二次方程的解。

#include <stdio.h>
#include <math.h>
int main(){
	float a,b,c;
	scanf("%f%f%f",&a,&b,&c);
	float x1,x2;
	x1 = (-b+sqrt(b*b-4*a*c))/(2*a);
	x2 = (-b-sqrt(b*b-4*a*c))/(2*a);
	printf("x1 = %f,x2 = %f",x1,x2); 
	return 0;
}

输入一个大写字母,将大写字母转换为小写字母。

#include <stdio.h>
#include<math.h> 
int main(){
	char a;
	a = getchar();
	putchar(a+32); 
	return 0;
}

第四章选择结构(if switch)

关系运算

> < >= <= == !=

作用:判断关系运算左右的表达式是否满足这种关系。

5>3===>是(1) 否(0)
1==1 5>=5

优先级:算术运算符>关系运算符>赋值运算符

关系运算符内部:(> < >= <=)>(== !=)
执行顺序:从左到右

#include <stdio.h>
#include<math.h> 
int main(){
	printf("%d\n",5>3==4<=2+3-'a'); 
	//1.5>3==4<=-92
	//2.1==0
	printf("%d\n",1==5>=3<=3>3-2*2); 
	//1.1==5>=3<=3>-1
	//2.1==1
	printf("%d\n",1+2-3>3<2!=3>3<7); 
	//1.0>3<2!=3>3<7
	//2.1!=3>3<7
	return 0;
}

2.逻辑运算&&(与) ||(或) !(非)

&&(与):a&&b-->如果a和b同时为真(1),结果为真,如果其中有一个为假,结果为假(0)。
1&&1=1 1&&0=0 0&&1=0 0&&0=0
-2&&1=1 0&&-1=0
非零值(-1 2 6 -100)为真,零为假。
||(或):a||b-->如果a和b其中有一个为真,结果为真,如果a和b同时为假,结果为假。
1||1=1 0||1=1 1||0=1 0||0=0
!(非):!a-->a如果为真,!a为假,a如果为假,!a为真。
!0=1 !-2=0
优先级:
!>算术运算符>关系运算符>&&和||>赋值运算符
逻辑运算符:从左到右。

#include <stdio.h>
#include<math.h> 
int main(){
	printf("%d\n",3+2>3&&'a'-2||4<5); 
	//1.5>3&&'a'-2||4<5
	//2.5>3&&95||4<5
	//3.1&&95||1 
	//4.1 
	printf("%d\n",3>=5-!2&&4-5<6>=2<3==4);
	//3>=5&&-1<6>=2<3==4
	//0&&1==4   0&&0=0
	return 0;
}

3.if...else语句

  • if
  • if ... else
  • if ... else if...

if

if(只要返回1或0的值){
		
	} 

if中的条件为真,执行{}里面的语句,if中的条件为假,不执行{}里面的语句。

例如:输入两个整数,按照由小到大的顺序输出。

#include <stdio.h>
int main(){
	int a,b,t;//2,3  3,2 
	scanf("%d%d",&a,&b);
	if(a>b){
		//交换 
		t = a; 
		a = b;
		b = t;
	} 
	printf("%d,%d",a,b);
	return 0;
}

if ... else

if(表达式){
		
	}else{
		
	}

表达式的值如果为1,执行if下{}里的程序段,表达式的值如果为0,执行else下{}里的程序段。

例题:输入一个年份,判断该年份是否为闰年。
闰年:能被4整除并且不能被100整除或能被400整除。
(year%4==0&&year%100!=0)||(year%400==0)

#include <stdio.h>
int main(){
	int year;
	scanf("%d",&year);
	if((year%4==0&&year%100!=0)||(year%400==0)){
		printf("YES!"); 
	}else{
		printf("NO!");
	}
	return 0;
}
#include <stdio.h>
int main(){
	int year;
	scanf("%d",&year);
	if((year%4==0&&year%100!=0)||(year%400==0))
		printf("YES!"); 
	else
		printf("NO!");
	return 0;
} 

注意:如果if或else下只有一句话或一个完成不可分割的整体时,可以省略{}。

image.png
image.png

#include <stdio.h>
int main(){
	double x,y ;
	scanf("%lf",&x);
	if(x<1) y = x;
	//1<=x<10
	else if(x>=1&&x<10) y = 2*x-1;
	else if(x>=10) y = 3*x-11;
	printf("y = %f\n",y);
	return 0;
}

条件表达式(唯一的三目运算符)

一般形式:表达式1?表达式2:表达式3;
含义:先执行表达式1,如果表达式1的值为真(非0),执行表达式2;如果表达式1的值为假(0),就执行表达式3.

例如:给定两个整数,求这两个整数的最大值。

#include <stdio.h>
int main(){
    int a=3,b=10,max;
    //no1
//    if (a>b) max = a;
//    else max = b;
//no2
	//max = a>b?a:b;
	//no3
//	a>b?max=a:max=b;
//    printf("max = %d",max);
//no4
	a>b?printf("%d",a):printf("%d",b);
	return 0;
}

练习:
输入一个字符,判断它是否为小写字母,如果是大写字母,将此字母转换为小写,如果不是大写字母,则不转换。

#include <stdio.h>
int main(){
    char ch;
	ch = getchar();//scanf("%c",&ch);
//	if(ch>='A'&&ch<='Z'){
//		ch = ch +32; 
//	} 
//	ch>='A'&&ch<='Z'?ch=ch+32:ch;
//	putchar(ch);//printf("%c",ch); 
	ch>='A'&&ch<='Z'?putchar(ch+32):putchar(ch);
	return 0;
}

输入一个字符,如果是大写字母转换为小写字母,如果是小写字母转换为大写字母,如果是其他字符直接输出。

#include <stdio.h>
int main(){
	char ch;
	ch = getchar();
	if(ch>='A'&&ch<='Z'){
		//转换成小写 
		ch = ch +32;
		putchar(ch);
	} else if(ch>='a'&&ch<='z'){
		//转换成大写 
		ch = ch - 32;
		putchar(ch);
	} else{
		//直接输出
		putchar(ch); 
	} 
	return 0;
}

switch语句

	switch(表达式){
		case 常量:语句;
		case 常量:语句;
		case 常量:语句;
		case 常量:语句;
		....
		default:语句; 
	}

解释:语句结构中的“表达式”的类型一定为整数类型(char);default语句可以省略;各case标号出现的顺序不影响执行结果;每个case的标号的值不应相同;多个case语句可以共用一组执行语句。

例如:用户输入成绩的等级,输出对应的分数段。如输入A或a输出100-85,输入B或b输出84-70,输入C或c输出69-60,输出D或d输出59-0.

#include <stdio.h> 
int main(){
	char grade;//成绩等级	A B C D E F G
	grade = getchar();
	switch(grade){//整数(char) 
		 case 'a':
		 case 'A':printf("100-85\n");break;
		 case 'b':
		 case 'B':printf("84-70\n");break;
		 case 'c':
		 case 'C':printf("60-69\n");break;
		 case 'd':
		 case 'D':printf("59-0\n");break; 
		 default :printf("错误!\n");
	} 
	//1.在switch语句中,当碰到break,就跳出。
	//2.如果在switch语句中没有break,从第一个符合 
	//case后常量的语句开始执行,直到遇到break停止运行
	//如果一直没有遇到break,就知道switch语句执行结束。 
	return 0;
}

典型例题
1.输入一个四位数,分别输出这个四位数的千位,百位,十位,个位。

#include <stdio.h> 
int main(){
	int a ;
	scanf("%d",&a);
	int q,b,s,g;
	q = a/1000;
	b = a%1000/100;
	s = a%1000%100/10;//
	g = a%1000%100%10;
	printf("q = %d\n",q);
	printf("b = %d\n",b);
	printf("s = %d\n",s);
	printf("g = %d\n",g);
	return 0;
}

2.求解一元二次方程

#include <stdio.h> 
#include <math.h>
int main(){
	double a,b,c;
	scanf("%lf%lf%lf",&a,&b,&c);
	double disc = b*b-4*a*c;
	double x1,x2,p,q;
	//当小数比较是否相等时,千万别写== 15.4 15.39999 
	if(fabs(disc)<=1e-8){//disc==0 
		//有两个相等的实数根
		printf("有两个相等的实数根:%f\n",-b/(2*a)) ;
	}else if(disc>0){
		//有两个不相等的实数根
		x1 = (-b+sqrt(disc))/(2*a);
		x2 = (-b-sqrt(disc))/(2*a);
		printf("有两个不相等的实数根:%f,%f\n",x1,x2) ;
	}else{//有两个不相等的复数根
		p = -b/(2*a);
		q = sqrt(fabs(disc))/(2*a);
		printf("第一个复数根:%f+%fi\n",p,q) ;
		printf("第二个复数根:%f-%fi\n",p,q) ;
	}	 
	return 0;
}

例题3:
输入一个百分制成绩,要求输出成绩的等级。
例如:100-90分输出A,80-89输出B,70-79输出C,60-69输出D,59-0输出E。

#include <stdio.h> 
int main(){
	float score;
	scanf("%f",&score);
	if(score>0&&score<=100){
		switch((int)(score/10)){//float-->int
			case 10:
			case 9:printf("A");break;
			case 8:printf("B");break;
			case 7:printf("C");break;
			case 6:printf("D");break;
			case 5:
			case 4:
			case 3:
			case 2:
			case 1:
			case 0:printf("E");break;
		}
	}else{
		printf("error!");
	} 
	return 0;
}