程序猿的学习笔记3-C语言篇1

C语言简介

发展史:BCPL ->  new B  ->  C ->  Minix -> Linux -> gcc
C语言诞生:  1970年~1973年,在肯.汤姆逊和丹尼斯.里奇(影响大)主导下编写完成,归属美国贝尔实验室
C语言的诞生专门用于编写操作系统,所以天生适合一些硬件编程,也以速度快著称,也非常适合实现数据结构和算法
由于出现时间过早,也没想到普通人也能使用C语言编程,因此存在着很多缺陷,但是前辈已经总结了一些避免陷阱的经验
C语言三剑客:《C语言陷阱与缺陷》、《C指针》《C专家编程》
C语言语法很*,*也意味着危险,*源于自律
	语法标准:
		C89语法标准,也是gcc默认的语法标准
		C99语法标准,对C语言的扩展和增强
		C11语法标准,全新的升级 

一、第一个C语言程序:helld world

#include<stdio.h>
开头#预处理
        程序员写的代码不是标准C代码,需要一段程序进行翻译成标准C代码,负责翻译的程序叫做预处理器,翻译的过程叫预处理,被翻译的代码叫做预处理指令,以#开头的都是预处理指令
        #include 的功能就是把一个头文件导入到当前文件夹中
        #include<>:从系统指定的目录下加载xxx.h
        #include"":先从当前目录下加载xxx.h,如果找不到,再从系统指定目录找
        stdio.h  标准输入输出库函数
            头文件:以.h结尾的文件,里面存储的是一些辅助性的代码,绝大多数都是函数的声明
            源文件:以.c结尾的文件,里面存储的是功能性代码
            C语言标准委员会为C语言以函数的形式提供了一些基础的功能,这些函数都会封装在libc.so库中
            很多头文件负责对libc.so库中的代码进行声明,stdio.h就是其中一个
            string.h   stdlib.h

int main()
    C语言以函数的形式来管理代码,是管理代码的最小单位,一个函数就是一段代码的集合
    main函数是C程序的主函数,是整个C程序的执行入口和出口,有且只有一个
    int 是一种数据类型,表示函数的返回值类型是一个整数
    main函数的返回值返回给操作系统,main函数是由操作系统所调用的,反映了该程序是如何结束的,通常有三种:
        正数 出现异常(别人的错误)
        0    一切正常
        负数 出现错误(自己的错误)
        echo $?  可以获取上一个程序的返回值
{
    printf("hello world");
    return 0;
}

printf/scanf都是标准库中的函数,负责输入输出数据,用来调试程序
转义字符:键盘上一些没有的符号,用一些特殊的字符来表示,这些特殊的字符就是转义字符,\n就是其中之一。
    \n 换行
    \t 制表符,用于对齐数据
    \r 光标回到行首
    \a 铃响
    \b 退一个字符
    %% 表示%
    \\ 表示\
C语言中以分号作为一行代码的结束标注,使用{}来划分区域

二、编译器

把人能看懂的代码组成的文件,翻译成计算机能看懂二进制文件,由预处理器、编译器、链接器组成。
gcc是HNU社区为了编译Linux代码而开发的一款免费的编译器,默认采用C89语法标准,-std=gnu99可以设置C99语法
    常用的参数:
    -E 只显示与处理的结果
    -c 只编译不链接
    -o 指定输出结果的名字
    -I 指定头文件的加载路径
    -S 进行汇编,生成汇编代码
    -l 指定要使用的库文件
    -Wall 尽可能多的产生警告
    -Werror 把警告当错误处理
    -std 指定编译语法
    -D 命令行定义宏

三、C代码变成可执行程序的过程

1、预处理:把源文件翻译成预处理文件     一般用于查看宏定义的替换结果,检查宏函数
    gcc -E code.c   显示预处理处理的结果        
    gcc -E code.c -o code.i   生成以i结尾的预处理文件 
2、编译:把预处理文件翻译成汇编文件     理解C/C++代码的底层工作原理 函数重载原理
    gcc -S code.i   生成以.s结尾的汇编文件 
3、汇编: 把汇编文件翻译成2进制的目标文件       生成代码库、静态库、共享库
    gcc -c code.s   生成以o为结尾的目标文件
4、链接:把若干个目标文件合并成一个可执行文件       多文件编程的基础
    gcc code.o a.o b.o c.o ...   默认生成一个a.out的可执行文件

四、不同的C文件类型

    .h 头文件
    .h.gch 头文件的编译结果,它会被优先使用
    .c 源文件
    .i 预处理文件
    .s 汇编文件
    .o 目标文件
    .a 静态库
    .so 共享库

五、数据的储存单位

Bit     比特    一个二进制位,只能存0或者1,计算机中存储数据的最小单位
Byte    字节    8个二进制位,计算机中存储数据的基本单位
KB      1024字节
MB      1024KB
GB      1024MB
TB      1024GB
PB      1024TB

六、数据类型

为什么要对数据分类:
    1、现实生活中的数据都是自带类别属性
    2、对数据进行分类可以节约储存空间,提高运行的效率

C语言中的数据分为两大类:自建(程序员自己设计,例如:结构、联合、类)、内建(C语言中自带)
可以使用sizeof计算类型的字节数大小  sizeof(signed long)
整型:
    signed      有符号
        signed char         1   -128~127
        signed short        2   -32768~32767
        signed int          4   正负20亿
        signed long         4或8(由操作系统位数决定)
        signed long long    8   以9开头19位数字的整数
        注意:signed不加就代表加

    unsigned    无符号
        unsigned char         1     0~255
        unsigned short        2     0~65535
        unsigned int          4     0~40亿
        unsigned long         4或8(由操作系统位数决定)
        unsigned long long    8     1开头的20位正整数
        注意:由于定义无符号的数据是比较麻烦,标准库把这些无符号的类型重新定义成以下的类型:
            需要包含一个头文件<stdint.h>
            uint8_t uint16_t  uint32_t  uint64_t

浮点型:
    float           4
    double          8
    long double     12或者16(根据系统)
    注意:采用科学计数法存储,二进制与真实的数据之间需要翻译转换,因此浮点型运算速度就比整型要慢,编程时尽量采用整型
    小数点后六位有效
    判断float类型的数据是否是0
    float num;
    if(num 0 <= 0.000001 || num >= -0.000001)

字符型:
    char 字符其实就是符号或者图案,但是,在内存中存储的是整数,需要显示字符时,会根据ASCLL码表中对应关系来显示相应的符号或者图案。
    0       ''      特殊字符,表示什么都没有
    48      '0'
    65      'A'
    97      'a'
布尔型:
    由于先有了C语言后才有了bool类型,所以C语言不可能有真正的布尔类型,使用stdbool.h头文件,该文件是对布尔类型做的模拟
        bool  true  false

七、变量与常量

什么是变量:程序运行期间数值可以发生改变的叫做变量,相当于存储数据的盒子。
定义:  类型 变量名;
        int num;
    取名规则:
        1、只能是由字母、数字、下划线组成
        2、不能以数字开头
        3、不能与32个C关键字重名
        4、见名知意【功能、类型、作用域...】
使用:
    赋值:num = 100;
    参与运算:num*10;
    注意:C语言中变量的值默认是随机的,为了安全起见,一般都初始化为0

变量的输入输出:
    int printf (const char *format,...);
    功能:输出数据
    format: "双引号包含的格式信息(提示信息+占位符)"
    ...: 要输出的变量的列表
    返回值: 输出的字符的个数

    int scanf(const char *format,...);
    功能:从键盘输入数据
    foemat:"由双引号包括的格式信息(占位符)"
    ...:要接收的变量的列表
    返回值:成功输入的变量个数
    注意:scanf需要的是变量的类型、变量的地址,变量的地址 = &变量名
    
     练习1:定义各种类型的变量并初始化,使用scanf输入,使用printf显示
#include<stdio.h>
 
int main(int argc,const char* argv[])
{
	char num_c=0;
	short num_s=0;
	int num_i=0;
	long num_l=0;
	long long num_ll=0;
	unsigned char num_uc=0;
	unsigned short num_us=0;
	unsigned int num_ui=0;
	unsigned long num_ul=0;
	unsigned long long num_ull=0;
	float num_f=0;
	double num_d=0;
	long double num_ld=0;
	printf("请输入num的值:");
	scanf("%hhd%hd%d%ld%lld",&num_c,&num_s,&num_i,&num_l,&num_ll);
	scanf("%hhu%hu%u%lu%llu",&num_uc,&num_us,&num_ui,&num_ul,&num_ull);
	scanf("%f%lf%LF",&num_f,&num_d,&num_ld);
	printf("char=%hhd,short=%hd,int=%d,long=%ld,longlong=%lld",num_c,num_s,num_i,num_l,num_ll);
	printf("uchar=%hhu,ushort=%hu,uint=%u,ulong=%lu,ulonglong=%llu",num_uc,num_us,num_ui,num_ul,num_ull);
	printf("float=%f,double=%lf,longdouble=%LF",num_f,num_d,num_ld);
}
类型占位符:C语言通过占位符来传递变量的类型 
    signed      %hhd %hd %d %ld %lld
    unsigned    %hhu %hu %u %lu %llu
                %f %lf %LF 

什么是常量:程序运行期间数值绝对不能改变的叫常量
    字面值常量
        100 'a' "hello world"
    枚举常量
    宏常量
    100 int(默认int)
    100l long
    100ll long long
    100u unsigned int
    100lu
    100llu
    3.14 默认double类型
    3.14f float

八、格式化输入输出

%nd  显示n个字符宽度,如果不够则补空格,右对齐
%-nd  显示n个字符宽度,如果不够则补空格,左对齐
%0nd  显示n个字符宽度,如果不够则补0,右对齐
%n.mf   显示n个字符宽度,小数也算一位,不够则补空格,m表示小数点后的位数(四舍五入)
%g    不显示小数点后多余的0

九、运算符

自变运算符:
    前后++/--,使变量的值自动加1或者减1
        前自变  立即有效
        后自变  下一句语句生效
        注意:不要再一行语句中多次使用自变运算符

算数运算符
    + - * / %
    / %  除数不能为0,会造成浮点数例外,核心已转储,程序直接死掉
    整数/整数   结果没有小数部分

关系运算符
    > < >= <= == !=
    比较的结果是0(假)或1(真),运算结果可以继续参与运算 
        if(a>b==0)
    int num = 500;
    0<num<100;永远为真

逻辑运算符
    && || !
    比较对象转换为逻辑值,0转换成假,非0转换为真
    A && B 一假为假
    A || B 一真为真
    !A     求反
    &&、|| 具有短路特性:
        当左边的表达式可以确定整个表达式的结果时,右边不进行计算
    
三目运算符
    运算对象有3个
    A?B:C   先判断A的表达式真假,若为真执行B,假执行C
    注意:该语句不能使用流程控制语句,因为他必须要有运行结果

赋值运算符
    = += -= *= /=
    num+=100  <=>  num=num+100

位运算符
    & | ~ ^ >> <<
    后边讲

十、类型转换

自动类型转换:
    只有相同类型的数据才能进行运算,不同类型数据自动转换成相同类型再进行计算:
        转换规则(以不丢失数据为基础,适当牺牲一些空间)
            1、字节少的向字节多的转     考虑优先级
            2、有符号向无符号的转
            3、整型向浮点型转

    强制类型转换:
        (想要转成的类型)原数据;
        int num;
        (short)num;
        注意:有丢失数据风险,慎重使用

十一、分支语句

if(表达式)  //单分支
{
    表达式为真,执行此处代码
}

if(表达式)    //双分支
{
    表达式为真,执行此处代码
}
else
{
    表达式为假,执行此处代码
}

if(表达式1)   //多分枝
{
    表达式1为真,执行此处代码
}
else if(表达式2) 
{
    表达式2为真,执行此处代码
}
else if(表达式3)
{
    表达式3为真,执行此处代码
}
else
{
    当表达式123都为假时执行此处代码
}

作业

作业1:输入三个整数(键盘),从大到小显示。
#include<stdio.h>
 
int main(int argc,const char* argv[])
{
	int a[3];
	int i,k,j;
	printf("请输入三个整数");
	for(i=0;i<3;i++)
	{
		scanf("%d",&a[i]);
	}
	for(i=0;i<3;i++)
	{
		for(j=i+1;j<3;j++)
		{
			if(a[i]<a[j])
			{	
				k=a[i];
				a[i]=a[j];
				a[j]=k;
			}		
		}
	}
	for(i=0;i<3;i++)
	{
		printf("%d",a[i]);
	}
	return 0;	
}
作业2:输入一个年份,判断是否时闰年
#include<stdio.h>
 
int main(int argc,const char* argv[])
{
	int year;
	printf("请输入年份");
	scanf("%d",&year);
	if(year % 400 == 0)
	{
		printf("是闰年");
	}
	else if(year % 4 == 0 && year % 100 != 0)
	{
		printf("是闰年");		
	}
	else
	{
		printf("不是闰年");
	}

}
作业3:输入一个年份与月份,判断该月多少天
#include<stdio.h>
 
int main(int argc,const char* argv[])
{
	int year,mon;
	printf("请输入年份");
	scanf("%d",&year);
	printf("请输入月份");	
	scanf("%d",&mon);
	if(year % 400 != 0 && year % 4 != 0)
	{
		if(mon==2)
		{
			printf("该月28天");	
		}
		else if(mon==4 || mon==6 || mon==9 || mon==11)
		{
			printf("该月30天");
		}
		else if(mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)
		{
			printf("该月31天");	
		}
		else
		{
			printf("输入错误");	
		}
	}
	else
	{
		if(mon==2)
		{
			printf("该月29天");	
		}
		else if(mon==4 || mon==6 || mon==9 || mon==11)
		{
			printf("该月30天");
		}
		else if(mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)
		{
			printf("该月31天");	
		}
		else
		{
			printf("输入错误");	
		}
	}
	return 0;
}
作业4:输入一个三位整数,判断是否是水仙花数
#include<stdio.h>
 
int main(int argc,const char* argv[])
{
	int g,s,b;
	int num;
	printf("请输入一个三位整数");
	scanf("%d",&num);
	b=num/100;
	s=num%100/10;
	g=num%10;
	if(num>=100 && num<=999)
	{
		if(num==g*g*g+s*s*s+b*b*b)
		{
			printf("是水仙花数");
		}
		else
		{
			printf("不是水仙花数");
		}
	}
	else
	{
		printf("请仔细审题");
	}
	return 0;
}
作业5:输入一个成绩,判断该成绩的等级
#include<stdio.h>
 
int main(int argc,const char* argv[])
{
	int cj;
	printf("请输入成绩");
	scanf("%d",&cj);
	if(cj<0 || cj>100)
	{
		printf("输入错误");	
	}
	else
	{
		
	
			if(cj<=100 && cj>=90)
			{
				printf("A");
			}		
			else if(cj<90 && cj>=80)
			{
				printf("B");
			}		
			else if(cj<80 && cj>=70)
			{
				printf("C");
			}		
			else if(cj<70 && cj>=60)
			{
				printf("D");
			}		
			else if(cj<60 && cj>=0)
			{
				printf("E");
			}		
	}
	return 0;
}
上一篇:Kubernetes Helm的应用


下一篇:51nod_2006_飞行员配对(二分图最大匹配)