C语言基础学习 - 初识 C 语言(二)
1. 选择语句
int coding;
printf("你愿意敲代码么? -- 1 愿意 -- 0 不愿意\n");
printf("根据上面提示输入0或1:");
scanf("%d", &coding);
//printf("%d", coding);
if (coding == 1) {
printf("你愿意敲代码.");
}
else if (coding == 0)
printf("你不愿意敲代码.");
else
printf("输入有误!");
== : 判断 左值和右值是否相等
2. 循环语句
循环语句
int num = 1;
//一直执行不中止的循环叫做死循环
// 输出 1 - 10
while (num <= 10) {
//循环体
printf("%d\n", num);
num++;
}
for (int i = 1; i <= 10; i++) {
printf("%d\n", i);
}
while 循环的格式如下面的代码所示, 但是要注意的是 while 循环要有循环结束的条件, 如果循环一直不结束, 就会出现死循环, 比如上面的代码片段, 如果注释掉 num++;
, 那么 num 的值一直是 1, 且 num <= 10
一直成立, 则这个程序一直不会停止.
while (条件表达式){
循环体
}
for 循环和 do while 循环后面会详细再说.
3. 函数
void add();// 函数声明
int mian(){
int num1, num2;
printf("请输入两个整数:");
scanf("%d%d", &num1, &num2);
printf("两个整数的和为:%d\n",num1+num2);
// 函数的调用
add();
}
// 函数的定义
void add() {
int n1, n2;
printf("请输入两个整数:");
scanf("%d%d", &n1, &n2);
printf("两个整数的和为:%d\n", n1 + n2);
}
函数的定义只有一次, 但是调用可以多次.
可以直接定义函数, 函数特点简化代码, 代码复用, 也可以先声明函数, 在main()函数之后定义函数.
4. 数组
数组是将一些变量编制到一个组中;用来存放一组类型相同、意义通常也相同的数据。其中每个数据称为数组的元素,每个元素就是一个变量.数组中的每个元素都有各自的位序,可通过数组名和索引号操作各个元素.长度为 n 的数组索引号范围为 [0, n-1].
4.1 一维数组
定义数组数据类型 变量名[数组大小(可省略)];
数组的初始化有三种方式, 如下面的代码所示:
int s[10] = { 1,2,3,4,5,6,7,8,9,10 };//1. 完全初始化
int s[10] = { 1,2,3,4,5 };//2. 不完全初始化
int s[] = {1,2,3,4,5,6,7,8,9,10}//3. 省略长度的初始化,与完全初始化等价
通过数组名和索引号访问和存取各个数剧元素, 注意, 数组下标是从 0 开始的.
int a = s[1];
#include <stdio.h>
int main(void) {
//一维数组初始化
//int s[10];//定义整型长度为10的数组
//int s[10] = { 1,2,3,4,5,6,7,8,9,10 };//完全初始化
//int s[10] = { 1,2,3,4,5 };//不完全初始化
//int s[] = {1,2,3,4,5,6,7,8,9,10}//省略长度的初始化,与完全初始化等价
//一维数组元素的引用:数组名[下标]
//int a = s[1];
//printf("%d", a);
//将一组整数逆置
int n;//n个整数,n小于40
printf("请输入数组长度: ");
scanf_s("%d", &n);
int a[40];//数组定义
printf("数组为:");
for (int i = 0; i < n; i++)//数组元素赋值
scanf_s("%d", &a[i]);
for (int j = 0; j < n / 2; j++) {//交换元素
int temp = a[j];
a[j] = a[n - j - 1];
a[n - j - 1] = temp;
}
for (int k = 0; k < n; k++) {//循环输出元素
printf("%d ", a[k]);
}
return 0;
}
结果:
4.2 二维数组
C语言二维数组的存储是按行优先存储的
定义 初始化 通过数组名和索引号操作各个元素输入及输出.
#include <stdio.h>
int main(void) {
//二维数组的定义及其初始化;
//double a[2][3];//定义了2个一维数组,每个一维数组有三个元素;
//int b[2][3] = { 1,2,3,4,5,6 };//按行连续赋值
//int c[3][2] = { {1,2},{3,4},{5,6} };//按行分段赋值
//int d[3][3] = { 1,2,3 };//可以对部分元素赋值,未赋值的元素自动取0值
//int e[][2] = {1,2,3};//第一维长度可以不给出
//输入二维数组元素
int f[2][3];
printf("输入二维数组元素:");
for (int i = 0; i < 2; i++)
for (int j = 0; j < 3; j++)
scanf_s("%d", &f[i][j]);
//输出二维数组元素
printf("输出二维数组元素:");
for (int i = 0; i < 2; i++)
for (int j = 0; j < 3; j++)
printf("%d ", f[i][j]);
return 0;
}
结果:
由于程序中定义的二位数组是2行3列,所以输入的多出来的在输出时会自动忽略.
5. 操作符
操作符名称 | |
---|---|
算术操作符 | +, -, * , /, % |
移位操作符 | >> , << |
位操作符 | &, ^, | |
赋值操作符 | =, +=, -=, *=, /=, &=, ^=, |=, >>=, <<= |
单目操作符 | ! , ~, -, +, &, sizeof, --, ++, *, (类型) |
关系操作符 | >, >=, <, <=, !=, == |
逻辑操作符 | &&, || |
条件操作符 | exp1 ? exp2 : exp3 |
逗号表达式 | exp1, exp2, exp3, … , expN |
下标引用,函数调用,结构成员 | [], (), ., -> |
6. 关键字
C语言中的关键字如下所示:
auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while
6.1 typedef
typedef 顾名思义是类型定义,这里应该理解为类型重命名。
//将unsigned int 重命名为 uint , 所以 uint 也是一个类型名
typedef unsigned int uint;
int main(){
unsigned int x = 10;// 表示 x 是一个无符号整数
uint y =20;// 使用了 typedef, 语句变得更加简洁
return 0;
}
6.2 static
static 是用来修饰变量和函数的
1. 修饰局部变量-称为静态局部变量
2. 修饰全局变量-称为静态全局变量
3. 修饰函数-称为静态函数
6.2.1 修饰局部变量
void func() {
int num = 0;
num = num + 1;
printf("%d\n", num);
}
int main(){
func();
func();
return 0;
}
上面这段代码的结果是全 1, 但是当我们在定义 num 是使用 static 修饰变量, 打印的内容会有哪些变化呢?
static int num = 0;
结果如图所示:
在上面的代码中, static 修饰局部变量, 改变了变量的声明周期, num 的生命周期跟随了整个程序, 不影响变量的作用域.
6.2.1 修饰全局变量
在 test01.c
// 变量的定义
int global = 10;
在 test02.c 中想要访问同一项目其他源文件的全局变量, 需要使用关键字 extern.
// 变量的声明
extern int global;
int main(){
// 可以直接在主函数使用 global 变量
return 0;
}
如果我们将 test01.c 中的全局变量使用关键字 static 修饰, 那么在 test02.c 中就会提示错误, 因为被 static 修饰的全局变量的作用域被修改, 只在当前文件中有效果, 其他文件无法应用.
6.2.3 修饰函数
在 test01.c
// 函数的定义
int add() {
int n1, n2;
printf("请输入两个整数:");
scanf("%d%d", &n1, &n2);
printf("两个整数的和为:%d\n", n1 + n2);
return 0;
}
在 test02.c 中想要访问同一项目其他源文件的函数, 需要使用关键字 extern.
// 函数的声明
extern int add();
int main(){
// 可以直接在主函数调用函数 add()
add();
return 0;
}
如果我们将 test01.c 中的函数使用关键字 static 修饰, 那么在 test02.c 中就会提示错误, 因为被 static 修饰的函数的作用域被修改, 只在当前文件中有效果, 其他文件无法应用.
7. #define 定义常量和宏
下面的语句可以代替上面的 add() 函数, 一定程度上可以替代, 也不是所有的都可以替代, 剩余有关的内容会在后面详细说.
#denfine ADD(x, y) x + y
8. 指针
内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的。
所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址.
变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。取出变量地址如下:
//指针
int x = 10;
//创建了一个指针变量p,p的类型叫做 int*
int* p = &x;
printf("%d\n", *p);
printf("%p\n", p);// p 存储的是 x 变量的地址
p
: 指针变量, 类型是 int*
&x
: 取 x 变量的地址
printf("%d\n", \*p);
此语句中的 * 叫做间接访问操作符 / 解引用操作符,
%p
用来打印指针变量, 无符号十六进制整数
9. 结构体
结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。
比如描述学生,学生包含:名字+年龄+性别+学号这几项信息。
这里只能使用结构体来描述了。如下面的代码片断所示:
enum Sex {
female,
male,
unknow
};
struct Student {
char name[20];// 字符数组表示字符串
int age;
enum Sex sex;// 枚举
int id;
};
C语言中常用字符数组表示字符串
创建类型变量
struct Student stu = {
"CY",
22,
male,
2020123
};
打印 数据
printf("%s\n", stu.name);
printf("%d\n", stu.id);
.: 成员访问操作符
%s: 打印字符串
打印结果如下:
修改数据
修改结构体变量成员值
修改 id, 如下所示:
stu.id = 200;//整数型可以直接修改
printf("%d\n", stu.id);
修改 name: 修改字符串时需要调用 strcpy() 函数, 不能直接进行修改, 代码片段如下所示:
// 不能直接修改
// stu.name = "XY"; // 错误
strcpy(stu.name, "XY");