C语言基础学习笔记
Linux基本命令
【1】打开/关闭终端
打开:
1.直接点终端图标
2.Ctrl + Alt + t
//默认家目录
3.Ctrl + Shift + n
//当前路径
关闭:
1.直接点击"x"关闭
2.exit
//终端输入并回车
3.Ctrl + d
【2】终端
hq @ eduVm : ~ $
用户名 主机名 当前路径 命令提示符
查看用户名:whoami
查看主机名:hostname
~:家目录 /home/hq
查看当前路径:pwd
【3】Linux文件系统标准
“倒置树形”
/home:存放用户信息
/bin:存放命令
/mnt:挂载文件
/dev:设备文件
【4】ls
列出当前路径下所有文件
ls -a
:列出当前路径下所有文件包括隐藏文件
ls -i
:查看当前路径下文件的inode号(文件唯一标识)
ls -l
:列出当前路径下所有文件的信息
d rwxrwxr-x 2 hq hq 4096 7月23 14:49 TEST
从左到右依次是:
文件类型 文件权限 链接数 用户名 组名 大小 最后一次修改的时间 文件名
文件类型(7种):
bcd_lsp
b
:块设备文件
c
:字符设备文件
d
:目录文件
-
:普通文件
l
:软链接
s
:套接字文件
p
:管道文件
文件权限:
rwx | rwx | r-x |
---|---|---|
用户权限 | 组内权限 | 其他 |
111 | 111 | 101 |
7 | 7 | 5 |
r
:读权限:4
w
:写权限:2
x
:可执行 :1
-
:没有权限 0
修改权限:chmod 权限值 文件名
【5】cd
cd + 绝对路径:
绝对路径:pwd
cd +相对路径:相对于当前路径
. :表示当前;
.. :表示上一级;
cd .. :返回上一级
cd -:返回上一次的路径
cd ~:回家目录
cd :回家目录
cd /:回根目录
【6】新建
新建普通文件:touch +普通文件名.后缀
同时新建多个普通文件:touch 1.c 2.c 3.c
touch同名文件:更新时间戳
新建目录文件:mkdir +目录文件名
同时新建多个目录文件:mkdir 1 2 3
创建多个层级关系的目录文件:mkdir -p 1/2/3
mkdir同名文件:File exists(报错!)
【7】rm
删除
rm 普通文件名
rm -r 目录文件名
rm -rf 目录文件名//强制删除
【8】cp
cp 普通文件名 目标路径
cp -r 目录文件名 目标路径
另存为:cp 普通文件名 路径/新文件名
cp 1.c ~/music/hello.c
【9】mv
mv 文件名 目标路径
mv 目录文件名 目标路径
重命名:mv 原文件名 新文件名
补充:共享文件夹 /mnt/hgfs
【10】常用快捷键
放大终端:Ctrl Shift +
缩小终端:Ctrl -
清屏:Ctrl l
clear
(终端输入)
查看历史命令:键盘上下键
补全:Tab
【11】vi编辑器
vi 文件名
三种工作模式:
命令行模式:复制、粘贴、删除、光标移动、撤销
插入模式:文本编辑
底行模式:保存、退出、分屏、查找、替换
命令行模式:
进入vi默认进入命令行模式
单行复制:yy
多行复制:nyy
粘贴:p
单行删除/剪切:dd
多行删除:ndd
撤销:u
恢复:ctrl r
光标移动:
首行:gg
末行:G
行首:0
行尾:$
整理代码格式:gg=G
插入模式:
a: 从光标所在位置的下一个字符键入
A:从光标所在行行尾键入
i:从光标所在位置的前一个字符键入
I:从光标所在行行首键入
o:从光标所在行下面另起一行键入
O:从光标所在行上面另起一行键入
底行模式:
保存:w
退出:q
保存并退出:x或wq
强制退出:q!
强制保存:w!
指定行复制:5,10y //复制5-10行内容
指定行删除/剪切:5,10d //删除5-10行内容
查找:/str
替换:s/str1/str2 //将光标所在行第一个str1换成str2
s/str1/str2/g //将光标所在行所有str1换成str2
1,$ s/str1/str2/g //将全文的str1 替换成str2
% s/str1/str2/g //将全文的str1 替换成str2
分屏:vsp 文件名
取消高亮:nohl
【12】简单编程步骤
- 创建.c文件
touch hello.c
- 用vi编辑器打开文件
vi hello.c
- 编写代码
#include<stdio.h> //头文件
int main( ) //主函数
{
printf("hello world!\n");//打印hello world!
return 0;
}
- 保存退出
wq
- 编译代码
gcc hello.c
- 执行可执行文件
./a.out
【1】编程语言发展历程
机器语言 二进制序列
汇编语言 移植性差
高级语言 c c++
【2】gcc 编译器
功能:将代码转换成计算机能识别的机器语言
编译过程
1. 预处理:展开头文件,删除无用注释,替换宏定义
gcc -E hello.c -o hello.i
2. 编译:检查语法错误,有就报错,没有问题就转换成汇编语言,生成汇编文件
gcc -S hello.i -o hello.s
3. 汇编:将汇编文件转换成二进制目标文件
gcc -c hello.s -o hello.o
4. 链接:链接库文件,最终生成机器能够识别的可执行文件
gcc hello.o -o hello
gcc hello.c -o hello
【3】计算机存储单位
字节、位
1Byte=8bit
1kB=1024B
1MB=1024KB
1GB=1024MB
1T=1024GB
【4】计算机数据表示形式
- 数值型数据:能够进行算术运算并能得到数值的数据
二进制 0、1 10 11
八进制 0-7 10
十进制 0-9 10
十六进制 0-9,A-F
基础内容
进制转换
进制转换:
十进制转换为二进制
1) 短除法:除2倒取余
66 1000010
2) 拆分法:拆成2的次方和
66=64+2=2^6+2^1
3) 计算机
二进制转十进制:
2的次方和
从低位开始,依次是2的0次方,递增
101100 44
八进制转换成二进制
1位8进制用3位二进制表示(421码),八进制以0开头
053 =》101 011
0765=》111 110 101
二进制转换成八进制
从低位开始三位二进制一组,不够补零
110110 066
101101001 0551
十六进制转二进制
1位16进制用4位二进制表示,0x开头(8421码)
0xab 1010 1011
0x3ce 0011 1100 1110
二进制转十六进制
从低位开始,每4个二进制为1组,转换成一位16进制
11000110 0xc6
- 非数值型数据
ASCII码
\0 0
\n 10
' ' 32
'0' 48
'9' 57
'A' 65
'Z' 90
'a' 97
'z' 122
大写字母 +32 = 小写字母
小写字母 -32 = 大写字母
‘0’-48=0
字符0 -48 = 数字0
man (7章)
- shell命令
- 系统调用
- 库函数
按q
退出
词法符号
概念:由若干字符组成的有意义的最小语法单位
分类:关键字 、标识符、运算符、分隔符、标点符号
【6】关键字(32个):重要记住!!!
概念:由系统预定义的具有特殊功能的词法符号
分类:
存储类型:auto static extern register
数据类型:char short int long float double signed unsigned
构造类型:struct union enum
选择结构:if else switch case default
循环结构:for while do goto break continue
其他:void(空) typedef (重定义) volatile(防止编译器优化)
const(只读修饰) sizeof(计算数据所占空间大小) return(返回值)
【7】标识符
概念:用来标识变量、函数或者其他用户自定义的项目的名称
遵循规则:
1. 由数字、字母、下划线组成
2. 开头不能是数字
3. 不能和关键字重复
4. 见名知义
【8】运算符(6种)
- 算术运算符
+ - * / % ++ --
/: 整数相除,向下取整
%:只能进行整数运算
++
:
int a=10/3; a=3
int a=5/2; a=2
float a=5/2; a=2.000000
float a=5.0/2; a=2.500000
%: 10%3=1
赋值运算:
int a=3;//定义了一个整形变量,并且赋值为3;
1) int b = ++a;//a=4,b=4; ++在前,先自加1再赋值
2) int b = a++; // b=3,a=4 ;++在后,先赋值再自加1
打印语句:
int a=3;
1) printf("%d\n",a++); //3,a=4;++在后,先打印再自加1
2) printf("%d\n",++a);//4 ,a=4;++在前,先自加再打印
独立成句:
int a=3; //a=a+1;
1) a++;
printfk("%d\n",a);//4
2) ++a;
printfk("%d\n",a);//4
练习题:
1.以下程序输出的结果是:d=31
#include <stdio.h>
int main(int argc, char const *argv[])
{
int a = 10;
int b = a++; // b=10,a=11
int c = a + b; // c=21
int d = (b++) + c; // d=31,b=11
printf("d=%d\n", d);
return 0;
}
2.以下程序输出的结果是:d=34
#include <stdio.h>
int main(int argc, char const *argv[])
{
int a = 10;
int b = ++a; // a=11,b=11
int c = a + (b++); // c=22,b=12
int d = b + c; // d=34
printf("d=%d\n", d);
return 0;
}
--
:
--在前,先自减1,再赋值
--在后,先赋值,再自减1
- 逻辑运算符
&& :逻辑与
|| :逻辑或
! :逻辑非
运算法则:
逻辑与:&& : 全真才真,一假则假
逻辑或:|| : 一真则真,全假则假
逻辑非: ! : 非真即假,非假即真
截断法则:
逻辑与运算中,如果第一个表达式为假,则后面的表达式不执行
逻辑或运算中,如果第一个表达式为真,则后面的表达式不执行
例如:
#include <stdio.h>
int main()
{
int a = 5, b = 6, c = 7, d = 8, m = 2, n = 2;
(m = a < b) || (n = c > d);
printf("%d %d", m, n); // 1 2
return 0;
}
#include <stdio.h>
int main()
{
int a = 5, b = 6, c = 7, d = 8, m = 2, n = 2;
(m = a > b) && (n = c > d);
printf("%d %d", m, n); // 0 2
return 0;
}
- 位运算符
& | ~ ^ << >>
运算法则:
&:全1则1,有0则0
0xab & 0x3c
0xab 1010 1011
0x3c 0011 1100
&: 0010 1000 0x28
|:有1则1,全0为0
0xd5 | 0x9c
0xd5: 1101 0101
0x9c: 1001 1100
|: 1101 1101 0xDD
~(按位取反,通过补码取反)
反码:除符号位外,每一位按位取反
补码:
正数的补码等于正数本身
负数的补码等于反码+1
^:异或
相同为0,不同为1
0xab ^ 0x3c
0xab: 1010 1011
0x3c: 0011 1100
^: 1001 0111 0x97
<<
左移
左移几位右边补几个0
位运算中左移一位是乘二的关系
-5 << 3
-40
>>
右移
右移几位,左边补几个符号位
8 >> 2 2
置位问题:
将4的1位置1,100 //110
4|(1<<1)
置一公式:将a的n位置一: a|(1<<n)
置零公式: 将a的n位置0:a&(~(1<<n))
- 关系运算符
> < == != >= <=
两个等号是相等!!!
- 赋值运算符
= += -= *= /= %=。。
a+=1;//a=a+1;
a*=5;//a=a*5;
- 三目运算符
表达式1?表达式2:表达式3;
运算法则:如果表达式1成立,执行表达式2,否则执行表达式3;
#include <stdio.h>
int main()
{
int a = 3, b = 5;
int c = a < b ? a++ : ++b; // c=3,a=4;
printf("%d", c);//3
return 0;
}
运算符优先级:
单目运算符: ! ~ ++ --
算术运算符: + - * / %
移位运算符: << >>
关系运算符: < <= > >= == !=
位与运算符: &
异或运算符: ^ |
逻辑运算符: && ||
条件运算符: ?:
赋值运算符: = += -= *= /= %=
口诀:
单算移关与,异或逻条赋
从右向左单条赋
【2】标点符号
分号 逗号 大括号 小括号
【3】分隔符
空格 tab 换行
变量 常量
【4】变量
概念:在程序运行过程中会发生变化的量
格式:存储类型 数据类型 变量名
数据类型:变量所占字节的个数
char 字符型 1字节 -2^7 ~ 2^7-1
short 短整型 2字节 -2^15 ~ 2^15-1
int 整形 4字节 -2^31 ~2^31-1
long 长整型 4字节 -2^31 ~2^31-1
float 单精度浮点型 4字节 有效数据的位数6—7位
double 双精度浮点型 8字节 有效数据的位数15-16位
变量名注意符合标识符的命名规则
变量的分类(区别):
全局变量
定义位置:定义在函数体外部
初值:0
存储位置:全局区(静态区)
生命周期:随整个程序的结束而结束
作用域:整个程序
局部变量
定义位置:定义在函数体内部
初值:随机值
存储位置:栈区
生命周期:随着函数调用结束而结束
作用域:整个函数
【1】内存分区
【2】常量
概念:在程序运行中不会发生变化的量
分类:
1)字符常量
'a' '\0'
2) 字符串常量
"hello" "a"
字符串的结尾会默认补'\0'
3)整型常量
100 5 3
4)浮点型常量
3.1415926 2.5 3.6
5)指数常量
3*10^3 3e3
2*10^-5 2e-5
6)标识常量
宏定义:其标识作用
宏名符合标识符命名规则
宏名一般大写
#define 宏名 常量或表达式
特点:
原样替换,不要手动运算
练习:
#include <stdio.h>
#define N 2
#define M N + 3
#define NUM N + M / 2 + 1
void main()
{
int a = NUM;
printf("%d\n", a);
} // 6
练习:结合宏定义和三目运算符实现两个数求最大值
#include <stdio.h>
#define MAX a > b ? a : b
int main()
{
int a = 3, b = 5;
printf("%d\n", MAX);
}//5
输入 输出
【3】输入输出
函数三要素:功能 参数 返回值
1. 按照字符输入输出
输入:
int getchar (void);
功能:从终端输入一个字符
参数:无
返回值:输入字符的ASCII码
输出:
int putchar (int c);
功能:向终端输出一个字符
参数:c:要输出字符的ASCII码//putchar(97) == putchar('a')
返回值:要输出字符的ascii码
练习:实现输入大写字母转换成小写字母输出
#include <stdio.h>
int main()
{
int ret = getchar();
putchar(ret + 32); // 大写转小写
putchar('\n');
}
2. 按照格式进行输入输出
输出:
int printf(const char*format,....);
功能:按照指定格式向终端输出
参数:format:字符串
"%d" int
"%c" char
"%f" float
"%lf" double
"%s" 字符串
"%#x" 十六进制
"%#o" 八进制
"%p" 地址
"%e" 指数
"%u" 无符号
"%-m.n" -:左对齐,一般默认右对齐
m:位宽,当m>实际数据位宽时,按m位宽输出
当m<实际数据位宽时,按实际位宽输出
.n:表示保留小数点后n位
返回值:输出字符的个数(不常用)
输入:
int scanf(const char*format,....);
功能:按照指定格式从终端输入
参数:formet同printf
"%d" int
"%c" char
"%f" float
"%lf" double
"%s" 字符串
"%#x" 十六进制
"%#o" 八进制
"%p" 地址
"%e" 指数
"%u" 无符号
返回值:正确输入数据的个数
练习:一个水分子的质量约为3.0*10^-23g,1夸脱水大约有950g,
编写一个程序,要求输入水的夸脱数,然后显示这么多水中包含多少水分子。
表示:3.0e-23 打印格式:%f或%e
#include <stdio.h>
int main()
{
int num;
scanf("%d", &num); // num夸脱数
printf("%e\n", num * 950 / 3.0e-23);
return 0;
}
【4】垃圾字符回收
1.通过空格
进行回收
回收一个或多个空格、tab 、\n
char a, b;
scanf("%c %c", &a, &b);
2.%*c
在这里插入代码片
回收任意一个字符
char a, b;
scanf("%c%*c%c", &a, &b);
3.getchar();
一般在循环中用,只能回收一个字符
【5】强制类型转换
int a=5;
float num=(float)5/2;
控制语句
分支语句
【6】if else
基本结构:
if (表达式)
{
语句块1;
}
else
{
语句块2;
}
分层结构:
if (表达式1)
{
语句块1;
}
else if (表达式2)
{
语句块2;
}
else
{
表达式3;
}
嵌套结构:
if (表达式1)
{
if (表达式2)
{
语句块1;
}
else
{
语句块2;
}
}
else
{
语句块3;
}
总结:
1)if后面可以没有else
但是else前面必须有if
2)if else 后面的{}可以省略,但是只能匹配后面的第一条语句。
switch case
基本结构:
switch(变量或表达式)
{
case 常量1: 语句块1;break;
case 常量2: 语句块2;break;
case 常量3: 语句块3;break;
...
case 常量n: 语句块n;break;
default:语句块n+1;
}
执行顺序:
判断switch后面的表达式的结果,和case后面的常量进行匹配,如果
能匹配上就执行对应的语句块,遇到break就结束switch语句,
当case都不匹配时,执行default后面的语句块
注意:
1.表达式不能是浮点类型或者字符串
2.case后面的break可以省略,省略时代码会顺序执行,
直到遇到break结束
练习:从终端输入一个学生的成绩,判断学生成绩,打印成绩级别
【90 - 100】 A
【80 - 89】 B
【70 - 79】 C
【60 - 69】 D
< 60 sorry you lost
#include <stdio.h>
int main()
{
int score;
scanf("%d", &score);
switch (score / 10)
{
case 10:
case 9:
printf("A\n");
break;
case 8:
printf("B\n");
break;
case 7:
printf("C\n");
break;
case 6:
printf("D\n");
break;
default:
printf("sorry you lost\n");
}
return 0;
}
练习:写程序实现功能:读入两个整数(data1和data2)和一个运算符(op),计算表达式data1 op data2 的值.
其中op可以为+、-、*、/四个符号中的任一种(用switch语句实现)
#include <stdio.h>
int main()
{
int data1, data2;
char op;
scanf("%d %c %d", &data1, &op, &data2);
switch (op)
{
case '+':
printf("%d\n", data1 + data2);
break;
case '-':
printf("%d\n", data1 - data2);
break;
case '*':
printf("%d\n", data1 * data2);
break;
case '/':
if (data2 == 0)
{
printf("err\n");
}
else
{
printf("%d\n", data1 / data2);
}
break;
default:
printf("input err\n");
}
return