【从浅学到熟知Linux】基础IO第一弹=>C语言文件操作接口、文件系统调用、文件描述符概念及分配规则

news2024/9/20 2:48:39

在这里插入图片描述

🏠关于专栏:Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程等内容。
🎯每天努力一点点,技术变化看得见

文章目录

  • C语言文件接口回顾
  • 系统文件概念与接口
    • 文件基本概念
    • 系统接口
      • open
      • read
      • write
      • close
      • lseek
    • 什么是当前路径
  • 文件描述符
    • 文件描述符概念与原理
    • 文件描述符分配规则


C语言文件接口回顾

在开始介绍基础IO上篇的相关内容前,让我们先巩固一下C语言的文件操作

C语言中打开文件的方式及区别如下标所示↓↓↓

打开模式描述
r只读方式打开
r+以读写方式,读写开始位置默认在文件开始
w以写方式打开,文件不存在则创建,存在则清空
w+以读写方式打开,文件不存在则创建,存在则清空
a以追加方式打开,文件不存在则创建,文件存在则在文件末尾追加写入
a+以追加与读方式打开,文件不存在则创建,读写位置默认在文件尾

下面是三个读写文件的函数

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
int fprintf(FILE *stream, const char *format, ...);

【代码示例1】r(只读)方式打开,结合fread函数↓↓↓

#include <stdio.h>

int main()
{
	FILE* fp = open("./log.txt", "r");
	char buffer[1024];
	fread(buffer, sizeof(buffer), sizeof(char), fp);
	printf("%s\n", buffer);
	fclose(fp);
	return 0;
}

在这里插入图片描述
【代码示例2】r+(读写)方式打开,结合fwrite、fread函数↓↓↓

#include <stdio.h>
#include <string.h>

int main()
{
	FILE* fp = fopen("./log.txt", "r+");
	char* msg = "xm";
	fwrite(msg, strlen(msg), sizeof(char), fp);
	char buffer[1024];
	fread(buffer, sizeof(buffer) - 1, sizeof(char), fp);
	printf("%s\n", buffer);
	fclose(fp);
	return 0;
}

在这里插入图片描述
【代码示例3】w(写)方式打开,结合fprintf函数↓↓↓

#include <stdio.h>

int main()
{
	FILE* fp = fopen("./log.txt", "w");
	fprintf(fp, "jammingpro\n");
	fclose(fp);
	return 0;
}

在这里插入图片描述
【代码示例3】w+(读写)方式打开,结合fseek、fread、fwrite函数↓↓↓

★ps:fseek的接口声明如下↓↓↓

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

其中whence和offset可填写值和关系如下:

whenceoffset
SEEK_SET从文件开始位置向后偏移n个位置
SEEK_CUR从当前位置向后偏移n个位置
SEEK_END从文件结尾位置向前偏移n个位置
#include <stdio.h>
#include <string.h>

int main()
{
	FILE* fp = fopen("./log.txt", "w+");
	char* msg = "jammingpro\n";
	fwrite(msg, strlen(msg), sizeof(char), fp);
	fseek(fp, 0, SEEK_SET);
	char buffer[1024];
	fread(buffer, sizeof(buffer), sizeof(char), fp);
	printf("%s", buffer);
	fclose(fp);
	return 0;
}

在这里插入图片描述
【代码示例4】a(追加)方式打开,结合fwrite函数↓↓↓

#include <stdio.h>
#include <string.h>

int main()
{
	FILE* fp = fopen("./log.txt", "a");
	char* msg = "Jammingpro\n";
	fwrite(msg, strlen(msg), sizeof(char), fp);
	fclose(fp);
	return 0;
}

在这里插入图片描述
【代码示例5】a+(读写)方式打开,结合fseek、fread、fwrite函数↓↓↓

#include <stdio.h>
#include <string.h>

int main()
{
	FILE* fp = fopen("./log.txt", "a+");
	char* msg = "Jammingpro\n";
	fwrite(msg, strlen(msg), sizeof(char), fp);
	fseek(fp, 0, SEEK_SET);
	char buffer[1024];
	fread(buffer, sizeof(buffer), sizeof(char), fp);
	fclose(fp);
	return 0;
}

在这里插入图片描述

系统文件概念与接口

文件基本概念

当我们使用ls -l查看文件信息时,会显示文件的类型、权限、引用计数、所有者、所属组、大小、创建时间等信息,这些都是文件一些属性信息。
在这里插入图片描述
由此,我们可以知道:文件=内容+属性

文件被打开,需要先被加载到内存。由于内存空间有限,不可能将所有文件全部打开,所以文件可分为已经被打开的文件和没有被打开的文件。

对于打开的文件,由于文件必然是被进程打开的,因而我们需要研究文件与进程之间的关系;对于没有打开的文件,这些文件一定存放于磁盘中,这么多的未打开文件如何被分门别类的存放于磁盘中,要如何快速找到它们并对它们做增删改查操作是我们需要研究的问题。对于打开的文件,将在该文章中介绍,未打开的文件将在下一篇文章介绍。

系统接口

文件其实是在磁盘上的,磁盘属于外部设备,访问磁盘上的文件就是访问磁盘。进程要对文件做操作就需要访问硬件设备,而整个计算机中只有操作系统具有这种权力,操作系统会提供对应的调用接口用于访问对应的硬件设备。下面介绍一下操作系统提供的文件操作接口↓↓↓

open

在这里插入图片描述
open系统接口第一个参数需要传入待打开文件的路径,第二个参数表示以什么样的方式打开,第二个参数可填写的选项如下标所示↓↓↓

flags选项描述
O_RDONLY只读
O_WRONLY只写
O_CREAT不存在就创建
O_TRUNC清空文件
O_APPEND追加写入

这些选项如何使用?使用原理是什么呢?它的原理就是位图结构。一个int类型包含32个比特位,如果我们让低位起第1位为1表示READ,低位起第2位为1表示WRITE…(如下图所示)
在这里插入图片描述
此时若要实现CREAT、TRUNC、WRITE,则只要对这三个数做或运算,即CREAT | TRUNC | WRITE,则会得到一个值为00000000 00000000 00000000 00011010的flags。将它传递给处理函数中,处理函数会将flags与READ、WRITE、APPEND等,挨个做与运算,如果与出来的结果不为0,则表示该选项被选择。

#include <stdio.h>

#define READ	(1 << 0)
#define WRITE	(1 << 1)
#define APPEND	(1 << 2)
#define CREAT	(1 << 3)
#define TRUNC	(1 << 4)

void run(int flags)
{
	if(flags & READ)
	{
		printf("reading...\n");
	}
	if(flags & WRITE)
	{
		printf("writing...\n");
	}
	if(flags & APPEND)
	{
		printf("appending...\n");
	}
	if(flags & CREAT)
	{
		printf("creating...\n")
	}
	if(flags & TRUNC)
	{
		printf("truncing...\n");
	}
}

int main()
{
	run(READ);
	printf("------------------------------------\n");
	run(WRITE | TRUNC | CREAT);
	printf("------------------------------------\n");
	run(APPEND | CREAT);
	printf("------------------------------------\n");
	return 0;
}

在这里插入图片描述

而open的第三个参数表示表示文件创建时的权限。当我们使用touch命令创建文件时,我们习以为常的认为,文件的默认权限是666,文件夹的默认权限是777。但在使用系统接口时,我们需要显示指明文件权限,系统接口没有给我们设置默认权限。

★ps:系统文件权限默认是666,目录默认权限是777。但它们的默认权限需要与~umask做与运算,即文件的最终权限等于666&~mask,目录的最终权限是777&~umask。我们可以使用umask接口手动设置umask,而不使用当前系统的默认umask。(umask的修改只在该程序内有效)
在这里插入图片描述
下面,我们使用系统接口open以O_RDONLY | O_CREAT创建一个文件↓↓↓(由于没有写明创建文件时的权限,故创建的文件权限是随机的)

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	int fd = open("./log.txt", O_RDNOLY | O_CREAT);
	printf("%d\n", fd);
	return 0;
}

在这里插入图片描述
下面,我们使用系统接口open以O_TRUNC | O_CREAT创建一个权限为0666的文件↓↓↓(在创建文件前,我们需要umask权限掩码清零)

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	umask(0);
	int fd = open("./log.txt", O_TRUNC | O_CREAT, 0666);
	printf("%d\n", fd);
	return 0;
}

在这里插入图片描述

★ps:open打开文件后会返回一个数字,该数字称为文件描述符,用于唯一标识当前进程打开的文件(即同时打开的不同文件的文件标识符不同),下文将对文件描述符做详细介绍

read

在这里插入图片描述
要从某个文件中读取内容时,第一个参数需要传入该文件的文件描述符,第二个参数需要传入接收文件内容的缓冲区首地址,第三个参数表示要从文件中读取多少字节的内容。

下面程序模拟实现了C语言fopen的r(只读)打开模式↓↓↓

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	int fd = open("./log.txt", O_RDONLY);
	char buffer[1024];
	read(fd, buffer, sizeof(buffer));
	printf("%s", buffer);
	return 0;
}

在这里插入图片描述

write

在这里插入图片描述
要向某个文件中写入内容时,第一个参数需要传入该文件的文件描述符,第二个参数需要传入将要写入文件的字符串的地址,第三个参数表示要向文件中写入多少字节的内容。

下面程序模拟实现C语言fopen的w(只读)模式打开↓↓↓

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	int fd = open("./log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
	char* msg = "Have a good day!\n";
	write(fd, msg, strlen(msg));
	return 0;
}

在这里插入图片描述
下面程序模拟实现C语言fopen的a(追加)模式打开↓↓↓

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	int fd = open("./log.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
	char* msg = "Have a good day!\n";
	write(fd, msg, strlen(msg));
	return 0;
}

在这里插入图片描述

close

在这里插入图片描述
close用于关闭文件描述符对应的文件,它只需要传入文件描述符即可。该处不做代码演示,在lseek的示例代码中会演示close的使用。

lseek

在这里插入图片描述
lseek与C语言的fseek使用方法类似,用于移动文件的读写位置,不同之处在于fseek第一个参数传入的是FILE*类型的FILE结构体指针,而lseek第一个参数传入的是文件描述符。第三个描述符仍可以填写以下三个中的一个:SEEK_SET(文件头)、SEEK_CUR(当前位置)、SEEK_END(文件尾),而第二个参数表示偏移量。

下面给出代码示例↓↓↓

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	int fd = open("./log.txt", O_RDONLY | O_APPEND, 0666);
	char buffer[1024];
	read(fd, buffer, sizeof(buffer));
	printf("%s", buffer);
	//回到文件头再读一遍
	lseek(fd, 0, SEEK_SET);
	read(fd, buffer, sizeof(buffer));
	printf("%s", buffer);
	close(fd);
	return 0;
}

在这里插入图片描述

什么是当前路径

当我们没有指名open打开文件的路径时,则open将在当前路径下创建文件↓↓↓

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	int fd = open("log.txt", O_CREAT);
	close(fd);
	sleep(60);
	return 0;
}

在这里插入图片描述
将程序运行起来后,我们可以使用ps axj | grep test查看运行该程序的进程pid,进入/proc/进程pid目录,可以看到两个链接文件cwd和exe。其中,cwd是程序的工作路径,也就是我们常说的当前路径,而exe是可自行程序的保存位置。
在这里插入图片描述
当程序运行起来后,默认的工作路径是执行该程序时bash所处的路径。如果我们位于/home/xiaoming路径下执行上述程序,则cwd则指向/home/xiaoming。
在这里插入图片描述
★ps:几乎所有的库只要访问硬件设备,必须要封装系统调用。故C语言的文件操作接口是对上述系统调用接口的封装。

文件描述符

文件描述符概念与原理

通过上述内容,我们知道了文件描述符就是一个整数。下面我们来聊一聊文件描述符的内容。

C语言程序运行时,默认会打开3个输入输出流,我们可以使用一段代码来验证一下↓↓↓

★ps:C语言中接收fopen返回值的类型是FILE,C语言库函数是对系统接口的封装,故FILE中必然存在一个保存描述符的变量,即_fileno。

#include <stdio.h>

int main()
{
	printf("stdin->%d\n", stdin->_fileno);
	printf("stdout->%d\n", stdout->_fileno);
	printf("stderr->%d\n", stderr->_fileno);
	return 0;
}

在这里插入图片描述

C语言默认打开3个输入输出流是语言特性吗?其实不是,这是操作系统的特性。操作系统中,进程创建时默认会打开0、1、2号描述符,它们的详细内容如下标↓↓↓

文件描述符描述对应设备
0标准输入键盘
1标准输出显示器
2错误输出显示器

下面,我们使用系统接口从0号描述符读入内容,并将读入内容写入1号及2号描述符↓↓↓

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>

int main()
{
	char buffer[1024];
	read(0, buffer, sizeof(buffer));
	printf("write to 1st fd:\n");
	write(1, buffer, strlen(buffer));
	printf("write to 2nd fd:\n");
	write(2, buffer, strlen(buffer));
	return 0;
}

在这里插入图片描述

★ps:向1号和2号描述符中打印都是输出到显示器,那它们有什么区别呢?
当我们执行上述程序时使用./sysfileno > ouput.txt,再查看文件输出结果:打印到1号描述符的(printf默认打印到1号描述符)内容被写入到output.txt,而打印到2号描述符的内容的内容被输入到屏幕了。
在这里插入图片描述
./sysfileno > ouput.txt./sysfileno 1> ouput.txt是等价的,两者没有区别↓↓↓
在这里插入图片描述
那如果要将打印到2号描述符的内容打印到err.txt中,打印到1号描述符的内容打印到屏幕呢?则需要执行:./sysfileno 2> ouput.txt↓↓↓
在这里插入图片描述
如果需要将写入到1号和2号文件描述符的内容输入到result.txt,则需要执行./sysfileno > result.txt 2>&1./sysfileno 2> result.txt 1>&2↓↓↓(两者输出结果相同)
在这里插入图片描述
在这里插入图片描述

当操作系统中打开大量的文件时,就需要对打开的文件做管理。在Linux系统中,使用struct file结构体保存打开文件的信息;而对于每个进程来说,每个进程都维护着一个struct files_struct,struct files_struct保存着当前进程打开的各个文件的struct file地址。(每个打开的文件,在内核当中都有file对象,保存了文件相关的inode元信息)ps:inode将于专栏下一篇文章介绍

在这里插入图片描述
现在知道:文件描述符就是从0开始的小整数(因为数组的下标是从0下标开始的)。当打开文件时,操作系统在内存中要创建相应的结构体来描述目标文件,于是就有了file结构体(用于表示一个已经打开的文件对象)。当进程打开文件时,为了让进程和该进程打开的文件产生关联,每个进程就有了一个*files,指向一张files_struct表,该表最重要的部分是:包含了一个保存已打开文件的file结构体地址的指针数组。

所以,本质上,文件描述符就是数组下标(即当前进程的文件描述符表下标)。只要取得对应的文件描述符,就能找到对应的文件。

文件描述符分配规则

那我们打开一个新的文件时,是如何分配文件描述符的呢?↓↓↓

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>

int main()
{
	printf("stdin->%d\n", stdin->_fileno);
	printf("stdout->%d\n", stdout->_fileno);
	printf("stderr->%d\n", stderr->_fileno);
	
	int fd1 = open("./log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
	printf("fd1->%d\n", fd1);
	
	//关闭标准输入
	close(0);
	int fd2 = open("./log2.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
	printf("fd2->%d\n", fd2);

	//关闭标准错误
	close(2);
	int fd3 = open("./log3.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
	printf("fd3->%d\n", fd3);

	close(fd1);
	close(fd2);
	close(fd3);
	return 0;
}

在这里插入图片描述
系统默认打开三个标准输入输出流stdin(0号)、stdout(1号)、stderr(2号),此时我们打开一个文件时分配3号描述符,因为0到2号均被占用;关闭0号,再打开一个新文件时,该新文件的文件描述符为0;关闭2号,再打开一个新闻界时,该文件的文件描述符为2。由此可知,文件描述的分配规则是:分配当前最小的未使用的文件描述符

🎈欢迎进入从浅学到熟知Linux专栏,查看更多文章。
如果上述内容有任何问题,欢迎在下方留言区指正b( ̄▽ ̄)d

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1612074.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CTFHUB RCE作业

题目地址&#xff1a;CTFHub 完成情况如图&#xff1a; 知识点&#xff1a; preg_match_all 函数 正则匹配函数 int preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags PREG_PATTERN_ORDER [, int $offset 0 ]]] )搜索 subject 中…

Navicat Premium 16最新版激活 mac/win

Navicat Premium 16 for Mac是一款专业的多连接数据库管理工具。它支持连接多种类型的数据库&#xff0c;包括MySQL、MongoDB、Oracle、SQLite、SQL Server、PostgreSQL等&#xff0c;可以同时连接多种数据库&#xff0c;帮助用户轻松地管理和迁移数据。 Navicat Premium 16 fo…

如何在在wordpress安装百度统计

前言 看过我的往期文章的都知道&#xff0c;我又建了一个网站&#xff0c;这次是来真的了。于是&#xff0c;最近在查阅资料时发现&#xff0c;有一款免费的软件可以帮我吗分析网站数据。&#xff08;虽然我的破烂网站压根没人访问&#xff0c;但是能装上的都得上&#xff0c;…

【离散数学】关系

一、序偶和笛卡尔积 序偶&#xff1a;两个元素按照一定的次序组成的二元组&#xff0c;记为<x,y>&#xff0c;x为第一元素&#xff0c;y为第二元素 序偶的相等条件&#xff1a;<a,b><c,d>当且仅当ac,bd n重有序组&#xff1a;n个元素按照一定次序组成的n元…

CSS——前端笔记

CSS 1、选择器1.1、基础选择器1.2、复合选择器1.2.4、伪类选择器 1.3、属性选择器1.4、结构伪类选择器1.5、伪元素选择器 2、CSS的元素显示模式2.1、块元素2.2、行内元素2.3、行内块元素2.4、元素显示模式转换 3、字体属性3.1、font-family 字体3.2、font-size 字体大小3.3、fo…

Python 数据结构和算法实用指南(四)

原文&#xff1a;zh.annas-archive.org/md5/66ae3d5970b9b38c5ad770b42fec806d 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第十二章&#xff1a;字符串算法和技术 根据所解决的问题&#xff0c;有许多流行的字符串处理算法。然而&#xff0c;最重要、最流行和最有…

c语言之字符串的集合存放形式

采用指针分配的二维数组与直接定义的二维数组&#xff0c;sizeof的不同 采用指针分配的二维数组&#xff1a; 它的遍历方式是&#xff1a; 上面这个是分配二级指针的地址&#xff0c;二级指针就是一片可以用来分配一级指针空间的地址&#xff0c;然后指针寻址本来就可以当成数组…

Mac多媒体播放器 Movist Pro v2.11.4中文激活版下载

Movist Pro for Mac是一款专业的媒体播放器&#xff0c;特别为Mac用户设计。它不仅界面简洁美观&#xff0c;而且功能强大&#xff0c;能满足用户各种播放需求。 Movist Pro v2.11.4中文激活版下载 首先&#xff0c;Movist Pro for Mac支持多种媒体文件的播放&#xff0c;包括视…

Ubuntu系统安装Anaconda

1. 下载Anconda安装包 1.1 wget命令下载 当然还可以去清华大学开源软件镜像站&#xff1a;Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror&#xff0c;下载各种版本的Anaconda。 wget下载命令如下&#xff1a; 我这里下载的是2024.02…

【IDEA】在IntelliJ IDEA中导入Eclipse项目:详细指南

IntelliJ IDEA和Eclipse是两款常用的集成开发环境&#xff08;IDE&#xff09;&#xff0c;在软件开发中经常会遇到需要在它们之间迁移项目的情况。本文将重点介绍如何在IntelliJ IDEA中导入Eclipse项目&#xff0c;以帮助开发者顺利地迁移他们的项目&#xff0c;并在IntelliJ …

计算机组成原理【CO】Ch7 I/O大题

目录 I/O大题解题方法 I/O接口 各种I/O方式的特点 I/O端口编址 程序查询方式 中断控制方式 DMA控制方式 程序中断的工作流程 程序中断的工作流程 DMA方式和中断方式的区别 I/O大题解题方法 CPU 程序查询中断DMA I/O接口的类型 按字传输&#xff1a;每次传输一个字 程…

OpenCV基本图像处理操作(十)——图像特征harris角点

角点 角点是图像中的一个特征点&#xff0c;指的是两条边缘交叉的点&#xff0c;这样的点在图像中通常表示一个显著的几角。在计算机视觉和图像处理中&#xff0c;角点是重要的特征&#xff0c;因为它们通常是图像中信息丰富的区域&#xff0c;可以用于图像分析、对象识别、3D…

小而强,大不同:小模型SLM在人工智能时代的影响

小模型的优势越来越明显了 在人工智能领域的竞赛中&#xff0c;小型语言模型&#xff08;SLM&#xff09;正在崛起&#xff0c;挑战传统观念。虽然大型语言模型&#xff08;LLM&#xff09;曾占据主导地位&#xff0c;但SLM凭借其小巧、高效和适应性强的优势&#xff0c;正在推…

【php开发工程师系统性教学】——Laravel框架(验证码)的配置和使用的保姆式教程

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

决策树分类任务实战(python 代码详解)

目录 一、导入库、数据集、并划分训练集和测试集 二、参数调优 (一)第一种调参方法&#xff1a;for循环 (1)单参数优化 ①单参数优化(无K折交叉验证) ②单参数K折交叉验证 优化 (2)多参数优化 ①多参数优化(无K折交叉验证) 参数介绍&#xff1a; ②多参数K折交叉验证…

博客网站/部署服务器---继上篇前端页面接入后端

目录 准备工作 创建用户类博客类与连接数据库 创建博客类 创建用户类 创建连接数据库工具类 实现对数据库数据博客的操作 实现对数据库用户的操作 创建数据库语句 登录页面 前端 后端 博客列表 前端 注销登录 写入数据 判断用户是否登录 替换页面用户昵称 后…

C语言中的控制语句(循环语句while、for)

循环语句 什么是循环 重复执行代码 为什么需要循环循环的实现方式 whiledo...whilefor while语句 语法格式&#xff1a; while (条件) {循环体…… } 需求&#xff1a;跑步5圈 示例代码&#xff1a; #include <stdio.h>int main() {// 需求跑步5圈// 1. 条件变量的…

C语言 逻辑运算符

本文 我们来说 逻辑运算符 有时做出决策需要测试多个条件&#xff0c;C语言提供了用于将简单条件组合成复杂条件的逻辑运算符。 逻辑运算符 如下图 用逻辑运算符连接操作数组成的表达式称为逻辑表达式。 逻辑运算的结果只有0和1 逻辑运算的对象可以是任意数值型&#xff0c;但…

Axure RP 9中文激活版:专业原型设计工具mac/win

Axure RP 9是一款由美国Axure Software Solution公司开发的专业原型设计工具。它凭借强大的交互功能和丰富的设计素材&#xff0c;为产品经理、UI设计师、交互设计师等用户提供了高效、便捷的原型设计体验。 Axure RP 9支持快速创建线框图、流程图、原型和规格说明文档&#xf…

过零可控硅光耦与随机可控硅光耦

无过零检测 推荐型号 MOC3021无过零检测 对应的数据手册 原理框图 工作电流 过零检测 推荐型号 MOC3061 原理框图 工作电流 注意事项 随机导通型是随时打开的。都是过零时关闭 也即是说&#xff1a;过零型打开的都是一个馒头波。 参考链接 过零可控硅光耦怎么用-电路知识干…