当前位置: 首页 > news >正文

C语言基础知识理论版(很详细)

文章目录

  • 前述
  • 一、数据
    • 1.1 数据类型
    • 1.2 数据
      • 第一种数据:常量
      • 第二种数据:变量
      • 第三种数据:表达式
        • 1、算术运算符及算术表达式
        • 2、赋值运算符及赋值表达式
        • 3、自增、自减运算符
        • 4、逗号运算符及其表达式(‘顺序求值’表达式)
        • 5、强制类型转换(显式转换)
        • 6、隐式转换
      • 第四种数据:函数
    • 1.3 标识符
  • 二、顺序结构
    • 2.1 什么是顺序结构
    • 2.2 printf()输出函数
    • 2.3 scanf()输入函数
    • 2.4 字符类型数据的输入输出专属函数
  • 三、选择结构(也叫分支结构)
    • 3.1 两类表达式
      • (1)关系运算符及关系表达式
      • (2)逻辑运算符与逻辑表达式
    • 3.2 if语句
    • 3.3 switch语句
  • 四、循环结构
    • 格式1——while语句
    • 格式2——do while语句
    • 格式3——for语句
    • 两个控制语句——break continue
    • 例题
  • 五、数组
    • 5.1 一维数组的定义和引用(只有一个下标)
      • 1、一维数组的定义格式:
      • 2、一维数组元素的引用格式:
      • 3、一维数组的初始化
    • 5.2 二维数组的定义和引用(有两个下标)
      • 1、二维数组的定义格式:
      • 2、二维数组的引用
      • 3、二维数组的初始化
    • 5.3 字符数组
      • 1、字符数组的初始化
      • 2、字符串
      • 3、字符串使用
        • (1)字符串存储(赋值)四种方法
        • (2)字符串函数
  • 六、函数
    • 6.1 函数定义
    • 6.2 函数调用的两种方式
    • 6.3 函数使用例题分析
  • 七、在函数中的变量
    • 7.1函数的定义与使用
    • 7.2 变量的三个属性
      • 1、变量类型
      • 2、作用范围
      • 3、存储类别
  • 八、预编译命令
    • 8.1 预编译命令
    • 8.2 宏
      • 1、第一种:无参宏定义
      • 2、第二种:带参宏定义
  • 九、指针
    • 9.1 指针变量定义
      • 1、定义的格式:
      • 2、指针变量的引用
    • 9.2 指向数组的指针变量
      • 1、指向数组元素的指针变量
      • 2、指向一维数组的指针变量
    • 9.3 指向多维数组的指针变量
      • 1、指向多维数组元素的指针变量
      • 2、指向由m个元素组成的一维数组的指针变量
    • 7.4 指向字符串指针的指针变量
    • 7.5 指向函数的指针变量
    • 7.6 返回指针的参数
    • 7.7 指针数组和指向指针的指针变量
      • 1、若一个数组的所有元素均为指针类型(地址),则称为指针数组。
    • 7.8 空指针
  • 九、构造类型
    • 9.1 结构体类型
      • 1、构造结构体类型
      • 2、定义结构体变量
      • 3、结构体变量的初始化及引用】】使用结构体变量、结构体数组、结构体指针变量
    • 9.2 共用体类型
      • 1、共用体变量的定义
      • 2、共用体变量的引用
    • 9.3 typedef
  • 十、位运算与文件
    • 10.1 位运算
      • 1、按位与运算(&)
      • 2、按位或运算(|)
      • 3、按位异或运算(^)
      • 4、按位取反运算(~)
      • 5、按位左移运算符(<<)
      • 6、按位右移运算符(>>)
    • 10.2 文件
      • 1、文件概念
      • 2、文件的打开与关闭
      • 3、文件的读写
      • 4、文件当前位置读写函数

前述

C语言是一门编程语言,在大学中很多专业都会学习,考研中部分专业会有涉及,工作中也仍有应用。

以下是chatgpt对c语言的简单介绍:

C语言是一种广泛应用于系统编程和应用程序开发的高级编程语言。以下是对C语言的简单介绍:

  1. 发展历史:C语言由贝尔实验室的Dennis Ritchie在20世纪70年代初开发而成。它是基于早期的B语言,并在其基础上进行了改进和扩展。

  2. 特点和优势

    • 简洁而高效:C语言提供了简洁而高效的语法结构,使得程序编写和阅读相对容易。它具有较少的语法规则和关键字,使得程序员可以更自由地控制代码的行为。
    • 高度可移植性:C语言编写的程序可以在不同的计算机平台上进行编译和运行,具有较高的可移植性。这使得C语言成为系统级编程和跨平台开发的首选语言之一。
    • 强大的底层控制能力:C语言提供了丰富的底层控制能力,可以直接访问内存和硬件资源。这使得C语言在系统编程、驱动程序开发和嵌入式系统等领域得到广泛应用。
    • 丰富的函数库:C语言拥有丰富的标准函数库和第三方函数库,可以方便地进行各种操作,如文件处理、字符串处理、数学计算等。
  3. 应用领域:C语言广泛应用于系统编程、嵌入式系统开发、驱动程序开发、操作系统开发等领域。它也是其他高级编程语言(如C++、Java等)的基础语言。


需要注意的是,C语言相对较底层,需要程序员自行管理内存和资源,因此对于初学者来说可能有一定的学习曲线。但掌握C语言的基础知识可以为后续学习其他编程语言打下坚实的基础。

一、数据

编写程序的目的是处理数据,所以先要了解数据。计算机中的数据不同于我们数学课上写的数可以随意表示任何数据,计算机中的整数和小数是不一样的,它们属于不同的类型:计算中的数据是有类型的。

1.1 数据类型

数据类型四大类:基本类型、构造类型、指针类型、空类型

  1. 基本类型:字符型 char、整型 int、浮点型(单精度浮点型 float、双精度浮点型 double)
  2. 构造类型:数组型、结构体类型 struct、共用体类型、枚举类型 enum
  3. 指针类型
  4. 空类型
    在这里插入图片描述

1.2 数据

C语言中的常量、变量、表达式、函数都可以理解为数据。

第一种数据:常量

常量有四类:整型常量、实型常量、字符型常量、字符串常量。

  1. 整型常量:三种形式(十进制、八进制、十六进制)
  2. 实型常量:两种形式(小数、指数)
    • 第一形式 -> 小数形式:由数字和小数点组成。
      如:123.456 123. .456 0.456 都是合法的实型常量。
    • 第二形式 -> 指数形式:用"E"或"e"后紧跟一个整数表示以10为低的幂。
      如:1.23E-5
      注:
      字母E或e之前之后必须都有数字,且后必须是整数。
      字母E或e的前后及各数字之间不能有空格。
  3. 字符型常量:四种形式(常规、转义、八进制、十六进制)
    • 第一形式 -> 普通字符:一对单引号括一个字符
      如:‘a’ ‘A’ ‘@’ ‘9’
    • 第二形式 -> 转义字符常量:必须以一个反斜杠“\”作为开头,常用的转义字符有
      \n 表示换行符
      \t 表示制表符
      \b 表示退格符
      \r 表示回车符
    • 第三形式 -> 八进制表示的字符:\ddd 最多可以有三位八进制数
    • 第四形式 -> 十六进制表示的字符:\xhh 最多可以有两位十六进制数
  4. 字符串常量:一种形式
    定义:用一对双引号括起来若干个字符
    如:“abcdefgh” “123456” “a1b2c3”
    注:
    每一个字符串尾都有一个字符 ‘\0’
    C语言种没有字符串变量

第二种数据:变量

变量使用规则:先定义后使用
定义格式:数据类型名 变量名列表;
比如:

int i;int j;int k;
int i, j, k;
int i=1, j=1, k=9;	/*赋初值*/

注:

  1. 变量必须先定义后使用。
  2. 变量名属于用户标识符,遵守用户标识符命名规则
  3. 在同一“函数体”{}中 不能定义同名变量。
  4. 同时定义多变量,必须用逗号分隔。
  5. 变量可赋初值(初始化),无初值是随机值。

第三种数据:表达式

各种表达式
定义:表达式:用运算符将数据连接起来的合法式子
运算符:三个属性:功能、优先级、结合性(运算方向(左->右 or 左<-右))
如:
3.5 + 1/2 3.5 + (1/2)
1+2+3 (3.5 * 1)/ 2 = 1.75
1.0/2 = ? 1/2 = ?

1、算术运算符及算术表达式

 + - * / %		【结合性是 左->右】

取余(%):

  1. 两边的运算对象必须是整型
    如:7.0%3、4%3. 、不合法的表达式
  2. 求值方法:先忽略符号不计求出余数,再将所得余数的符号定成与被除数相同的符号即可。
    如:
    17%3 结果为2
    17%-3 结果为2
    -17% 3 结果为-2
    -17% -3 结果为-2
    注:
    (1)单独的常量、变量或函数调用都是C语言的合法表达式
    (2)凡是表达式都有一个确定的值

2、赋值运算符及赋值表达式

赋值运算符:= 【14级 左<-右】
格式:变量名=表达式
赋值运算符的功能:将表达式的值赋给“=”左边的变量
例如:A = 5+8 【先计算,后赋值】
a=b=c=1+2的计算顺序是a=(b=(c=(1+2))) 【表达式的值赋值给变量】
注:

  • (1)赋值运算符左边只能是一个变量
    • 如:
      a+b= 3 4=3 非法表达式
      a=6 a+(b=3) 合法的表达式
  • (2)赋值运算符右边可以是合法表达式
    • a = b = 20 a = (b=10)/(c=2)
  • (3)赋值表达式的值就是赋值运算符左边变量的值(重要)
  • (4)实型数据赋给整型变量时,实型小数舍去,整型赋给实型变量时系统自动将整型数据转成实型数据。
    • 复合赋值运算符: 【结合性:左<-右】
      += -= *= /= %= &= |= ^= >>= <<=
    • 注:复合赋值运算符的两个运算符中间不能有空格
      如:a+ =3

例1. 若有int a = 5,b=8; 则下列表达式的值是多少?用完表达式后变量a和b的值分别为多少?
a+=b/=a
表达式的值:
A的值:
B的值:

3、自增、自减运算符

自增运算符:++ i++ ++i
自减运算符:-- i-- --i
如:
i++; ++i; 等价于:i=i+1
i–; --i; 等价于:i=i-1
【自增自减运算符:结合性2:左<-右,优先级2级】
注:
(1)只能用于变量不能用字啊常量或表达式。
如 3++、(a+b)++ 不合法的表达式
如 int a=3; 则表达式的值 变量的值
a)a++ ?3 ?4
b)++a ?4 ?4
c)a-- ?3 ?2
d)–a ?2 ?2
题1. int a=3;求a++*a

#include <stdio.h>int main()
{int a = 3;int b=	a++*a;printf("a=%d\n", a);printf("b=%d\n",b);return 0;
}

题2. 若有定义int a=20,b=20,c=20,d=20;则下列表达式的值分别为多少?
A、a++ * 10
B、10 * b++
C、++c / 7

4、逗号运算符及其表达式(‘顺序求值’表达式)

格式:表达式1,表达式2,表达式3,……,表达式n;
功能:逗号表达式的值就是表达式n的值,求值顺序是从左到右依次求解。

5、强制类型转换(显式转换)

强制类型转换(显示转换)就是手动编写代码强制性地修改数据类型。
格式:
(类型名) 表达式(类型名) (表达式)
利用强制类型转换运算符可将一个表达式的值转换成指定的类型。
如:
float x = 123.456,y;
(1) int(x) 错
(2) (int) x (int)(x)
(3) (int)x+y (int)(x+y)
进行强制类型转换,得到的是一个中间值,而原来表达式或变量的类型未发生改变。
如:
若变量x为int类型,则表达式(float)x的结果是一个单精度类型,但是x还是int型。

6、隐式转换

隐式类型转换(隐式转换)就是自动修改数据类型,一般是高精度的数据赋值给低精度的数据会出现隐式类型转换。
【隐式转换是自动完成的】
隐式类型转换

1.0/2=? 1/2=?

说明:
同一优先级的运算符,运算次序由结合方向所决定。
简单记就是:!>算术运算符 > 关系运算符 > && > || > 赋值运算符

第四种数据:函数

函数(标准函数 自定义函数)

#include<math.h>
// |-5| 如何表示?abs()		
abs(-5)

1.3 标识符

标识符就是名字。这类名字分为三类,一类是关键字,一类是预定义标识符(库函数名等),一类是用户自定义标识符(函数名、变量名)。

  1. 保留字(关键字)【int char float double等 32个(C89)】
    C语言的关键字是一些具有特殊含义的保留字,它们在C语言中有着特定的用途和功能。使用时需要遵循语法规则。
  2. 预定义标识符【main】
    预定义标识符:预先定义并具有特殊含义的标识符
    scanf printf include等
  3. 用户自定义标识符【自定义的函数名、变量名】

二、顺序结构

C语言语句:三类语句
类型1 -> /**/
类型2 -> 定义语句;
类型3 -> 执行语句;

2.1 什么是顺序结构

定义:从main()开始,由上往下一条一条地执行。

三大类语句(注释、定义、执行)->执行语句有5类:

  1. 控制语句(9条)
  2. 函数调用语句;
  3. 表达式语句;
  4. 空语句;
  5. 复合语句;
    花括号算是一条语句。

顺序结构伪代码:就是第一步干什么,第二步干什么,下一步干什么…

例如:某同学3门功课的平均分? 是顺序结构
顺序结构的程序设计框架:

#include <> 
int main() 
{ 	输入 76 89 92	//第一步计算				//第二步输出 			//第三步return 0;
} 

以下是chatgpt对顺序结构的解释:

在C语言中,顺序结构是一种基本的程序控制结构,它按照代码的顺序依次执行每个语句,没有任何条件或循环的控制。顺序结构是C语言程序中最简单、最基础的结构,也是程序的默认执行方式。

顺序结构的特点是代码按照从上到下的顺序依次执行,每个语句的执行不受其他因素的影响。当程序执行到一个语句时,会顺序执行该语句,然后继续执行下一个语句,直到程序结束。

以下是一个简单的顺序结构示例:

#include <stdio.h>int main() 
{int a = 10;int b = 20;int sum = a + b; // 第一条语句printf("The sum is: %d\n", sum); // 第二条语句return 0; // 第三条语句 
} 

在上述示例中,程序按照从上到下的顺序执行。首先,声明并初始化变量a和b,然后计算它们的和并将结果存储在变量sum中。接下来,使用printf函数打印出sum的值。最后,使用return语句结束程序的执行。

顺序结构在C语言中非常常见,它使得程序可以按照预定的顺序执行各个语句,从而实现特定的功能和逻辑。

2.2 printf()输出函数

“标准输入输出函数”是以一些库函数来实现的
注意:标准函数/库函数使用前必须:#include<头文件名>再包含的程序文件中最顶部。

printf():“占位符”是以%开始的,被替换。
占位符字符:

  1. d 带符号十进制整数
  2. u 无符号十进制整数
  3. o 无符号的进制整数
  4. X或x 无符号十六进制整数
  5. c 输出一个字符,不输出单引号
  6. s 输出一个字符串。输出时不输出双引号
  7. f 输出一个实型数。隐含输出6位小数
  8. E或e 输出指数形式的实型数

在C语言中,printf函数是一个用于输出格式化字符串的函数,它可以将指定的数据以指定的格式打印到标准输出(通常是终端窗口)。printf函数属于stdio.h头文件中的标准库函数,因此在使用之前需要包含该头文件。

printf函数的基本语法如下:

#include <stdio.h>int printf(const char *format, ...); 

其中,format是一个字符串参数,用于指定输出的格式。…表示可变参数列表,用于指定要输出的数据。

printf函数的使用方法如下:

  1. 在程序中包含<stdio.h>头文件。

  2. 在需要使用printf函数的地方,调用该函数并传入相应的参数。

  3. 在format字符串中,可以使用占位符来指定输出的格式,例如:%d表示输出整数,%f表示输出浮点数,%s表示输出字符串等。

以下是一个简单的示例,演示了如何使用printf函数输出不同类型的数据:

#include <stdio.h>int main() {int num = 10;float pi = 3.14;char str[] = "Hello, World!";printf("The value of num is: %d\n", num);printf("The value of pi is: %f\n", pi);printf("The string is: %s\n", str);return 0; 
}

在上述示例中,我们使用printf函数分别输出了一个整数、一个浮点数和一个字符串。通过在format字符串中使用相应的占位符,我们可以指定输出的格式,并将要输出的数据作为参数传递给printf函数。

运行上述程序,将会输出以下结果:

The value of num is: 10 
The value of pi is: 3.140000 
The string is: Hello, World! 

注意,printf函数中的format字符串中的占位符必须与传递给printf函数的参数类型匹配,否则可能会导致输出结果不正确或程序崩溃。

2.3 scanf()输入函数

考点1:“普通/占位符”,输入时普通字符必须原样输入。

int a, b;
scanf("%d,%d", &a, &b);
//输入:3,5scanf("a=%d,b=%d",&a,&b);
scanf("%d",&a);//编码时常写这种

考点2:“占位符”,输入时4种输入格式。

int a,b;
scanf("%d%d", &a, &b);
//输入时,中间用空格或tab间隔或回车,最后是回车
//方式一:空格	方式二:tab	方式三:空格tab	方式四 回车

考点3:“占位符”,输入时1种输入。

char ch1,ch2;
scanf("%c%c", &ch1, &ch2);
//输入时,只能挨着输入,chr1输入后不能写空格

都是字符就需要连续输入字符

考点4:“占位符”,输入时一种输入。

char ch1, ch2;
int x;
scanf("%c%d%c", &ch1, &x, &ch2);
//输入时,数字前可有空格。如:"a 3b"
//实践:输入时,数字前可有空格或tab或回车。数字后必须直接跟字符。

考点5、地址列表,输入时&。

int x;
scanf("%d",x);//错误 or 正确

2.4 字符类型数据的输入输出专属函数

(1)putchar()
格式:putchar(字符常量或字符变量)
功能:输出一个字符但不输出单引号。
如:

putchar('a');	//a
putchar('\n');
putchar(100);	//d
putchar('100');//错误

(2)getchar()
功能:接收一个从键盘输入的字符。
注:getchar()没有任何参数,函数的返回值就是输入的字符
如:

char a,b;
a=getchar();
b=getchar();

若输入为:1<回车>
则变量a的值为字符 ‘1’,变量b的值为回车符。

三、选择结构(也叫分支结构)

3.1 两类表达式

构成单个条件、联合多个条件。

(1)关系运算符及关系表达式

<     <=     >     >=     ==     !=

三要素:功能、优先级(6级)、结合性(左->右)
关系表达式的结果是一个逻辑值(0和1,代表真假)

> 4>5 
> 5==5 
> 7=7 
> 1<2<3 
> 5>4>3

(2)逻辑运算符与逻辑表达式

&&     ||     !

在C语言中,逻辑表达式的值只有 1 和 0 两种值。其中,1表示“真”,0表示“假”。
&&    11级     左 —> 右
||       12级     左 —> 右
!        2级       左 <— 右

//例题:
> 5||5
> 4<3&&9
> 0&&7
> 5>4>3&&3

做题时要考虑:

  1. 合法
  2. 短路
  3. 优先级,同级结合性

3.2 if语句

格式1:

if(表达式)语句序列; 
后续语句;

格式2:

if(表达式)语句序列1;
else语句序列2;
后续语句;

格式3:

if(表达式)if(表达式)语句序列11;else语句序列12;
else语句序列2;
后续语句;

3.3 switch语句

格式:

switch(表达式)
{case 常量表达式1	: 语句序列1;case 常量表达式2	: 语句序列2;……case 常量表达式n	: 语句序列n;default		   	: 语句序列n+1;
}
  1. switch后必须用小括号将表达式括起。
  2. case后是常量整型或字符型,不能有变量和逗号运算符。
  3. 各case后常量不能出现相同的值。
  4. case 和 default只是一个入口标号,不起中断作用。它们的顺序可以任意颠倒。switch是按照代码书写顺序执行case,最后执行default。
  5. 执行的过程是:程序执行到switch时,计算小括号内的表达式的值,若该值与某个case后的值相同时,则程序直接跳到该case语句块往后执行;若没有一个case后的值与switch后括号内表达式的值相同,当有default时程序直接跳到default所在语句块执行,当没有default时程序直接跳出switch。switch执行时,先用switch后小括号内的表达式的值对比所有的case后的常量,如果两个值相等,则执行该case语句块,如果该case语句块中有break则直接跳出switch,如果没有break,则继续检查下一个case。
  6. case和default必须出现在switch语句中。
  7. 多个case可以共用一组执行语句
    case 'A':
    case 'B':
    case 'C':printf("CCC\n");break;
    

四、循环结构

1、循环语句
功能:重复执行相同的代码段。
有三格式

格式1——while语句

while(表达式)
{//循环体语句序列;
}
//后续语句:

格式2——do while语句

do
{//循环体语句序列
}while(表达式);
//后续语句;

格式3——for语句

for(i=0; ; i++)
{//循环体语句;if(i == 35){break;}printf("123");
}
//后续语句

exp1一般是定义并初始化循环变量。循环在最初执行一次,只执行一次
exp2一般是是条件判断语句
exp3一般是循环的条件变量的增量(增加或减少)
for执行流程:最初执行一次并只执行一次exp1,然后 exp2->循环体语句->exp3 往复执行。若exp2为假则跳出循环,为真继续循环。
思考:若是没有exp2怎么办?相当于是1,永真,就是死循环。
例题:1+2+3+4+……+100

#include <stdio.h>
int main()
{int i,sum=0;//while// i = 1;// while(i<=100){//     //sum += i;//     sum = sum +i;//     i++;// }// for(i=1; i<=100; i++){//        sum += i;	//sum = sum +i;//    }//    printf("%d\n", sum);do{sum += i;i++;}while(1);//scanf("%d", &i);return 0;}

两个控制语句——break continue

格式:break;
功能:中止退出。范围:循环体中和switch体中。

for(i=1; i<4; i++)
{i++;break;
}
printf("%d", i);

格式:continue;
功能:结束当前本轮循环直接进行下一轮循环。
范围:循环体中。

for(i=1; i<=10; i++)
{//i++;if(i==6 || i==5){continue; }sum += i;//.....
}
printf("%d", i);//5

如果循环体中的continue前后都有代码,那么如果执行到continue,就相当于只跳过了循环体的后半部分。如下:

for(i=1; i<4; i++)
{i++;continue;i++;
}

例题

以下程序的运行结果是:15 or 20 or 25 or 30

#include <stdio.h>int main()
{int i,j,m;for(i=5; i>=1; i--){m = 0;for(j=i; j<=5; j++){m = m + i*j;}}printf("%d\n",m);
}

以下程序的运行结果是:20 or 21 or 32 or 43

#include <stdio.h>int main()
{int n = 4;while(n--);printf("%d", --n);
}
以下程序的运行结果是?
#include <stdio.h>int main()
{int i = 5;do{switch(i%2){case 0:i--;break;case 1:i--;continue;}i--;i--;printf("%d", i);}while(i>0);
}

五、数组

1、一维数组
2、二维数组
3、字符串
特点:同一数组中的所有元素都属于同一种数据类型(int char float)数组元素用数组名和相应的下标来确定。
方法:一个数组元素其实就是一个变量,在数组中称为带下标的变量。

5.1 一维数组的定义和引用(只有一个下标)

1、一维数组的定义格式:

类型名 数组名[常量表达式];

如:

float s[25];
float s[5*5];
int a[10];
char s1[30];

定义数组有四个注意:

  1. 数组名属于用户定义标识符。要遵守标识符命名规则。比如int for[25];是不行的。
  2. 定义一维数组时数组名后必须用一个方括号(将常量表达式括起来,常量表达式的值表示数组共有多少个元素)。
    如:下面定义是非法的
    int a(10);
    int a{10};
  3. 定义数组时方括号中的表达式不能含有变量。另外表达式的值必须要大于 0 且为正整数。如:
    int a[1.5];
    int a[-10];
    int a[n];
    int a[0];
    int N=9;int a[N];
  4. C语言每个数组在内存中分配空间时是连续分配的。

2、一维数组元素的引用格式:

数组名[下标]
先定义数组后使用
不能整体用数组名
注:C语言中不能对数组进行整体引用,只能单独引用其中的元素。引用时下标可以是如下形式。

char a[10];
a[0] = 'A';
a[3+7] = 'b';//错误

记住:数组元素下标的值在0和size-1之间。即下标范围属于[0, size-1]

3、一维数组的初始化

格式:
类型名 数组名[常量表达式]={初值1, 初值2, ……};
注意:

  1. 定义一维数组时可以将各元素的初始值依次放在一堆{}中赋值给数组(必须用{}将初值括起,且初值之间用一个逗号分隔)。
    int a[5] = {19, 45, 30, 20, 10, 66}; int a[5] = {11};
  2. 多则出错;少则补0。
  3. 定义赋初值的个数大于数组长度,则数组长度可以省略。
    int a[] = {19, 45, 66, 90};//ok
    int a[];
  4. 一个也不给则是随机值。
    int a[5];
  5. 只能在定义数组的同时用{}给数组元素整体赋值。
    a[5] = {19, 45, 30, 20, 10, 66};

5.2 二维数组的定义和引用(有两个下标)

1、二维数组的定义格式:

类型名 数组名[常量表达式1][常量表达式2]
如:
int a[10][10];
char b[3][4];
float s[7][3];
注:

  1. 数组名要遵守用户自定义标识符的命名规则。

  2. 定义二维数组第一个方括号常量表示行数,第二个方括号常量表示列数。

    int a[4*5];	//一维 	20个元素个数
    int a[4][5];//二维 	4行5列 20个元素
    
  3. 定义数组时方括号中的表达式不能有变量,且表达式的值必须是大于 0 的正整数。

  4. 在内存中二维数组元素的存放也是连续的,先行后列原则。
    在这里插入图片描述

2、二维数组的引用

数组名[行下标][列下标];
注:

  1. 不能整体引用,只能引用其中的元素
  2. 引用二维数组元素时,必须有行下表和列下标两个下标。从0开始依次加1。
    在这里插入图片描述

3、二维数组的初始化

方法1:将初值依序放在一对 {} 中,与一维数组初始化格式相同。
例如:int a[2][3] = {1,2,3,4,5,6};
方法二:定义二维数组的同时,按行初始化每一行初值均用一对 {} 括起,采用嵌套的 {} 格式。
例如:int a[2][3]={ {1,2,3}, {4,5,6} };
注意:定义二维数组的同时给数组初始化,则可以省略行数,但列数不能省略。
例如:

int a[][3]= {1,2,3,4,5,6};//对?
int a[2][]= {1,2,3,4,5,6};//错?
int a[][3];//?

5.3 字符数组

1、字符数组的初始化

char s[]={‘a’, ‘b’, ‘c’, ‘d’, ‘e’};
与其它类型数组的初始化方式一样,只是其初始值是字符。

2、字符串

因为字符串最后都有一个字符串结束符(‘\0’),所以用字符数组来存放字符串时一定要有一个元素存放结束符’\0’

  1. 字符串常量后有一个’\0’。
    如:
    "abcd"由5个字符组成:‘a’ ‘b’ ‘c’ ‘d’ ‘\0’
  2. 用字符串给一字符数组进行初始化有三种情况:
    a. 方法一:char a[] = “abcd”;
    b. 方法二:char a[] = {“abcd”};
    c. 方法三:char a[] = {‘a’,‘b’,‘c’,‘d’,‘\0’};
    遇到双引号就加 ‘\0’

3、字符串使用

(1)字符串存储(赋值)四种方法

方法1:利用scanf();键盘输入

char a[10];
scanf(“%s”, a);//输入:ab cd<回车>
scanf(“%s”, &a); //非法
printf(“%s”, a);//输出时,从当前地址开始输出,遇到’\0’结束
注:用 %s 格式输入时,遇到空格符或回车符则自动结束输入。 scanf(“%s,%s”, a,b); 不能正确读取数据。

方法2:利用gets();键盘输入

功能:读取字符串赋值给字符数组。可有空格
注:

  1. 用gets()输入字符时,只有遇到回车才读取字符。

    char str1[10];
    gets(str1);	//输入:ab cd<回车>
    //str:ab cd
    
  2. 不论用%s还是gets()在输入时均不需要输入双引号。若输入了双引号则双引号也作为字符串的有效字符。

puts()输出
功能:屏幕上输出字符数组中的字符。
注:用该函数输出与用%s格式输出一样,只是该函数将’\0’转成’\n’输出。
//如;

puts("abc");put("def");
/* 输出结果:
abc
def
*/

方法3:利用字符数组初始化

char s[] = "abc";
char s[] = {"abc"};
char s[] = {'a', 'b', 'c', '\0'};

方法4:strcpy()

char a[10];
strcpy(a, "abcd");

方法4:字符串常量赋值给指针

char *s = "hello";
char *buf = "hello world";

(2)字符串函数

第 1 函数:strcat()
格式:

#include<string.h>
strcat(字符数组1, 字符数组2);

功能:“连接”
如:

char a[18] = "jack";
char b[10] = "zhy";
strcat(a,b);
/*
a=>"jackzhy"
b=>"zhy"
*/

第 2 个函数:strcpy():
格式:

#include<string.h>
strcpy(字符数组1, 字符数组2);

功能:将字符数组2中的字符串替换到字符数组1中。函数值为字符串数组1的首地址。
如:

char str1[10] = "123456";
char str2[10] = "abc";
strcpy(str, str2);
// str1=> "abc"
// str2=> "abc"

第 3 个函数:strcmp()

#include<string.h>
strcmp(字符数组1, 字符数组2);

功能:函数返回值相同位置不同字符的ASCII码差值。
返回值:一个整型数,是一个插值。

// strcmp("abc", "abc") => 0
// strcmp("abc", "abfc") => 'c' - 'f' => -3
// strcmp("abc", "ab") => 'c' - '\0' => 99

注:不能用关系运算符直接进行字符串大小或字符数组大小的比较。

//这是不行的
"abc" == "abc";
"abc" > "ab";

第4个函数:strlen()
格式:

#include<string.h>
strlen(字符数组);

功能:求出字符数组的实际长度(不包括结束符)

char a[10] = "4332567";
printf("%d", strlen(a));//7char a[10] = "abc\018\0";	// \01是8进制
printf("%d", strlen(a));//5char a[10] = "abc\012\0";	// \012是8进制
printf("%d", strlen(a));//4

六、函数

C语言程序的框架有两种:

  1. 一个main() 单框架
  2. 一个main() + 多个子函数 复合框架

注:

  1. 一个源程序文件可由一个或多个函数组成
  2. 一个C程序可以由一个或多个源程序文件组成。
  3. C程序执行从main开始,结束于main结束;可调用其它函数。
  4. 函数不能嵌套定义,但可以互相调用,不能调用main()函数。
    函数的分类:
    (1)无参函数和有参函数
    (2)库函数和用户自定义函数+main()

6.1 函数定义

1、函数定义

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

说明:

  1. 函数体可以没有语句,但不能没有花括号,函数名后必须有一对小括号。

  2. 定义有参函数时,形参的定义可以采用传统方式或现代方式两种。

    //传统方式:
    int max(x,y)
    int x,y;	// 不能定义形参以外的其它变量
    {//...
    }//现代方式:
    int max(int x, int y)
    {}
    
  3. 函数返回值类型:两类

    // 形式1:非void型(int float double等...)
    int fun(int x, int y)
    {return 表达式;
    }// 形式2:void型
    void fun(int x, int y)
    {//不加return
    }
    

6.2 函数调用的两种方式

方式一:非void型

变量名 = 函数名(实参列表)

方式二:void型

函数名(实参列表)

6.3 函数使用例题分析

(1)原型声明
方式一:#include<头文件> (库函数)
方式二:声明的格式 (用户自定义函数)
函数类型 函数名(形参类型1 形参1, 形参类型2 形参2, …);
函数类型 函数名(形参类型1, 形参类型2, …);

void sum(int x, int y);	/*函数原型声明*/int main()
{sum(3, 5);return 0;
}void sum(int x, int y)
{printf("%d", x+y);
}
  • 有头有分号 - 声明
  • 有头有体无分号 - 定义
  • 函数名(实参) - 调用
    (2)函数调用的过程
    在进行函数调用时系统将实参值对应地(按位置次序对应)传给形参,是一种值的单向传递。
    实参与形参之间有一个关系。(顺序、类型、个数 一致)

七、在函数中的变量

7.1函数的定义与使用

函数定义:

函数返回值类型 函数名(形式参数列表)
{函数体;
}
//这是函数的定义

函数声明:

函数类型  函数名(形参类型1  形参1, 形参类型2  形参2,  ...);
函数类型  函数名(形参类型1, 形参类型2,  ...);
//这是函数的声明语句
void sum(int x, int y);int main()
{sum(3, 5);return 0;
}void sum(int x, int y)
{printf("%d", x+y);
}

7.2 变量的三个属性

变量三属性:

  1. 类型(用类型去定义变量)
  2. 作用范围(根据位置)
    a. 内部(局部)变量
    b. 外部(全局)变量
  3. 存储类别
    a. auto
    b. static
    c. register
    d. extern

1、变量类型

就是数据类型,如int、float、double

2、作用范围

(1)局部变量(内部变量)
定义:在一个函数内部定义的变量称为局部变量

  1. 局部变量只在函数(它所在的函数)内部有效
  2. 不同函数中可以出现同名变量,他们分别是不同函数的局部变量
  3. 复合语句中定义的变量只能在此复合语句中有效
  4. 所有形式参数是局部变量

(2)全局变量(外部变量)
定义:在函数外部定义的变量为全局变量

  1. 全局变量的有效范围是在本文件内从定义该变量的位置开始到本文件结束。
  2. 全局变量可以在它的有效范围内被每个函数引用(使用)。
  3. 在同一文件中若全局变量与局部变量同名,局部变量“覆盖”全局变量。

全局变量也是静态变量

3、存储类别

(1)auto变量(默认)

  1. auto类别变量用完后释放所占用空间。
  2. 局部变量默认为auto类别,无初始化时,初始值为随机值。
  3. 使用时间短,一般都为auto类别变量。

(2)static变量

  1. static从定义到程序运行结束均占用存储空间。
  2. 全局变量默认为static类别,无初始化时,初值为0。
  3. static类别变量只能进行一次初始化。

(3)register类别变量

  1. register类别只能是局部变量才能被说明。
  2. 一般不能直接使用。

(4)extern类别变量

  1. extern类别变量可以加大变量的作用范围。
  2. 两种说明格式
    1. 格式 1:
      定义的同时说明类别:
      存储类别 类型名 变量名;
    2. 格式 2:
      分别定义、说明:
      类型名 变量名;
      存储类别 变量名;

八、预编译命令

8.1 预编译命令

文件包含(include)
#include <>
#inclulde “”

8.2 宏

1、第一种:无参宏定义

格式:
#define 宏名 宏内容
功能:用一个指定的标识符(宏名)来代表一串字符串(宏内容)。
如:
#define PI 3.141592
#define N 10

注:

  1. 宏名我们一般用大写字母表示,遵守用户自定义标识符命名规则。
    如:#define PI “abcdefg”
  2. #define 可以在函数外定义也可以在函数内定义,但该命令应该在单独一行上。
  3. 在进行宏定义时,可以引用已经定义的宏名进行层层置换。
  4. 在进行宏替换时,必须先替换完所有的宏后再运算,同时替换过程中不能乱加括号。

2、第二种:带参宏定义

#define 宏名(参数列表) 宏内容
功能:提供了一种更加灵活的替换方式。
如:#define s(x,y) x*y+2

注:

  1. 在定义有参宏时,参数列表必须用一对小括号括起且小括号和宏名之间不能有空格。
  2. 对有参宏名进行替换时,需要将形参改成相应的实参,并且注意分清形参和实参的对
    应关系。

九、指针

9.1 指针变量定义

C语言有两种变量:其中变量(普通变量)存储内容值;地址变量(指针变量)存储地址值。

1、定义的格式:

类型名 *指针变量名;

如:

int a, b, *p1, *p2;
float x, y, *p3, *p4;
char s, *p5, *p6;int b, *a;
int* a;

注:

  1. 定义变量(普通变量、指针变量)都必须在前面有类型名。
  2. 在定义指针变量时,指针变量名前的“*”表示现在定义的是一个指针类型的变量。星号并不是指针变量名的一部分,只是一个标志。
  3. 指针变量专门用来存放地址,禁止将一个整型值直接赋值给一个指针变量。

2、指针变量的引用

“&”取地址运算符,通过&运算符可以取出普通变量的地址。
指针运算符,*可以取出指针变量所指向的普通变量的值,(间接引用普通量)。
*指针变量名

如:

int a,b=20,c=30,d=40,*p;
p = &d;
a = *p;	//a=d;
  1. 可以通过赋值使一个指针变量“指向”某一普通变量(指针变量 = &普通变量)
  2. 在C语言中正确的做法是先让指针变量指向一个确定的存储单元后,再通过该指针变量引用它所指向的存储单元。
  3. 变量名(普通变量、指针变量)都表示其存储单元内的值:
    p1=p2; /* p1指向了p2所指向的单元 */
  4. 若指针变量p指向变量a,即将变量a的地址赋给了指针变量p。
  5. 所有的指针变量在内存中分配的字节数相同。sizeof()

说明:int fun(int a[10]) <=> int fun(int *a) <=> int fun(int a[])
若数组做为形参,则将数组名做指针变量来处理。

9.2 指向数组的指针变量

1、指向数组元素的指针变量

由于数组元素与普通一样,所以定义指向数组元素的指针变量与定义指向普通变量的指针变量完全一样
在这里插入图片描述

2、指向一维数组的指针变量

注:
(1)C语言中规定:数组名代表数组的首地址,而且是一个地址常量
在这里插入图片描述

(2)当指针变量指向数组中的某一个元素时,指针变量加1后指向数组中后一个元素,指针变量减1时指向数组中前一个元素。
在这里插入图片描述

举例指针在数组中的使用:
在这里插入图片描述

(3)若两个指针变量指向同一个数组,则这两个指针变量可以进行大小比较如:

char s[10];
char *p1 = s+3, *p2 = &s[7];
//则 p1 > p2  ===> 0	p1 < p2 ===> 1
// p1 - p2 == -4

(4)在形参中的数组实际上是一个指针变量,并不是真正的数组,因为该“数组名”的值是可以改变的,而真正的数组名的值是不能改变的。
(5)若形参是数组或指针变量,则在函数中可以通过该形参改变实参的值。

9.3 指向多维数组的指针变量

若a是一个二维数组,则:

  1. a+i 是行指针,即指向的是一整行。若对它加1则指向下一行。
  2. *(a+i)和a[i]一样,都是一个列指针,即指向一个元素。
  3. *(a+i)+j 和 a[i]+j一样,都表示元素a[i][j]的地址。即与 &a[i][j]等价。
  4. ((a+i)+j)、(a[i]+j)、((a+i))[j] 和 a[i][j] 一样,都表示元素。
//若有以下定义:
int w[2][3];
//则对w数组元素的非法引用是:
/*
A:*(w[0]+2)
B:*(w+1)[2]
C:w[0][0]
D:*(w[1]+2)
E:w[1]+2
*/

在这里插入图片描述

1、指向多维数组元素的指针变量

如:

int a[3][4];
int *p = &a[0][3];
//则:
p+1指向元素a[1][0];
p+4指向元素a[1][3];
p-2指向元素a[0][1];
常用于取二维数组a元素地址的方式:&a[i][j]、a[i][j]*(a+i)+j 元素地址

在这里插入图片描述
在这里插入图片描述

2、指向由m个元素组成的一维数组的指针变量

定义指向由m个元素组成的一维数组的指针变量的格式:
基类型 (*指针变量名)[m];
如:

int a[5][7];//a是行地址
int (*p)[7];
p=a;
char b[10][80];
char(*r)[80];
r = b+5;

在这里插入图片描述
在这里插入图片描述

7.4 指向字符串指针的指针变量

符串常量:C语言对字符串常量是按首地址处理字符串常量的

  1. char str[] = “China”
  2. char *p = “China”
  3. str = “Chinese” 错误
  4. p = “Chinese”

7.5 指向函数的指针变量

函数名与数组名一样,是起始地址,而且是一个地址常量
定义指向函数的指针变量的方式:
类型名 (*指针变量名)();
有()的标志说明是函数

一维数组 列地址
二维数组 行地址
函数 函数地址

区分:

/*
类型名 (*指针变量名)();
类型名 普通变量名:
类型名 数组名[];
类型名 *指针变量名:
类型名 函数名()
{....}
类型名 (*指针变量名)[M];
*/

在这里插入图片描述

注:
(1)在定义指向函数的指针变量时,要注意有两个小括号必须要有,不需要定义形参。
(2)单独的函数名代表该函数的首地址(函数的入口地址)
(3)函数的指针变量只能指向函数的入口处(函数的首地址),不能指向函数中的某条指令。(
另外,对指向函数的指针变量加1是没有意义的)。
(4)给指向函数的指针变量赋值时,只写函数名即可,不必写参数。

7.6 返回指针的参数

类型名 函数名(形参)
{}返回指针的函数的定义方式为:
类型名 *函数名(形参)
{return 地址值;
}

在这里插入图片描述

7.7 指针数组和指向指针的指针变量

1、若一个数组的所有元素均为指针类型(地址),则称为指针数组。

格式:
类型名 *数组名[常量表达式];
int *s[10];

注:
(1)要注意它与定义指向m个元素组成的一维数组的指针变量之间的区别
类型名 *数组名[常量表达式];
类型名 (*指针名)[常量表达式m];
(2)它的每个元素都是一个指针类型(地址),即它的每个元素相当于一个指针变量。

int *a[10]:
int a[10]:
int a[10][10]:

在这里插入图片描述
2、指向指针的指针变量
用来存放指针变量地址的指针变量 称为 指向指针的指针变量。
定义格式:基类型名 **指针变量名;
在这里插入图片描述

如:

int a=3;
int *p = &a;
int **k = &p;
/*
则:*k得到变量p(变量a的地址)
*/

7.8 空指针

指针变量可以有空值,即指针变量不指向任何变量,不指向任何有用的存储单元。

在系统中已将NULL定义为0,即NULL的值为0。
int a,b,c,*p=NULL;
此时p的值为空指针,即p不指向任何有用的存储单元。尽管NULL的值为0,但我们不能认为p指向了地址为0的存储单元。

注:
(1)当一个指针变量的值为空指针时,我们不能引用它所指向的存储单元。
(2)若某指针(地址)的基类型为void型,则有引用时应进行相应的强制类型转换。
在这里插入图片描述

#include <stdio.h>
main()
{int a[]={1,2,3,4,5,6,7,8,9,10,11,12};int *p=a+5,*q=NULL;*q=*(p+5)printf("%d %d\n",*p,*q);
}
输出:

九、构造类型

9.1 结构体类型

1、构造结构体类型

struct 结构体类型名
{成员1的定义;成员2的定义;......;成员n的定义;
};struct student
{int sn;int age;char sex;int s[3];
};

注:
(1)定义成员的方式与定义普通变量的方式一样
(2)成员列表必须用一对花括号括起
(3)结构体名可以省略。

2、定义结构体变量

A.先定义结构体类型名再定义结构体变量

main()
{struct student{int sn;int age;char sex;int s[3];}; /*类型定义*/struct student stu1,stu2,st[25];/*变量定义*/
}

B.在定义结构体类型同时定义变量

struct student
{int sn;int age;char sex;int s[3];
}stu1,stu2,st[25]; 

C.类型、变量同时定义,类型名student省略

struct
{int sn;int age,char sex;int s[3];
}stu1,stu2,st[25]; 

注:
(1)结构体变量在内存中占用字节数为各成员占用字节数总和。【有待商榷】
在这里插入图片描述

3、结构体变量的初始化及引用】】使用结构体变量、结构体数组、结构体指针变量

(1)再定义结构体变量的同时可以将各成员的初值按顺序放在一对花括号中,来进行对结构体变量的初始化。若初值个数多于成员个数则出错,若初值个数少于成员个数,则多余成员自动赋0。

struct aa
{int a;char b[10];float c;
} a1={30, "china", 40.5}, a2={60,"hello"};

(2)结构体变量不能整体引用,只能引用它的成员(同数组相似)

/* 引用结构体成员的方式:
结构体变量名.成员名
其中.为成员运算符
*/
printf("al=%d,%s,%f", a1);//非法/
printf("al=%d,%s,%f", a1.a, a1.b, a1.c);
a1.a=80;
a1.b="xinjiang";//strcpy(a1.b, "abc")
a1.c=60.5;

(3)结构体指针变量
在这里插入图片描述
(4)指向结构体数组的指针

struct student
{int num;char name[20];char sex;float score;
};
struct student stu[3] = {{1001,"zhang",'M',60.5},{1002,"li",'M',100},{1003,"wang",'W',90.9}};
struct student *p=stu;// &stu[0]等价//引用成员:
stu[1].num;(p+1)->num;(*(p+1)).num;
stu[0].name;p->name;(*p).name;

在这里插入图片描述
注:
(1)可以用结构体变量的成员作为实参,它与普通变量作为实参的用法是一样的。
(2)用结构体变量作为实参时,要求形参必须是同一结构体类型的变量,传递后形参与实参各对应成员值是一样的。
(3)也可以用结构体类型的地址(指针变量或数组)作为实参,要求形参必须是同一结构体类型的指针变量或数组。只要是地址传递,则间可以通过形参来改变实参的值。

9.2 共用体类型

共用体中的所有成员共用同一段内存(所有成员的起始地址都是一样的)
格式:

union 共用体名
{成员列表;
};

注:
(1)成员列表为定义该共用体的成员,成员定义的方式与普通变量的方式一样。
(2)成员列表必须用一对花括号括起。
(3)共用体名可以省略。

1、共用体变量的定义

(1)先定义类型,再定义变量
(2)定义类型的同时,定义变量
(3)直接定义变量

union data
{int i;char ch[10];float s;
}

注:
由于共用体类型变量的所有成员公用同一段内存,所以共用体类型变量所占的字节数等于该共用体类型中占字节数最多的成员所占的字节数。

2、共用体变量的引用

注:
(1)不能整体引用共用体变量,只能引用其成员。
(2)同类型成员共享值。
(3)在内存中整型数据的二进制数低8位占用前面一个字节,高8位占用后面一个字节。
如:
整数255,在内存中的存储形式是:
1111 1111 0000 0000
一个字符型数据占用一个字节,对于数组来说前面元素占用前面的字节。
(4)共用体变量之间可以相互赋值,赋值后两个变量应使用同一成员。
(5)共用体变量的地址与各成员的地址都相同的。
(6)在定义共用体时,可以对其进行初始化,但只能有一个初值且必须用花括号将初值括起。相当于给第一个成员赋值。
(7)共用体、结构体的成员均可以是共用体或结构体类型
(8)不能用共用体类型变量做为函数参数。
(9)计算共用体占用字节数。

在这里插入图片描述

9.3 typedef

用typedef 定义新类型名
在编程中可以用typedef来定义新的类型名来代替已有的类型名。给已有类型起别名。
格式:
typedef 已有类型名 新的类型名;

如:

typedef int INTEGER;
//以后在定义变量时int和INTEGER是等价的。
INTEGER a[10],b; int a[10],b;

(1)typedef可用于定义各种类型名,但不能定义变量,即只要见到typedef则该语句最后的标识符必定是一个类型名而不是变量名。
(2)typedef只能对已经存在的类型新增一个别名,而不是创造新类型。即在ypedef后必须是一个已有的类型。
在这里插入图片描述

十、位运算与文件

10.1 位运算

位运算的操作对象只能是整型或字符型数据。
C语言提供6种位运算符:
&   |   ^   ~   <<   >>
复合赋值运算符:
&=   |=   ^=   <<=   >>=

1、按位与运算(&)

两个相应的二进制位都是1时,它们按位运算后的结果才是1,否则为0。
1&1=1
1&0=0
0&1=0
0&0=0
全1为1;有0为0。
作用:清零。

2、按位或运算(|)

两个相应的二进制位中只要有一个为1,则它们按位或运算后结果为1。
1|1=1
1|0=1
0|1=1
0|0=0
作用:将特定位 置1。

3、按位异或运算(^)

当两个相应的位同为1或同为0时,按位异或运算结果为0;两个相应位一个为1另一个为0时,按位异或运算结果为1。
1^1=0
1^0=1
0^1=1
0^0=0
相同为0,相异为1

4、按位取反运算(~)

按位取反运算符是一个单目运算符。按位取反后0变1,1变0。
注:
对一个数按位取反得到的值为该数+1后再乘-1。???

5、按位左移运算符(<<)

格式:数<<n
功能:将二进制位按位依序左移n位。
对一个十进制数左移n位后得到的值为该数乘以2n的积。

6、按位右移运算符(>>)

格式:数>>n
功能:将二进制位按位依序右移n位。
若该数为一个负数并且不能被2n整除则得到的数为商加-1。

10.2 文件

1、文件概念

  1. 文件:记录在外部存储介质(外存)上的数据的集合。
  2. 文件的分类:
    • 文本文件(ASCII码文件):每个字符存储在文件中。
    • 二进制文件:以二进制存储。
    • C语言对文件的存取是以字符(字节)为单位的。
  3. 文件类型指针
    考试中,记住FILE就是文件类型名,它是一个结构体类型。对一个文件进行操作,通过文件指针进行的,定义如下:FILE *fp, *in, *out;

2、文件的打开与关闭

1、文件的打开(fopen()函数)
格式:fopen(文件名,文件使用方式)
功能:按指定的“使用方式”打开文件,函数返回打开文件的指针,该指针的基类型为文件类型。文件名和文件使用方式均为字符串。
如:以只读方式打开文件data.txt,并用指针变量fp指向它。

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

打开文件的“使用方式”:
“r”:打开已存在的文件
“w”:刷新写、创建写
“a”:追加写、创建写
“+”:增强
“r+” “w+” “a+”
“rb” “wb” “ab”
“rb+” “wb+” “ab+”

注:
(1)文件使用方式只能用小写字母,文件名用大写或小写均一样。
如:

FILE *fp;
fp = fopen("c:\\tc\\data.txt", "w");

(2)在“文件使用方式”中若含有字母 b,则打开的是一个二进制文件(bit)。
(3)当fopen“打开”失败时,函数返回NULL。

if (fp = fopen(文件名, 文件使用方式)==NULL)
{printf("can not open this file\n");exit(0);
}

2、文件的关闭(fclose函数)
文件使用完后应该关闭该文件。
格式:fclose(文件指针);
如:fclose(fp);

3、文件的读写

(1)fputc()
格式:fputc()
功能:把一个字符写到文件指针所指的文件中。其中字符可以是字符常量也可以是字符变量。若输出成功则函数返回输出的字符,失败则返回EOF(stdio.h中定义为-1)。

(2)fgetc()
格式:fgetc(文件指针)
功能:从文件指针所指文件中读取一个字符。若读取成功则函数返回读取的字符,失败(遇到文件结束)则返回EOF。

char ch;
ch = fgetc(fp);

(3)fgets()
格式:fgets(str, n, fp)
功能:其中str表示一个字符指针,可以是字符数组名也可以是字符指针变量名。从fp所指文件中读取n-1个字符(不是n个字符),并在这些字符最后加一个字符串结束符’\0’后赋给str。
函数返回str的首地址。

(4)fputs()
格式:fputs(str, fp)
功能:向fp所指文件中写(输出)str中的字符串,str可以是字符串常量、字符数组或字符指针变量。在输出时字符串的结束符’\0’不会输出。若输出成功则返回0,失败返回EOF(stdio.h中定义为-1)。

(5)fread()、fwrite()
格式:
fread(buffer, size, count, fp);
fwrite(buffer, size, count, fp);
其中:
buffer时数据的地址
size是每次读写的字节数
count表示让函数进行多少次的读写
fp是要进行读写的文件指针变量
功能:用来读写一个连续的数据块
注:

  1. 这两个函数以二进制方式进行读写。

(6)fprintf()、fscanf()
格式:
fprintf(文件指针, 格式说明符, 输出列表);
fscanf(文件指针, 格式说明符, 输入列表);
功能:按格式说明符所指定的格式向文件中读写(输入输出)数据。其中格式说明符和输入(输出)列表的用法与scanf和printf函数相同。

补充:feof(文件指针)
作用是测试文件的当前读写位置是否到达文件末尾,若是则返回非0值(真),否则返回0(假)。

while(!feof(fp))
{}

4、文件当前位置读写函数

(1)重新定位指针
格式:rewind(文件指针)
作用:使当前的读写位置重新指向文件的开头。函数无返回值。

(2)fseek()
格式:fseek(文件指针,位移量,起始点)
功能:将当前的读写位置从“起始点”开始按“位置量”所指定的移动字节数向后移动。
起始点有:
SEEK_SET 或 0 (表示“文件的开始”)
SEEK_CUR 或 1 (表示“当前位置”)
SEEK_END 或 2 (表示文件末尾)
位移量:要在数值后加字母l或L。
如:
fseek(fp, 100L, SEEK_SET)

例题分析:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
(3)ftell()
格式:ftell(文件指针)
功能:返回当前文件的位置值,用相对于文件头的位移量表示。若返回-1L表示出错。
在这里插入图片描述

相关文章:

C语言基础知识理论版(很详细)

文章目录 前述一、数据1.1 数据类型1.2 数据第一种数据&#xff1a;常量第二种数据&#xff1a;变量第三种数据&#xff1a;表达式1、算术运算符及算术表达式2、赋值运算符及赋值表达式3、自增、自减运算符4、逗号运算符及其表达式&#xff08;‘顺序求值’表达式&#xff09;5…...

CG MAGIC分享3d Max中的Corona渲染器材质如何成转换VRay材质?

大家无论是使用Corona渲染器还是Vray渲染器时&#xff0c;进行材质问题时&#xff0c;都会遇到转化材质问题。 如何将CR转换成VR或者将VR转换CR材质呢&#xff1f; 对于这两者之间转换最好最好的方法只能是材质转换器。 CG MAGIC小编&#xff0c;梳理了两种方法&#xff0c;大…...

电脑入门:路由器常见问题排错步骤

HiPER系列路由器使用中Ping LAN口不通的诊断步骤 准备工作: 在可以ping通的时候记录下路由器LAN口的MAC地址: 命令hiper% show interface ethernet/1 mac Mac : 0022aa419d1e 以下步骤在ping不通路由器的时候依次操作,并记下结果: 步骤一:观察设备各端口…...

mac电脑识别不出来u盘?mac识别不了u盘怎么办

有些用户反馈说本来想要拷贝文件&#xff0c;但是将U盘插入mac系统后竟然不能识别&#xff0c;这时候我们需要用到NTFS For Mac软件。 其实mac系统只提供了它自身磁盘格式(mac os 扩展)等的读写权限&#xff0c;只提供了读的权限给NTFS、FAT32给硬盘和U盘&#xff0c;我们99%使…...

【系统编程】线程池以及API接口简介

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言&#xff0c;数据结构&#xff0c;Linux基础&#xff0c;ARM开发板&#xff0c;网络编程等领域UP&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff0…...

Verilog零基础入门(边看边练与测试仿真)-笔记

文章目录 第一讲第二讲第三讲第四讲 第一讲 1、testbench 没有端口&#xff0c;所以没括号 2、testbench 输入端 之后要变动 所以定义为reg 3、#10 &#xff1a;过10个时间单位 &#xff1b;’timescale 1ns/10ps 即 1ns 的时间单位 10ps的时间精度 4、reg 型变量赋值的时候 用…...

LLMs之Code:Code Llama的简介、安装、使用方法之详细攻略

LLMs之Code&#xff1a;Code Llama的简介、安装、使用方法之详细攻略 导读&#xff1a;2023年08月25日(北京时间)&#xff0c;Meta发布了Code Llama&#xff0c;一个可以使用文本提示生成代码的大型语言模型(LLM)。Code Llama是最先进的公开可用的LLM代码任务&#xff0c;并有潜…...

[国产MCU]-W801开发实例-MQTT客户端通信

MQTT客户端通信 文章目录 MQTT客户端通信1、MQTT介绍2、W801的MQTT客户端相关API介绍3、代码实现本文将详细介绍如何在W801中使用MQTT协议通信。 1、MQTT介绍 MQTT 被称为消息队列遥测传输协议。它是一种轻量级消息传递协议,可通过简单的通信机制帮助资源受限的网络客户端。 …...

搭建个人hMailServer 邮件服务实现远程发送邮件

文章目录 1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 hMailServer 是一个邮件服务器,通过它我们可以搭建自己的邮件服务,通过cpolar内网映射工…...

React的 虚拟DOM创建

React是一个流行的JavaScript库&#xff0c;用于构建用户界面。它通过使用虚拟DOM来提高性能和渲染速度。本文将详细介绍React的虚拟DOM的创建方式、用法和案例&#xff0c;以及相关代码和解释。 虚拟DOM是什么&#xff1f; 虚拟DOM是React的一个重要概念&#xff0c;它是一个…...

供热管网安全运行监测,提升供热管网安全性能

城市管网是城市的“生命线”之一&#xff0c;是城市赖以生存和发展的基础&#xff0c;在城市基础设施高质量发展中发挥着重要作用。供热管网作为城市生命线中连接供热管线与热用户的桥梁&#xff0c;担负着向企业和居民用户直接供热的重要职责。随着城市热力需求的急剧增加&…...

手写Mybatis:第14章-解析和使用ResultMap映射参数配置

文章目录 一、目标&#xff1a;ResultMap映射参数二、设计&#xff1a;ResultMap映射参数三、实现&#xff1a;ResultMap映射参数3.1 工程结构3.2 ResultMap映射参数类图3.3 添加类型处理器3.3.1 日期类型处理器3.3.2 类型处理器注册机 3.4 存放映射对象3.4.1 结果标志3.4.2 结…...

GE VME-7807RC-410001350-93007807-410001 K数字输入模块

通道数目&#xff1a; VME-7807RC-410001350-93007807-410001K 数字输入模块通常具有多个数字输入通道&#xff0c;可以同时监测多个数字信号。 输入类型&#xff1a; 这种模块通常用于监测数字信号&#xff0c;例如开关状态&#xff08;ON/OFF&#xff09;或计数器脉冲。 采…...

C++插入加密,替代加密

void 插入加密() {//缘由https://bbs.csdn.net/topics/396047473int n 1, j 0;char aa[60]{}, aaa[] "abcde";cin >> aa;while (j < 60 && (aa[j] - \0))cout << aa[j] << aaa[j % 5]; } void 插入加密() {//缘由https://bbs.csdn.n…...

Web前端开发概述

Web&#xff08;World Wide Web&#xff0c;全球广域网&#xff09;是指一种基于互联网的信息系统&#xff0c;通过超文本链接将全球各地的文档、图像、视频等资源相互关联起来&#xff0c;并通过Web浏览器进行交互浏览和访问。Web的发展使得人们可以方便地获取和共享各种类型的…...

Web自动化 —— Selenium元素定位与防踩坑

1. 基本元素定位一 from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By # selenium Service("../../chromedriver.exe") # driver webdriver.Chrome(serviceService) # driver.…...

【数据结构】树和二叉树的概念及结构(一)

目录 一&#xff0c;树的概念及结构 1&#xff0c;树的定义 2&#xff0c;树结点的分类及关系 3&#xff0c;树的表示 二&#xff0c;二叉树的概念及结构 1&#xff0c;二叉树的定义 2&#xff0c;特殊的二叉树 3&#xff0c;二叉树的性质 4&#xff0c;二叉树的存储结构 1&…...

第三章 USB应用笔记之USB鼠标(以STM32 hal库为例)

第三章 USB应用笔记之USB鼠标&#xff08;以STM32 hal库为例&#xff09; 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 第三章 USB应用笔记之USB鼠标&#xff08;以STM32 hal库为例&#xff09;前言一、STM32 U…...

微服务01-基本介绍+注册中心EureKa

基本介绍 服务集群&#xff1a;一个请求由多个服务完成&#xff0c;服务接口暴露&#xff0c;以便于相互调用&#xff1b; 注册中心&#xff1a;每个服务的状态&#xff0c;需要进行维护&#xff0c;我们可以在注册中心进行监控维护服务&#xff1b; 配置中心&#xff1a;这些…...

【ES6】JavaScript中的异步编程:async和await

在JavaScript中&#xff0c;异步编程是一种处理长时间运行的操作的方法&#xff0c;这些操作包括读取文件、网络请求或处理大数据等。在传统的回调函数中&#xff0c;代码按照顺序执行&#xff0c;一旦遇到长时间运行的操作&#xff0c;就需要回调函数来处理结果。这使得代码变…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...