关于C语言的各类知识点汇总—复习第一天

基础语法

基本数据类型

整型(int):用于表示整数,通常占用 4 个字节。

短整型(short int):占用的字节数比 int 少。

长整型(long int):占用的字节数比 int 多。

无符号整型(unsigned int):只能表示非负整数

浮点型(float、double):用于表示实数。

float 通常占用 4 个字节,精度较低。

double 通常占用 8 个字节,精度较高。

字符型(char):用于表示单个字符,占用 1 个字节。

变量与常量

变量:在程序运行过程中可以改变其值的量。

变量的定义:数据类型 变量名;
例如

int a;

变量的初始化:可以在定义变量的同时为其赋值,
例如

int a = 10;

常量:在程序运行过程中其值不能改变的量。

字面常量:如整数常量 10、浮点数常量 3.14、字符常量 ‘A’ 等。

符号常量:使用 #define 定义的常量,
例如

 #define PI 3.14。

运算符

算术运算符:+(加)、-(减)、*(乘)、/(除)、%(取余)。

关系运算符:>(大于)、<(小于)、>=(大于等于)、<=(小于等于)、==(等于)、!=(不等于)。

逻辑运算符:!(非)、&&(与)、||(或)。

赋值运算符:=、+=、-=、*=、/=、%= 等。

其他运算符:sizeof(计算变量或类型的大小)、&(取地址)、*(指针解引用)等。

表达式

由运算符和操作数组成的式子称为表达式。
例如 a + b、a > b 等都是表达式。

输入输出

printf函数:用于输出信息到控制台。
例如

printf("Hello, World!");。

scanf函数:用于从控制台读取用户输入。
例如:

scanf("%d", &a);

其中 &a 表示变量 a 的地址。

控制结构

条件语句

if语句
语法:

if(表达式) {语句块}。

如果表达式的值为真,则执行语句块中的内容。
例如:

if(a > b) {printf("a 大于 b");}。

if-else语句
语法:if(表达式) {语句块 1} else {语句块 2}。如果表达式的值为真,则执行语句块 1,否则执行语句块 2。
例如:

if(a > b) {printf("a 大于 b");} else {printf("a 不大于 b");}。

if-else if-else语句
用于多条件判断。语法:if(表达式 1) {语句块 1} else if(表达式 2) {语句块 2}… else {语句块 n}。依次判断表达式的值,当某个表达式为真时,执行对应的语句块。
例如:

if(a > b) {printf("a 大于 b");} else if(a < b) {printf("a 小于 b");} else {printf("a 等于 b");}。

switch-case语句
语法:switch(表达式) {case 常量表达式 1: 语句块 1; break; case 常量表达式 2: 语句块 2; break;… default: 语句块 n;}。根据表达式的值与各个 case 后的常量表达式进行匹配,执行匹配成功的语句块。
例如:

switch(grade) {case 'A': printf("优秀"); break; case 'B': printf("良好"); break; case 'C': printf("中等"); break; case 'D': printf("及格"); break; default: printf("不及格");}。

循环语句

for循环
语法:for(初始化表达式; 条件表达式; 更新表达式) {语句块}。先执行初始化表达式,然后判断条件表达式,如果为真,则执行语句块,接着执行更新表达式,重复这个过程直到条件表达式为假。
例如:

for(int i = 0; i < 10; i++) {printf("%d ", i);}。

while循环
语法:while(表达式) {语句块}。当表达式的值为真时,重复执行语句块。
例如:

int i = 0; while(i < 10) {printf("%d ", i); i++;}。

do-while循环
语法:do {语句块} while(表达式);。先执行语句块,然后判断表达式的值,如果为真,则继续执行语句块,直到表达式为假。
例如:

int i = 0; do {printf("%d ", i); i++;} while(i < 10);。

控制结构的嵌套

可以在条件语句和循环语句中嵌套其他的控制结构,以实现更复杂的逻辑。
例如:

for(int i = 0; i < 10; i++) {
if(i % 2 == 0) {
    printf("%d 是偶数\n", i);
} else {
    printf("%d 是奇数\n", i);
}

}

跳转语句

break语句:用于跳出循环或 switch 语句。

continue语句:用于结束本次循环,开始下一次循环。

goto语句:可以无条件地跳转到程序中的指定位置,但不建议使用,因为它会使程序的结构变得混乱。

函数

函数的定义

语法:

		返回值类型 函数名(参数列表) {函数体}

返回值类型:指定函数返回值的数据类型。如果函数不返回任何值,则为 void。

函数名:用于标识函数的名称,遵循标识符的命名规则。

参数列表:可以包含零个或多个参数,每个参数由参数的数据类型和参数名组成。参数用于在函数调用时传递数据给函数。

函数体:包含函数执行的具体语句。

示例:

   int add(int a, int b) {
   return a + b;
 }

这个函数名为 add,接受两个整数参数 a 和 b,并返回它们的和。

函数的调用

语法:

	对于有返回值的函数:变量 = 函数名(参数列表);
	
	对于无返回值的函数:函数名(参数列表);

示例:

	  int main() {
  		 int result = add(3, 5);
  		 printf("3 + 5 = %d\n", result);
   return 0;

}
在 main 函数中,调用 add 函数并将返回值赋给 result 变量,然后输出结果。

参数传递

值传递:在 C 语言中,默认情况下参数是按值传递的。这意味着函数接收的是参数的副本,对参数的修改不会影响到原始变量。

地址传递(指针传递):通过传递变量的地址,可以在函数中修改原始变量的值。

函数的返回值

返回值类型:函数可以返回各种数据类型的值,包括整数、浮点数、字符、指针等。如果函数不需要返回值,则返回值类型为 void。

返回语句:使用 return 语句将值返回给调用者。如果函数的返回值类型不是 void,则函数必须有一个 return 语句。

函数的声明

作用:在使用函数之前,需要对函数进行声明,告诉编译器函数的名称、参数列表和返回值类型。这样编译器才能在编译过程中正确地识别函数的调用。

语法:

   返回值类型 函数名(参数列表);

示例:

  int add(int a, int b);

 int main() {
   int result = add(3, 5);
   return 0;
 }

  int add(int a, int b) {
   return a + b;
}

在 main 函数之前声明了 add 函数,这样编译器在编译 main 函数时就知道 add 函数的存在。

函数的递归

概念:函数可以直接或间接地调用自身,这就是递归。递归通常用于解决可以分解为相同子问题的问题。
示例:计算阶乘的递归函数。

 int factorial(int n) {
   if (n == 0 || n == 1) {
       return 1;
   } else {
       return n * factorial(n - 1);
   }
 }

库函数

C 语言提供了许多标准库函数,可以在程序中直接使用。

使用库函数时,需要包含相应的头文件。

嵌套函数

函数的嵌套调用是指在一个函数的内部调用另一个函数。

#include 

// 定义函数 func1
void func1() {
printf("This is func1.\n");
}

// 定义函数 func2
void func2() {
printf("This is func2 before calling func1.\n");
func1(); // 在 func2 中调用 func1
printf("This is func2 after calling func1.\n");
}

// 定义主函数
int main() {
printf("This is main before calling func2.\n");
func2(); // 在 main 中调用 func2
printf("This is main after calling func2.\n");
return 0;
}

数组和指针

数组

定义:数组是一组相同类型元素的集合,这些元素在内存中是连续存储的。

例如:

int arr[5];

定义了一个包含 5 个整数的数组。
初始化:
可以在定义数组时进行初始化,例如

	int arr[5] = {1, 2, 3, 4, 5};。

也可以部分初始化,未初始化的元素会被自动初始化为 0。例如

int arr[5] = {1, 2};

此时arr[2]、arr[3]和arr[4]的值为 0。

访问数组元素:通过下标来访问数组元素,下标从 0 开始。例如arr[0]表示数组的第一个元素。

数组的大小:可以使用sizeof运算符来获取数组的大小(以字节为单位),然后除以单个元素的大小来得到数组的元素个数。例如

int arr[5]; 
int size = sizeof(arr) / sizeof(arr[0]);,

这里size的值为 5。

指针

定义:指针是一个变量,它存储了另一个变量的地址

例如:

int *ptr;

定义了一个指向整数的指针。

初始化:可以将一个变量的地址赋值给指针,
例如

int num = 10; int *ptr = #,

这里&num表示变量num的地址。

也可以将数组名赋值给指针,因为数组名本身就是一个指向数组第一个元素的指针。
例如

int arr[5]; int *ptr = arr;。

解引用指针:通过在指针前加上**星号(*)**来访问指针所指向的变量的值。例如

int num = 10; int *ptr = # printf("%d", *ptr);

会输出 10。

指针的运算
指针可以进行加法和减法运算,指针加上或减去一个整数 n,表示指针向前或向后移动 n 个元素的位置。
ptr指向一个整数,ptr + 1指向数组中的下一个整数。
两个指针可以相减,得到它们之间的元素个数。
ptr1和ptr2指向同一个数组中的两个元素,ptr2 - ptr1表示它们之间的元素个数。

数组与指针的关系

数组名是一个指向数组第一个元素的指针:例如

int arr[5]; int *ptr = arr;

这里arr和ptr都指向数组的第一个元素。
可以使用指针来访问数组元素
ptr指向一个数组的第一个元素,那么*(ptr + i)表示数组的第 i 个元素,与arr[i]是等价的。
数组作为函数参数时会退化为指针:当数组作为函数参数传递时,实际上传递的是数组的首地址,也就是一个指针。
例如:

   void printArray(int arr[], int size) {
   for (int i = 0; i < size; i++) {
       printf("%d ", arr[i]);
   }
  }

  int main() {
   int arr[5] = {1, 2, 3, 4, 5};
   printArray(arr, 5);
   return 0;
 }	

在这个例子中,函数printArray的参数arr实际上是一个指针,它指向数组的第一个元素。

结构体和联合体

结构体(struct)

定义:
结构体是一种用户自定义的数据类型,它可以包含不同类型的成员变量。
语法:

struct 结构体名 {成员列表};。

例如:

struct Student {char name[20]; int age; float score;};

定义了一个名为Student的结构体,包含三个成员变量:一个字符数组name表示学生的姓名,一个整数age表示学生的年龄,一个浮点数score表示学生的成绩。

初始化:可以在定义结构体变量的同时进行初始化。
例如:

struct Student stu = {"Tom", 18, 90.5};。

也可以使用结构体成员访问运算符(.)逐个初始化成员变量
例如:

struct Student stu; strcpy(stu.name, "Tom"); stu.age = 18; stu.score = 90.5;。

**访问成员变量:**使用结构体成员访问运算符(.)来访问结构体变量的成员变量。
例如:

printf("Name: %s, Age: %d, Score: %.2f", stu.name, stu.age, stu.score);。

**结构体数组:**可以定义结构体数组来存储多个结构体变量。
例如:

struct Student students[3];

//定义了一个包含三个Student结构体变量的数组。

可以使用循环来初始化和访问结构体数组的元素
例如:

  for (int i = 0; i < 3; i++) {
     strcpy(students[i].name, "Student");
     students[i].age = i + 18;
     students[i].score = (i + 1) * 80.5;
 }
 for (int i = 0; i < 3; i++) {
     printf("Name: %s, Age: %d, Score: %.2f\n", students[i].name, students[i].age, students[i].score);
 }

**结构体指针:**可以定义结构体指针来指向结构体变量。
例如:

struct Student *p = &stu;

定义了一个指向stu结构体变量的指针p。
使用结构体指针访问成员变量时,需要使用间接成员访问运算符(->)。例如:

printf("Name: %s, Age: %d, Score: %.2f", p->name, p->age, p->score);。

联合体(union)

定义:联合体是一种特殊的结构体,它的所有成员变量共享同一块内存空间。

语法:

union 联合体名 {成员列表};。

例如:

union Data {int i; float f; char c;};

定义了一个名为Data的联合体,包含三个成员变量:一个整数i、一个浮点数f和一个字符c。

初始化:联合体只能初始化其中的一个成员变量。
例如:

union Data data = {.i = 10};

初始化了联合体的整数成员变量i为 10。

访问成员变量:可以使用联合体成员访问运算符(.)来访问联合体的成员变量。但是,由于联合体的所有成员变量共享同一块内存空间,所以在同一时间只能访问其中的一个成员变量。
例如:

 union Data data;
 data.i = 10;
 printf("Integer value: %d\n", data.i);
 data.f = 3.14;
 printf("Float value: %.2f\n", data.f);
 data.c = 'A';
 printf("Character value: %c\n", data.c);

联合体的大小:联合体的大小等于其最大成员变量的大小。因为联合体的所有成员变量共享同一块内存空间,所以联合体的大小取决于其中最大的成员变量所需的内存空间。

文件操作

文件的打开与关闭

文件指针:在 C 语言中,使用文件指针(FILE 类型)来表示一个打开的文件。文件指针指向一个包含文件信息的结构体,通过这个结构体可以对文件进行各种操作。

打开文件:使用fopen函数打开一个文件。
语法:

FILE *fopen(const char *filename, const char *mode);

其中,filename是要打开的文件名,mode是打开文件的模式。
常见的打开模式有:
“r”:以只读方式打开文件。如果文件不存在,则打开失败。
“w”:以只写方式打开文件。如果文件不存在,则创建一个新文件;如果文件存在,则清空文件内容。
“a”:以追加方式打开文件。如果文件不存在,则创建一个新文件;如果文件存在,则在文件末尾追加内容。
“r+”:以读写方式打开文件。如果文件不存在,则打开失败。
“w+”:以读写方式打开文件。如果文件不存在,则创建一个新文件;如果文件存在,则清空文件内容。
“a+”:以读写方式打开文件。如果文件不存在,则创建一个新文件;如果文件存在,则在文件末尾追加内容。
例如:

FILE *fp = fopen("test.txt", "r");

打开一个名为test.txt的只读文件。

关闭文件:使用fclose函数关闭一个打开的文件。语法:int fclose(FILE *stream);。其中,stream是要关闭的文件指针。
例如:

fclose(fp);

关闭文件指针fp所指向的文件。

文件的读写操作

字符读写
fgetc函数:从文件中读取一个字符。
语法:

int fgetc(FILE *stream);。

返回值是读取的字符,如果到达文件末尾或发生错误,则返回EOF
fputc函数:向文件中写入一个字符。
语法:

int fputc(int c, FILE *stream);

其中,c是要写入的字符。返回值是写入的字符,如果发生错误,则返回EOF。
例如:

 FILE *fp = fopen("test.txt", "r");
 char ch;
 while ((ch = fgetc(fp))!= EOF) {
     putchar(ch);
 }
 fclose(fp);

这段代码从文件test.txt中读取字符并输出到屏幕上。

字符串读写
fgets函数:从文件中读取一行字符串。
语法:

char *fgets(char *str, int n, FILE *stream);

其中,str是存储读取字符串的字符数组,n是最多读取的字符数,stream是文件指针。返回值是指向str的指针,如果到达文件末尾或发生错误,则返回NULL。

fputs函数:向文件中写入一行字符串。
语法:

int fputs(const char *str, FILE *stream);

其中,str是要写入的字符串,stream是文件指针。返回值是写入的字符数,如果发生错误,则返回EOF。
例如:

FILE *fp = fopen("test.txt", "r");
 char str[100];
 while (fgets(str, 100, fp)!= NULL) {
     fputs(str, stdout);
 }
 fclose(fp);

这段代码从文件test.txt中读取字符串并输出到屏幕上。

格式化读写

fscanf函数:从文件中读取格式化数据。
语法:

int fscanf(FILE *stream, const char *format,...);

其中,stream是文件指针,format是格式化字符串,后面是可变参数列表,用于存储读取的数据。返回值是成功读取的数据项数,如果到达文件末尾或发生错误,则返回EOF。

fprintf函数:向文件中写入格式化数据。
语法:

int fprintf(FILE *stream, const char *format,...);

其中,stream是文件指针,format是格式化字符串,后面是可变参数列表,用于指定要写入的数据。返回值是写入的字符数,如果发生错误,则返回负数。
例如:

 FILE *fp = fopen("test.txt", "w");
 int num = 10;
 float fnum = 3.14;
 char str[] = "Hello";
 fprintf(fp, "%d %f %s", num, fnum, str);
 fclose(fp);

 fp = fopen("test.txt", "r");
 int n;
 float fn;
 char s[100];
 fscanf(fp, "%d %f %s", &n, &fn, s);
 printf("%d %f %s", n, fn, s);
 fclose(fp);

这段代码将一个整数、一个浮点数和一个字符串写入文件,然后从文件中读取并输出到屏幕上。

文件的定位操作

ftell函数:返回文件指针当前的位置。
语法:

long int ftell(FILE *stream);

返回值是文件指针当前的位置,如果发生错误,则返回-1L。

fseek函数:移动文件指针到指定的位置。
语法:

int fseek(FILE *stream, long int offset, int whence);

其中,stream是文件指针,offset是偏移量,whence是起始位置。whence可以是以下三个值之一:
SEEK_SET:文件开头。
SEEK_CUR:当前位置。
SEEK_END:文件末尾

例如:

fseek(fp, 10L, SEEK_SET);

将文件指针移动到文件开头往后 10 个字节的位置。

rewind函数:将文件指针移动到文件开头。
语法:

void rewind(FILE *stream);

例如:

rewind(fp);

将文件指针移动到文件开头。

文件的错误处理

ferror函数:检查文件操作是否发生错误。
语法:

int ferror(FILE *stream);

如果文件操作发生错误,则返回非零值;否则返回零。

clearerr函数:清除文件错误标志。
语法:

void clearerr(FILE *stream);。

例如:

 FILE *fp = fopen("test.txt", "r");
 if (fp == NULL) {
     perror("Error opening file");
     return 1;
 }
 char ch;
 while ((ch = fgetc(fp))!= EOF) {
     if (ferror(fp)) {
         perror("Error reading file");
         clearerr(fp);
         break;
     }
     putchar(ch);
 }
 fclose(fp);

这段代码在读取文件时检查是否发生错误,如果发生错误,则输出错误信息并清除错误标志。

你可能感兴趣的:(c语言,算法,开发语言)