C 语言

First Post:

Last Update:

概述

C 语言是一个中等级语言, 在机器语言和汇编语言之上, 在其他高级语言之下
大部分语言的编译器的内核都是用 C 构建的 (例: python, java, C#, C++, js)


  • C 语言不是面向对象的编程语言
  • C++是 C 语言的扩展

C 语言对初学者还挺难的(¬‿¬)


开始

stdio.h 包含一些关于输入输出的函数

1
2
3
4
5
6
7
// 预处理命令, 告诉编译器包含哪些文件
#include <stdio.h>

// main函数 程序入口点
int main(){
return 0;
}

在命令行中使用编译器

1
gcc "源码文件" -o '输出文件名'

注释

1
2
3
4
5
6
/**
* 多行
* 注释
*/

// 单行注释

变量

  • signed 有符号数据 (默认数据)
  • unsigned 指代无符号数据
  • short 短数据
  • long 长数据 (默认数据)
  • long long 长长数据

要使用变量类型 bool 需要引入 stdbool.h 头文件

1
#include <stdbool.h>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int x = 123;
int y = 321;

int age = 22; // 4 bytes (-2147483648 ~ 2147483647)
float gpa = 2.05; // 4 bytes
char grade = 'C'; // 1 byte (-128 ~ 127) %d
char name[] = "Bro"; // 字符串

// 还有更多数据类型
double d = 3.141592653589793; // 8 bytes
bool b = true; // 1byte (true false) %d

unsigned char g = 255; // 1 byte (0 ~ 255) %d

short int h = 32767; // 2 bytes (-32768 ~ 32768) %d
unsigned short int i = 65535; // 2 bytes (0 ~ 65535) %u

long int l; // 4 bytes 默认状态下, 这些就是 long 数据, 不需显式输入
long long int ll = 4656454654654654654654546U; // 8 bytes 记得在最后加个U, 否则编译器会发出warning

格式化输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 标志(flag) "-", "+", "0", ","
// - :左对齐
// + :输出正负符号
// 0 :用0填充数字
// , :数字大于1000, 用","隔开
% <标志> <宽度> <精度> <格式化类型>

// 精度 .2 显示后两位

float f = 3.1415;
long long int ll;

// 例:
printf("float: %f", f);
printf("long long data: %lld", ll);
Type 格式化
unsigned %u
long %l
int %d
float %f
double %lf
char %c
char[] %s
% %%

常量, 常量在程序中不可改变

1
2
// 常量一般用大写字母表示
const float PI = 3.14159;

用户输入

  • scanf 不会读取空格
  • fgets

注: & 为取地址符

1
2
3
4
5
6
7
8
// 获取用户输入的函数
// scanf(格式化字符串, 变量地址)
scanf("%d", &age);

// fgets(变量名, 数值大小, stdin);
// 这样获取字符串会把 \0 获取下来
// \0: 字符串结束符
fgets(name, 25, stdin);
1
2
3
4
#include <string.h>

// 获取字符串长度
strlen()

数学运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <math.h>

sqrt(9); // 开方 9的开方
pow(2, 4); // 幂运算 2的4次方

round(3.14); // 四舍五入
ceil(3.14); // 向上取整
floor(3.14); // 向下取整
fabs(-100); // 取绝对值

log(3); // 对数运算 以2为根, 3的对数

// 三角函数
sin(45);
cos(45);
tan(45);

流程控制

if 语句好像没什么说的…

1
2
3
4
5
6
7
8
9
if (true){
// code ...
}
else if(false) {
// code ...
}
else{
// code ...
}

switch 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
int choice;

switch (choice){
case 1:
// code ...
break;
case 2:
// code ...
break;
default:
//code ...
}


逻辑运算符

  • &&
  • ||
  • !

三元运算符

1
2
3
4
5
int min;
int max;
int result;

result = (max > min) ? max : min;

函数

1
2
3
4
5
6
7
8
9
10
11
// 无参函数
void myFunction(){
printf("I'm function!");
}

int main(){
// 调用函数
myFunction();

return 0;
}

参数:

1
2
3
4
// 变量会在参数处声明
void myFunction(int num){
printf("I'm function! and my argument is %d", num);
}

原型函数, 是一个函数声明, 在主函数之前的没有函数体的函数

该函数的主要作用是确保函数的参数正确(让编译器不忽略错误的传参)


字符串函数

要使用字符串函数, 需包含 string.h 头文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<string.h>

char string1[] = "Hi";
char string2[] = "my name is voilone";

// 将字符转换为大小写
strlwr();
strupr();

strcat(sring1, string2); // 将两个字符拼接, 结果会返回个string2

strcopy(string1, string2); // 将string2 复制到 string1
strncopy(string1, string2, n); //将 string2 的 n 个字符复制到 string1

strset(string1, '?'); // 将所有字符换为指定的字符
strnset(string1, '?', 1) // 将 n 个字符换为指定的字符
strrev(string1); // 反转字符串
1
2
3
4
5
6
7
strlen(); // 获取字符串长度

strcmp(); // 对比字符串, 如果相同, 返回0, 否则是其他数字
strncmp(); // 对比 n 个字符串

strcmpi(); // 对比所有字符串, 忽略字符串大小写
strnicmp() // 对比 n 个字符串, 忽略字符串大小写

循环

  • continue 跳过一个循环
  • break 跳出整个循环

for 循环

1
2
3
for (int i; i < 10; i++){

}

while 循环

1
2
3
while (true){

}

do while 循环

1
2
3
4
5
6
7
8
9
#include<stdbool.h>

bool judge = false;

do{
judge = true;
}while (judeg){
// code ...
}

数组

1
2
3
4
5
6
7
8
9
10
// 声明 一
double prices[3] = {2.2, 5.5, 6.6};

// 声明 二
int nums[2];
nums[0] = 1;
nums[1] = 2;

// 访问
prices[0];
1
2
3
4
int array[] = {1, 2, 3}

// 获取数组长度
sizeof(array)

二维数组

1
2
3
4
5
// 二维数组
int numbers[2][3] = {
{1, 2, 3},
{2, 3, 3}
};

字符串数组

1
2
3
4
5
6
#include <string.h>

char chars[][20] = {"hello", "This char array"};

// 替换数组中的字符串
strcopy(chars[0], "New string~");

struct 数据集合

struct 结构体

struct 是一些数据的集合, 每个单一的数据被称为: “成员(member)”

1
2
3
4
5
6
7
8
9
10
11
12
// 声明结构体
struct Player{
char name[12];
int score;
}

struct Player player1;
struct Player player2;

// 访问结构体, 并对其赋值
strcopy(player1.name, "voilone");
player1.score = 55;

struct 数组

1
2
3
4
5
6
7
8
9
10
struct Student{
char name[12];
float gpa;
}

struct Student student1 = {"voilone", 3.0};
struct Student student2 = {"sam", 2.0};
struct Student student3 = {"xv", 4.0};

struct Student students[] = {student1, student2, student3};

typedef

typedef 可以给关键字一个别称

1
2
3
4
// 别称 user
typedef char user[25]

user user1[25] = "voilone";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 不使用 typedef
struct User{
char name[25];
char password[12];
int id;
}

struct User user1 = {"voione", "654321", 666};

//------------------------------------------

// 使用 typedef
typedef struct {
char name[25];
char password[12];
int id;
} User;

User user2 = {"voione", "654321", 666};

enmu 枚举类型

一种用户自定义命名的整数数据, 使其代码更有可读性

1
2
3
4
5
6
enum Day{Sun = 1, Mon = 2, Tue = 3, Wed = 4, Thu = 5, Fri = 6, Sat = 7};

enum Day today = Sun;

// 打印结果: Today is 1
printf("Today is %d", today)

位运算符

  • &
  • |
  • ^
  • <<
  • >>

内存地址

  • memory 一个字节数组
  • memory block 一个单元的内存(byte), 用于储存数据
  • memory address 内存块的地址

& 取地址符

1
2
3
4
5
6
7
8
9
10
char a = 'X';
char b = 'Y';
char c = 'Y';

// 打印变量大小
printf("%d bytes", sizeof(a));

// 打印内存地址, %p
// 打印出的内存地址用16进制表示
printf("%p", &a)

指针

pointer 指针保存一个变量的内存地址
* 为解引用操作符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int age = 21;

// 使用 "*" 储存内存地址
// p: pointer
int *pAge = &age;

printf("address: %p", &age);
prinft("pAge value: %p", pAge);

printf("value: %d", age);
printf("pAge point to value %d", *pAge) // 解引用

// 也可采用NULL来声明指针
int *pAge2 = NULL;
pAge2 = &age;

函数与指针

1
2
3
void printAge(int *pAge){
printf("you are %d olds", *pAge);
};

其他

随机数

要生成随机数, 需要包含 stdlib.h 头文件

1
2
3
4
5
6
7
8
#include <stdlib.h>

// 随机数的生成前置条件
// ?
srand(time(0));

// rand() 函数 随机返回 0 ~ 32767 的整数
int number1 = (rand() % 6) + 1;

文件 cz

fopen(path, mode) 模式:

  • w 覆盖写入
  • a 添加
  • r 读取

检测是否存在文件:

1
2
3
FILE *pF = fopen("test.txt", "r");

if (pF == NULL) printf("No such file!");

写入文件

1
2
3
4
5
6
7
8
9
// 写入数据
// fopen("文件路径", 模式)
FILE *pF = fopen("test.txt", "w");

// 写入数据
fprintf(pF, "some fromat text");

// 关闭文件
fclose(pF);

文件删除:

1
2
// 成功删除, 返回 0
remove("test.txt");

读取文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
FILE *pF = fopen("test.txt"), "r";

// 声明缓冲区
char buffer[255];

// 读取单行文本
// fget(缓冲区, 最大大小, 文件地址)
fget(buffer, 255, pF);

// 读取多行
//! 注意, 此处为fgets()
while (fgets(buffer, 255, pF) != NULL){
printf("%s", buffer)
}