C语言大纲
目录
15.字符储存【字符本质上与整数的储存方式相同】... 11
C语言概述
1.为什么学习C语言
1).C的起源和发展
2).C的特点
优点
代码量小 速度快 功能强大
缺点
危险性高
开发周期长
可移植性不强
3).C的应用邻域
4).的重要性
2.怎样学习C语言
3.学习的目标
4.常见问题答疑
1.学习Java为什么建议先学C语言
2.没学过计算机专业课程能够学懂C语言
3.英语和数学不能学好C么?
5.课程计划
6.举列子:一元二次方程
C编程预备计算机专业知识
- cpu
- 内存条 硬盘 显卡 主板 显示器 之间的关系
- HelloWorld程序如何运行起来的
什么是数据类型
基本类型数据
整型
整型 — int --4
短整型 –- short int --2
长整型 –- long int --8
浮点数【实数】
单精度浮点数 – float --4
双精度浮点数 -double --8
字符
char --1
复合类型数据
结构体
枚举
共用体
4.什么是变量
变量的本质就是内存条中一段存储空间
5.cpu 内存条 vc++6.0 操作系统 之间的关系
6.变量为什么必须的初始化
所谓初始化就是赋值的意思
7.如何定义变量
数据类型 变量名 = 要赋的值
等价于
数据类型 变量名; 变量名= 要赋的值
举列子:
int i = 3; 等价于 int i; i = 3;
int i, j; 等价于 int i;int j;
int i,j =3;等价于int i;int j;j = 3;
int i = 3,j = 5;等价于 int i;int j;i=3;j = 5;
int i,j; i = j = 5;等价于 int i,j; i = 5;j = 5;
8.①什么是进制【ppt】
逢n进一
十进制就是逢十进一
二进制就是逢二进一
②把r进制转换成十进制
③十进制转成r进制
④不同进制所代表的数值之间的关系
十进制的3981转化成十六进制是F8D
十进制的3981和十六进制的F8D所代表的本质上都是同一个数字
9.常量在C语言中是如何表示的
整数
十进制: 传统的写法
十六进制: 前面加0x或者0X
八进制: 前面0 注意是数字零不是字母O
浮点数
传统的写法
float x = 3.2;//传统
科学计数法
float x = 3.2e3; //x的值是3200—3.2乘10的3次方
float x = 123.45e-2; //x的值是1.2345
字符
单个字符用单引号括起来
‘A’表示字符A
‘AB’错误
“AB”正确
字符串用双引号括起来
“A”正确,因为“A”代表了‘A’‘\0’的组合
10.常量以什么样的二进制代码储存在计算机中
整数是以补码的形式转化为二进制代码储存在计算机中的
实数是以IEEE754标准转为二进制代码储存在计算机中的
具体可参见末尾的 穿插在课堂中的零散笔记
字符的本质实际也是与整数的储存方式相同
11.代码规范化
一.基本框架
二.注释1/3
三.成对敲
四.缩进。
1地位相等不需要缩进
五.换行。
程序分三部分1定义变量2对变量进行操作4输出值
六.空格。
1.等号=两边打空格 2.if 3.用上级别最低
七.好处1.增强代码的可读性2.美观3.降低代码的出错率
12.什么是字节
字节就是存储数据的单位,并且是硬件所能访问的最小单位
1个字节 = 8位
1k = 1024字节
1M = 1024K
1G = 1024M
13.不同类型数据之间相互赋值的问题
暂不考虑
int i = 45;
long j = 102345;
i = j;
printf(“%ld %d\”, i,j);
float x = 6.6
double y = 8.8;
printf(“%f %if\n, x, y,“);
14.什么是ASCII
ASCII不是一个值,而是一种规定,
ASCII规定了不同的字符是使用哪个整数值去表示
它规定了
‘A’—65
‘B’—66
‘a‘—97
‘b‘—98
‘O’--48
15.字符储存【字符本质上与整数的储存方式相同】
基本的输入和输出函数的用法
printf() –-将变量的内容输出到显示器上
四种用法
- printf(“字符串\n“);//\n表示换行
- printf (“输出控制符“,输出参数);
- printf(“输出控制符1 输出控制符2.。。。。”,输出参数1,输出参数2,。。。。);
输出控制符和输出参数的个数必须一一对应
- printf (“输出控制符 非输出控制符”,输出参数);
输出控制符包含如下
%d -- int
%ld -- long int
%c -- char
%f -- float
%lf -- double
%x(或者%X或者%#X) -- int 或 long int 或 short int
%o 字母o --同上
%s -- 字符串
为什么需要输出控制符
1.01组成的代码既可以表示数据也可以表示指令
2.如果01组成的代码表示的是数据的话,那么同样的01代码组成以不同的输出格式输出就会有不同的输出结果
scanf()【通过键盘将数据输入到变量中】
两种用法:
用法一: scanf(“输入控制符”,输入参数);
功能:将从键盘输入的字符转化为输入控制符所规定格式的数据,然后存入以输入参数的值为地址的变量中
用法二:scanf(“非输入控制符 输入控制符”,输入参数);
功能:将从键盘输入的字符转化为输入控制符所规定格式的数据,然后存入以输入参数的值为地址的变量中非输入控制符必须原样输入 //&表示i的地址 &是一个取地址符
如何使用scanf编写出高质量代码
- 使用scanf之前最好先使用printf提示用户以什么样的方式输入
- scanf中尽量不要使用非输入控制符,尤其是不要用\n
- 应该编写代码对用户的非法输入做适当的处理[非重点]
while ( (ch = get char()) != ‘\n’)
continue;
运算符
算术运算符
+ - * / (除) %(取余)
关系运算符
> >= < <= !=(不等于) ==(等于)
逻辑运算符
!(非) &&(并且) ||(或)
C语言对真假的处理
非零是真
零是假
真是1表示
假是0表示
&&左边的表达式是假 右边的表达式肯定不会执行
| |左边的表达式为真 右边的表达式肯定不会执行
赋值运算符
= += *= /= -=
优先级别
算数>关系>逻辑>赋值
附录的一些琐碎的运算符知识
自增 自减 三目运算符 逗号表达式
自增{或者自减}
分类:
前自增 -- ++i
后自增 -- i++
前自增和后自增的异同:
相同:
最终都使i的值加1
不同:
前自增整体表达式的值是i加1之后的值
后自增整体表达式的值是i加1之前的值
为什么会出现自增
代码更精炼
自增的速度更快
学习自增要明白的几个问题
- 我们编程时应该尽量屏蔽掉前自增和后自增的差别
- 自增表达式最好不要作为一个更大的表达式的一部分来使用或者说
i++和++i单独成一个语句,不要把它作为一个完整复合语句的一部分来使用
如:
int m = i++ + ++i + i + i++;//这样写不但是不规范的代码,而且是不可移植的代码
printf(“%d %d %d”, i++, ++i, i);//同上
2.三目运算符
格式
A ? B : C
等价于
If(A)
B;
else
C;
3.逗号表达式
格式
(A, B, C, D)
功能:
从左到右执行
最终表达式的值是最后一项的值
流程控制[是我们学习C语言的第一个重点]
什么是流程控制
程序代码执行的顺序
流程控制的分类
顺序执行
选择执行
定义
某些代码可能执行,也可能不执行,有选择的执行某些代码
分类
if
if最简单的用法
格式:
if(表达式)
语句
功能:如果表达式为真,执行语句
如果表达式为假,语句不执行
if的范围问题
1.
If(表达式)
语句A
语句B
解释:if默认的只能控制一个语句的执行或不执行
if无法控制语句B的执行或不执行
2.
if(表达式)
{
语句A
语句B
}
此时if可以控制语句A和语句B
由此可见:if默认只能控制一个语句的执行或不执行
如果想控制多个语句的执行或不执行
就必须把这些语句用{}括起来
- if..else(否则)…的用法
- if..else if…else…的用法
格式:
if(1)
else if(2)
B;
else if(3)
C;
else
D;
C语言对真假的处理
非零是真
零就是假
真用1表示
假用零表示
- if举例—求分数的等级
- if见问题分析
- 空语句的问题
if(3>2);
等价于
if(3>2)
; //这是一个空语句
2.
if(表达式1)
A;
else
B;
是正确的
if(表达式);
A;
else
B;
是错误的
3.
if(表达式1)
A;
else if(表达式2)
B;
else if(表达式3)
C;
else
D;
即使表达式1和2都成立,也只会执行A语句
4.
if(表达式1)
A;
else if(表达式2)
B;
else if(表达式3)
C;
这样写语法不会出错,但逻辑上有漏洞
5.
if(表达式1)
A;
else if(表达式2)
B;
else if(表达式3)
C;
else (表达式4)//7行
D;
这样写是不对的,正确的写法是:
要么去掉7行的(表达式4)
要么在7行的else后面加if
6.
if(表达式1)
A;
else if(表达式2)
B;
else if(表达式3)
C;
else(表达式4);
D;
这样写语法不会出错,但逻辑上是错误的
else(表达式4);
D;
等价于
else
(表达式4);
D;
switch
循环执行
定义:
某些代码会被重复执行
分类
for
格式:
for(1;2;3)
语句A;
执行的流程{重点}
单个for循环的使用
多个for循环的嵌套使用
1.
for(1;2;3)//1
for(4;5;6)//2
A;//3
B;//4
整体是两个语句,1 2 3是第一个语句
4是第二个语句
2.
for(1;2;3)
for(4;5;6)
{
A;
B;
}
整体是一个语句
3.
for(7;8;9)
for(1;2;3)
{
A;
B;
for(4;5;6)
C;
}
整体是一个语句
范围问题
- 举例:
1+2+3+…+100
1+1/2+1/3+…+1/100
While
- 执行顺序
格式:
while (表达式)
语句;
- 与for的相互比较
for 与while可以相互转换
但for的逻辑性更强,更不容易出错。推荐多使用for
for (1; 2; 3)
A;
等价于
1;
while (2)
{
A;
3;
}
- 举例
从键盘输入一个数字,如果该数字是回文数。
则返回yes,否者返回no
回文数:正着写和倒着写都一样
比如:121 12321 都是回文数
- 什么时候使用while,什么时候使用for
没法说,用多了自然就知道了
do…while
格式
do
{
……
}while(表达式)
do…while.并不等价于for,当然也不等价于while
主要用于人机交互
switch(开关)
break和continue
break
break如果用于循环是用来终止循环
break如果用于switch,则是用于终switch
break不能直接用于if,除非if属于循环内部的一个子句
例子:
for(i = 0; i < 3; ++i)
{
If(3>2)
break; //break虽然是if内部的语句,但break终止的确是外部的for循坏
printf(“嘿嘿!\n”);//用于不会输出
}
在多层循环中,break只能终止距离它最近的那个循环
例子:
在多层switch嵌套中,break只能终止距离它最近的switch
例子:
int x=1, y=0, a=0, b=0;
switch(x) //第一个switch
{
case 1;
switch(y)//第二个switch
{
case 0;
a++;
break;//终止的是第二个switch
case 1;
b++;
break;
}
b = 100;
break; //终止第一个switch
case 2;
a++;
b++;
break;
}
printf(“%d %d\n”, a,b);//26行
最终输出结果是:1 100
continue(继续)
用于跳过本次循环余下的语句,
转去判断是否需要执行下次循环
例子1:
for(1; 2; 3)
{
A;
B;
continue;//如果执行该语句,则执行完该语句后,会执行完该语句后,会执行语句3,C和D都会被跳过去
}
例子2:
while(表达式)
{
A;
B;
continue; //如果执行该语句,则执行完该语句后,会执行表达式,C和D会被跳过
C;
D;
}
数组
为什么需要数组
为了解决大量同类型数据的存储和使用问题
为了模拟现实世界
数组的分类
一维数组
怎样定义一维数组
为n个变量连续分配储存空间
所有的变量数据类型必须相同
所有变量所占的字节大小必须相等
例子:
int a【5】;
一维数组名不代表数组中所有的元素,
一维数组名代表数组第一个元素的地址
有关一维数组的操作
初始化
完全初始化
int a【5】= {1, 2, 3, 4,5};
不完全初始化,未被初始化的元素自动为零
int a【5】= {1,2,3};
不初始化,所有元素是垃圾值
int a【5】;
清零
int a【5】= {0};
错误写法:
int a【5】;
a【5】= {1, 2, 3, 4, 5};//错误
只有在定义数组的同时才可以整体赋值,
其他情况下整体赋值都是错误的
int a【5】= {1,2,3,4,5};
a【5】= 100;//error 因为没有a【5】这个元素,最多只有a【4】
int a【5】= {1,2,3,4,5};
int b【5】;
如果要把a数组中的值全部复制给b数组
错误的写法:
b = a;//error
正确的写法:
for(i=0; i<5; ++i)
b【i】=a【i】;
赋值
排序
求最大/最小
二维数组 初始化
操作
输出二维数组的内容:
对二维数组排序
求每一行的最大值
判断矩阵是否对称
矩阵的相乘
多维数组
是否存在多维数组
不存在
因为内存是线性一维的
n维数组可以当做每个元素是n-1为数组的一维数组
比如:
int a[3] [4];
该数组是含有3个元素的一堆数组
只不过每个元素都可以再分成4个小元素
int a[3] [4] [5];
该数组是含有3个元素的一堆数组
只不过每个元素都是4行5列的二维数组
字符数组
字符串处理函数
在文件头添加“#include ”
1.输出字符串函数puts
puts函数的作用是将指定的字符数组中的字符串输出,遇到"\0"停止。 格式为:
puts(字符数组名)
说明:
puts函数输出一个字符串后自动换行。
结果
2.输入字符串函数gets
作用:
是将从光标位置开始到回车键结束的一个字符串输入到字符数组。
格式为:
gets (字符数组名) 说明: gets函数一次只能输入一个字符串,回车结束
3.字符串连接函数 strcat( )
作用:
实现字符串的连接,即把字符串2连接到字符串1的后面,结果放在字符数组1中。
格式为:
strcat(字符数组名1,字符数组名2)
说明:
(1) 实现过程
(2) 字符数组1必须足够大。
(3) 连接后原第一个字符串后的'\0'取消。
结果
4.字符串复制函数 strcpy( )
作用:
实现字符串的复制,即把字符串2中的字符串复制到字符数组1中。
格式为:
strcpy(字符数组名1,字符串2)
5.字符串比较函数 strcmp( )
格式为:
strcmp(字符串1,字符串2)
功能:
比较字符串1和字符串2。
比较规则:
对两个字符串从左向右依次比较对应位置上的字符(按ASCII码值进行比较),直到出现不同的字符或遇到字符串结束标志'\0'为止。
如果全部的字符都相同,认为两个字符串相等,函数值为0,
否则以第一个不同的字符决定两个字符串的大小。
如果字符串1大于字符串2,函数值为一个正整数,
如果字符串1小于字符串2,函数值为一个负整数。
结果 t1=-1,t2=1
6.字符串长度函数 strlen( )
格式为:
strlen(字符数组名)
功能:
计算字符串的实际长度(不包括'\0')。
实现过程:
从字符串的头部开始向右扫描至'\0'为止,返回其长度。
7.大写字母转换为小写字母函数strlwr( )
格式为:
strlwr(字符串)
功能:
将字符串中的大写字母转换成小写字母。
8.小写字母转换为大写字母函数strupr ( )
格式为:
strupr(字符串)
功能:
将字符串中的小写字母转换为大写字母。
Sizeof()
Sizeof() 是一种内存容量度量函数,功能是返回一个变量或者类型的大小(以字节为单位);在 C 语言中,sizeof() 是一个判断数据类型或者表达式长度的运算符。
getchar
getchar是读入函数的一种。它从标准输入里读取下一个字符,相当于getc(stdin)。返回类型为int型,为用户输入的ASCII码或EOF。
getchar()是stdio.h中的库函数,它的作用是从stdin流中读入一个字符,也就是说,如果stdin有数据的话不用输入它就可以直接读取了,第一次调用getchar()时,确实需要人工的输入,但是如果你输了多个字符,以后的getchar()再执行时就会直接从缓冲区中读取了。
getchar可用宏实现:#define getchar() getc(stdin)。getchar有一个int型的返回值。当程序调用getchar时.程序就等着用户按键。用户输入的字符被存放在键盘缓冲区中。直到用户按回车为止(回车字符也放在缓冲区中)。当用户键入回车之后,getchar才开始从stdin流中每次读入一个字符。getchar函数的返回值是用户输入的字符的ASCII码,若文件结尾(End-Of-File)则返回-1(EOF),且将用户输入的字符回显到屏幕。如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取。也就是说,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完后,才等待用户按键。
函数【C语言的第二个重点】:
为什么需要函数
避免了重复性操作
有利于程序的模块化
什么叫函 数
逻辑上:能够完成特定功能的独立的代码块
物理上:
能够接收数据[当然也可以不接受数据]
能够对接受的数据进行处理
能够对数据处理得结果返回[当然也可以不返回任何值
总结: 函数是个工具,它是为了解决大量类似问题而设计得
函数可以当做一个黑匣子
如何定义函数
函数的返回值 函数的名字(函数的形参列表)
{
函数的执行体
}
- 函数定义的本质:是详细描述函数之所以能够实现某个特定功能的具体实现方法
- return表达式;的含义:
1*终止被调函数,向主调函数返回表达式的值
2*如果表达式为空,则只终止函数,不向主调函数返回任何值
3*break是用来终止循环和switch的,return是用来终止函数的
- 函数返回值的类型也称为函数的类型,如果因为函数名前的返回值类型和函数执行体中的return表达式;中表达式的类型不同的话,则最终函数返回
值的类型以函数名前的返回值类型为准
例子:
函数的分类
有参函数 和 无参函数
有返回值函数 和 无返回值函数
库函数 和 用户自定函数
值传递函数 和 地址传递函数
普通函数 和 主函数(main函数)
一个程序必须有且只有一个主函数
主函数可以调用普通函数 普通函数不能调用主函数
普通函数可以相互调用
主函数是程序的入口,也是程序的出口
注意的问题
常用的系统函数调用和函数定义的顺序
如果函数调用写在了函数定义的前面,则必须加函数前置声明
函数的前置声明:
- 告诉编译器即将可能出现的若干个字母代表的是一个函数
- 告诉编译器即将可能出现的若干个字母所代表的函数的形参和返回值的具体情况
- 函数声明是一个语句,末尾必须加分号
- 对库函数的声明是通过 # include <库函数所在的文件的名字.h>来实现的
形参和实参
个数相同 位置一一对应 数据类型必须相互兼容
如何在软件开发中合理的设计函数来解决实际问题
一个函数的功能尽量独立,单一
多学习,多模仿牛人的代码
函数是C语言的基本单位,类是Java,C#,C++的基本单位
常用的系统函数
double sqr (double x);
求的x的平方根
int abs(int x)
求x的绝对值
double fabs(double x)
求x的绝对值
专题:
递归
可以参见数据结构视频
变量的作用域和存储方式:
按作用域分:
全局变量:
在所有函数外部定义的变量叫全局变量
全局变量使用范围:
从定义位置开始到整个程序结束
局部变量:
在一个函数内部定义的变量或者函数的形参 都统一称为局部变量
void f(int i)
{
int j = 20;
}
i和j都属于局部变量
局部变量使用范围:只在本函数内部使用
注意的问题:
局部变量和全局变量命名冲突的问题
在一个函数内部如果定义的局部变量和名字和全局变量的名字一样时,局部变量会屏蔽掉全局变量
按变量的存储发生
静态变量
自动变量
寄存器变量
强制类型转换
格式:
(数据类型)(表达式)
功能:
把表达式的值强制转换为前面所执行的数据类型
例子:
(int)(4.5+2.2) 最终值是6
(float)(5) 最终值是5.000000
浮点数的储存所带来的问题
float和double都不能保证可以把所有的实数都准确的保存在计算机中
例子
float i = 99.9;
printf(“%f\n”, i);
最终在Vc++6.0中的输出结果是:99.900002
因为浮点数无法精确存储,所以就衍生出来两个编程问题:
有一个浮点型变量x,如何判断x的值是否是零
if(|x-0.000001| <= 0.000001)
是零
else
不是零
为什么循环中更新的变量不能定义成浮点型
C语言大纲——郝斌C语言课程等个人学习笔记,部分图片等资源来自网络若有侵权烦请联系。