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

嵌入式Linux入门具备:C语言基础与基本驱动学习(2):Linux GIibc IO基础

标准IO

标准 I/O 虽然是对文件 I/O 进行了封装,但事实上并不仅仅只是如此,标准 I/O 会处理很多细节,譬如分配 stdio 缓冲区、以优化的块长度执行 I/O 等,这些处理使用户不必担心如何选择使用正确的块长度。I/O 库函数是构建于文件 I/O(open()、 read()、 write()、 lseek()、 close()等)这些系统调用之上的,譬如标准 I/O 库函数 fopen()就利用系统调用 open()来执行打开文件的操作、 fread()利用系统调用 read()来执行读文件操作、 fwrite()则利用系统调用 write()来执行写文件操作等等。那既然如此,为何还需要设计标准 I/O 库?直接使用文件 I/O 系统调用不是更好吗?事实上,并非如此, 在第一章中我们也提到过,设计库函数是为了提供比底层系统调用更为方便、好用的调用接口, 虽然标准 I/O 构建于文件 I/O 之上, 但标准 I/O 却有它自己的优势,标准 I/O 和文件 I/O 的区别如下:

虽然标准 I/O 和文件 I/O 都是 C 语言函数,但是标准 I/O 是标准 C 库函数,而文件 I/O 则是 Linux系统调用;

标准 I/O 是由文件 I/O 封装而来,标准 I/O 内部实际上是调用文件 I/O 来完成实际操作的;

  • 可移植性:标准 I/O 相比于文件 I/O 具有更好的可移植性,通常对于不同的操作系统,其内核向应用层提供的系统调用往往都是不同,譬如系统调用的定义、功能、参数列表、返回值等往往都是不一样的;而对于标准 I/O 来说,由于很多操作系统都实现了标准 I/O 库,标准 I/O 库在不同的操作系统之间其接口定义几乎是一样的,所以标准 I/O 在不同操作系统之间相比于文件 I/O 具有更好的可移植性。

  • 性能、效率: 标准 I/O 库在用户空间维护了自己的 stdio 缓冲区, 所以标准 I/O 是带有缓存的,而文件 I/O 在用户空间是不带有缓存的,所以在性能、效率上,标准 I/O 要优于文件 I/O。

对于标准 I/O 库函数来说,它们的操作是围绕 FILE 指针进行的,当使用标准 I/O 库函数打开或创建一个文件时,会返回一个指向 FILE 类型对象的指针(FILE *) ,使用该 FILE 指针与被打开或创建的文件相关联,然后该 FILE 指针就用于后续的标准 I/O 操作(使用标准 I/O 库函数进行 I/O 操作),所以由此可知,FILE 指针的作用相当于文件描述符,只不过 FILE 指针用于标准 I/O 库函数中、而文件描述符则用于文件I/O 系统调用中。FILE 是一个结构体数据类型,它包含了标准 I/O 库函数为管理文件所需要的所有信息,包括用于实际I/O 的文件描述符、指向文件缓冲区的指针、缓冲区的长度、当前缓冲区中的字节数以及出错标志等。 FILE数据结构定义在标准 I/O 库函数头文件 stdio.h 中。

所谓标准输入设备指的就是计算机系统的标准的输入设备,通常指的是计算机所连接的键盘;而标准输出设备指的是计算机系统中用于输出标准信息的设备,通常指的是计算机所连接的显示器;标准错误设备则指的是计算机系统中用于显示错误信息的设备,通常也指的是显示器设备。

用户通过标准输入设备与系统进行交互, 进程将从标准输入(stdin)文件中得到输入数据,将正常输出数据(譬如程序中 printf 打印输出的字符串) 输出到标准输出(stdout) 文件,而将错误信息(譬如函数调用报错打印的信息)输出到标准错误(stderr) 文件。标准输出文件和标准错误文件都对应终端的屏幕,而标准输入文件则对应于键盘。每个进程启动之后都会默认打开标准输入、标准输出以及标准错误, 得到三个文件描述符, 即 0、 1、2, 其中 0 代表标准输入、 1 代表标准输出、 2 代表标准错误;

在应用编程中可以使用宏 STDIN_FILENO、STDOUT_FILENO 和 STDERR_FILENO 分别代表 0、 1、 2,这些宏定义在 unistd.h 头文件中:

/* Standard file descriptors. */
#define STDIN_FILENO 0 /* Standard input. */
#define STDOUT_FILENO1 /* Standard output. */
#define STDERR_FILENO2 /* Standard error output. */

0、 1、 2 这三个是文件描述符,只能用于文件 I/O(read()、 write()等),那么在标准 I/O 中,自然是无法使用文件描述符来对文件进行 I/O 操作的,它们需要围绕 FILE 类型指针来进行,在 stdio.h 头文件中有相应的定义,如下:

/* Standard streams. */
extern struct _IO_FILE *stdin; /* Standard input stream. */
extern struct _IO_FILE *stdout; /* Standard output stream. */
extern struct _IO_FILE *stderr; /* Standard error output stream. */
/* C89/C99 say they're macros. Make them happy. */
#define stdin stdin
#define stdout stdou
t#define stderr stderr

Tips: struct _IO_FILE 结构体就是 FILE 结构体,使用了 typedef 进行了重命名。所以,在标准 I/O 中,可以使用 stdin、 stdout、 stderr 来表示标准输入、标准输出和标准错误。

用库函数fopen()打开或创建文件, fopen()函数原型如下所示:

#include <stdio.h>
FILE *fopen(const char *path, const char *mode);

使用该函数需要包含头文件 stdio.h。函数参数和返回值含义如下:

  • path: 参数 path 指向文件路径,可以是绝对路径、也可以是相对路径。

  • mode: 参数 mode 指定了对该文件的读写权限,是一个字符串,稍后介绍。

  • 返回值: 调用成功返回一个指向 FILE 类型对象的指针(FILE *),该指针与打开或创建的文件相关联,后续的标准 I/O 操作将围绕 FILE 指针进行。 如果失败则返回 NULL,并设置 errno 以指示错误原因。参数 mode 字符串类型,可取值为如下值之一:

mode说明flags 参数取值
r以只读方式打开文件。O_RDONLY
r+以可读、可写方式打开文件。O_RDWR
w以只写方式打开文件;如果文件存在,将文件长度截断为0;如果文件不存在,则创建文件。O_WRONLY | O_CREAT | O_TRUNC
w+以可读、可写方式打开文件;如果文件存在,将文件长度截断为0;如果文件不存在,则创建文件。O_RDWR |O_CREAT O_TRUNC
a以只写方式打开文件,进行追加内容(在文件末尾写入);如果文件不存在,则创建文件。O_WRONLY | O_CREAT | O_APPEND
a+以可读、可写方式打开文件,进行追加内容(在文件末尾写入);如果文件不存在,则创建文件。O_RDWR | O_CREAT | O_APPEND

读文件和写文件

当使用 fopen()库函数打开文件之后,接着我们便可以使用 fread()和 fwrite()库函数对文件进行读、写操作了,函数原型如下所示:

#include <stdio.h>
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);

库函数 fread()用于读取文件数据,其参数和返回值含义如下:

  • ptr: fread()将读取到的数据存放在参数 ptr 指向的缓冲区中;

  • size: fread()从文件读取 nmemb 个数据项,每一个数据项的大小为 size 个字节,所以总共读取的数据大小为 nmemb * size 个字节。

  • nmemb: 参数 nmemb 指定了读取数据项的个数。stream: FILE 指针。

  • 返回值: 调用成功时返回读取到的数据项的数目(数据项数目并不等于实际读取的字节数,除非参数size 等于 1);如果发生错误或到达文件末尾,则 fread()返回的值将小于参数 nmemb,那么到底发生了错误还是到达了文件末尾, fread()不能区分文件结尾和错误, 究竟是哪一种情况,此时可以使用 ferror()或 feof()函数来判断

库函数 fwrite()用于将数据写入到文件中,其参数和返回值含义如下:

  • ptr: 将参数 ptr 指向的缓冲区中的数据写入到文件中。

  • size: 参数 size 指定了每个数据项的字节大小,与 fread()函数的 size 参数意义相同。

  • nmemb: 参数 nmemb 指定了写入的数据项个数,与 fread()函数的 nmemb 参数意义相同。stream: FILE 指针。

  • 返回值: 调用成功时返回写入的数据项的数目(数据项数目并不等于实际写入的字节数,除非参数 size等于 1);如果发生错误,则 fwrite()返回的值将小于参数 nmemb(或者等于 0)。

由此可知,库函数 fread()、 fwrite()中指定读取或写入数据大小的方式与系统调用 read()、 write()不同,前者通过 nmemb(数据项个数) *size(每个数据项的大小)的方式来指定数据大小,而后者则直接通过一个 size 参数指定数据大小。譬如要将一个 struct mystr 结构体数据写入到文件中:

  • 可按如下方式写入:fwrite(buf, sizeof(struct mystr), 1, file);

  • 当然也可以按如下方式写:fwrite(buf, 1, sizeof(struct mystr), file);

库函数 fseek()的作用类似于系统调用 lseek(), 用于设置文件读写位置偏移量, lseek()用于文件 I/O,而库函数 fseek()则用于标准 I/O,其函数原型如下所示:

#include <stdio.h>int fseek(FILE *stream, long offset, int whence);

函数参数和返回值含义如下:

  • stream: FILE 指针。

  • offset: 与 lseek()函数的 offset 参数意义相同。

  • whence: 与 lseek()函数的 whence 参数意义相同。

  • 返回值: 成功返回 0;发生错误将返回-1,并且会设置 errno 以指示错误原因; 与 lseek()函数的返回值意义不同,这里要注意!调用库函数 fread()、 fwrite()读写文件时,文件的读写位置偏移量会自动递增,使用 fseek()可手动设置文件当前的读写位置偏移量。

  • 譬如将文件的读写位置移动到文件开头处:fseek(file, 0, SEEK_SET);

  • 将文件的读写位置移动到文件末尾:fseek(file, 0, SEEK_END);

  • 将文件的读写位置移动到 100 个字节偏移量处:fseek(file, 100, SEEK_SET);

调用 fread()读取数据时,如果返回值小于参数 nmemb 所指定的值,表示发生了错误或者已经到了文件末尾(文件结束 end-of-file),但 fread()无法具体确定是哪一种情况; 在这种情况下,可以通过判断错误标志或 end-of-file 标志来确定具体的情况。feof()函数库函数 feof()用于测试参数 stream 所指文件的 end-of-file 标志,如果 end-of-file 标志被设置了,则调用feof()函数将返回一个非零值,如果 end-of-file 标志没有被设置,则返回 0。

#include <stdio.h>
int feof(FILE *stream);

当文件的读写位置移动到了文件末尾时, end-of-file 标志将会被设置。库函数 ferror()用于测试参数 stream 所指文件的错误标志,如果错误标志被设置了,则调用 ferror()函数将返回一个非零值,如果错误标志没有被设置,则返回 0。其函数原型如下所示:

#include <stdio.h>
int ferror(FILE *stream);

C 库函数提供了 5 个格式化输出函数,包括: printf()、 fprintf()、 dprintf()、 sprintf()、 snprintf(),其函数定义如下所示:

#include <stdio.h>
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int dprintf(int fd, const char *format, ...);
int sprintf(char *buf, const char *format, ...);
int snprintf(char *buf, size_t size, const char *format, ...);

这 5 个函数都是可变参函数,它们都有一个共同的参数 format,这是一个字符串,称为格式控制字符串,用于指定后续的参数如何进行格式转换, 所以才把这些函数称为格式化输出,因为它们可以以调用者指定的格式进行转换输出; 学习这些函数的重点就是掌握这个格式控制字符串 format 的书写格式以及它们所代表的意义, 每个函数除了固定参数之外,还可携带 0 个或多个可变参数。printf()函数

用于将格式化数据写入到标准输出; dprintf()和 fprintf()函数用于将格式化数据写入到指定的文件中,两者不同之处在于, fprintf()使用 FILE 指针指定对应的文件、而 dprintf()则使用文件描述符 fd 指定对应的文件; sprintf()、 snprintf()函数可将格式化的数据存储在用户指定的缓冲区 buf 中。printf()函数前面章节内容编写的示例代码中多次使用了该函数,用于将程序中的字符串信息输出显示到终端(也就是标准输出),它是一个可变参函数,除了一个固定参数 format外,后面还可携带 0 个或多个参数。函数调用成功返回打印输出的字符数;失败将返回一个负值!打印“Hello World”:printf("Hello World!\n");打印数字 5:printf("%d\n", 5);

fprintf()可将格式化数据写入到由 FILE 指针指定的文件中,譬如将字符串“Hello World”写入到标准错误:fprintf(stderr, "Hello World!\n");向标准错误写入数字 5:fprintf(stderr, "%d\n", 5);函数调用成功返回写入到文件中的字符数;失败将返回一个负值!

dprintf()可将格式化数据写入到由文件描述符 fd 指定的文件中,譬如将字符串“Hello World”写入到标准错误:dprintf(STDERR_FILENO, "Hello World!\n");向标准错误写入数字 5:dprintf(STDERR_FILENO, "%d\n", 5);函数调用成功返回写入到文件中的字符数;失败将返回一个负值!

sprintf()函数:sprintf()函数将格式化数据存储在由参数 buf 所指定的缓冲区中, 譬如将字符串“Hello World”存放在缓冲区中:

char buf[100];sprintf(buf, "Hello World!\n");

当然这种用法并没有意义,事实上,我们一般会使用这个函数进行格式化转换,并将转换后的字符串存放在缓冲区中,譬如将数字 100 转换为字符串"100",将转换后得到的字符串存放在 buf 中:

char buf[20] = {0};
sprintf(buf, "%d", 100);

sprintf()函数会在字符串尾端自动加上一个字符串终止字符'\0'。

需要注意的是, sprintf()函数可能会造成由参数 buf 指定的缓冲区溢出,调用者有责任确保该缓冲区足够大,因为缓冲区溢出会造成程序不稳定甚至安全隐患!函数调用成功返回写入到 buf 中的字节数;失败将返回一个负值!snprintf()函数sprintf()函数可能会发生缓冲区溢出的问题,存在安全隐患,为了解决这个问题,引入了 snprintf()函数;在该函数中,使用参数 size 显式的指定缓冲区的大小,如果写入到缓冲区的字节数大于参数 size 指定的大小,超出的部分将会被丢弃!如果缓冲区空间足够大, snprintf()函数就会返回写入到缓冲区的字符数,与sprintf()函数相同,也会在字符串末尾自动添加终止字符'\0'。若发生错误, snprintf()将返回一个负值!

以上 5 个函数中的 format 参数应该怎么写,把这个参数称为格式控制字符串,顾名思义,首先它是一个字符串的形式,其次它能够控制后续变参的格式转换。格式控制字符串由两部分组成:普通字符(非%字符) 和转换说明。普通字符会进行原样输出,每个转换说明都会对应后续的一个参数,通常有几个转换说明就需要提供几个参数(除固定参数之外的参数), 使之一一对应,用于控制对应的参数如何进行转换。如下所示:printf("转换说明 1 转换说明 2 转换说明 3", arg1, arg2, arg3);这里只是以 printf()函数举个例子,实际上并不这样用。三个转换说明与参数进行一一对应,按照顺序方式一一对应。每个转换说明都是以%字符开头,其格式如下所示(使用[ ]括起来的部分是可选的) :

%[flags][width][.precision][length]type
  • flags: 标志,可包含 0 个或多个标志;

  • width: 输出最小宽度,表示转换后输出字符串的最小宽度;precision: 精度,前面有一个点号" . ";

  • length: 长度修饰符;

  • type: 转换类型,指定待转换数据的类型。

  • 可以看到,只有%和 type 字段是必须的,其余都是可选的。

首先说明 type(类型), 因为类型是格式控制字符串的重中之重,是必不可少的组成部分,其它的字段都是可选的, type 用于指定输出数据的类型, type 字段使用一个字符(字母字符)来表示:

字符对应数据类型含义示例说明
d/iint输出有符号十进制表示的整数,i 是老式写法printf("%d\n", 123); 输出: 123
ounsigned int输出无符号八进制表示的整数(默认不输出前缀0,可在 # 标志下输出前缀0)printf("%o\n", 123); 输出: 173
uunsigned int输出无符号十进制表示的整数printf("%u\n", 123); 输出: 123
x/Xunsigned int输出无符号十六进制表示的整数,xX 区别在于字母大小写printf("%x\n", 123); 输出: 7b printf("%X\n", 123); 输出: 7B
f/Fdouble输出浮点数,fF 区别在于字母大小写,默认保留小数点后 6 位数printf("%f\n", 520.1314); 输出: 520.131400 printf("%F\n", 520.1314); 输出: 520.131400
e/Edouble输出以科学计数法表示的浮点数,eE 区别在于字母大小写printf("%e\n", 520.1314); 输出: 5.201314e+02 printf("%E\n", 520.1314); 输出: 5.201314E+02
gdouble根据数值的长度,选择以最短方式输出,%f/%eprintf("%g %g\n", 0.000000123, 0.123); 输出: 1.23e-07 0.123
Gdouble根据数值的长度,选择以最短方式输出,%F/%Eprintf("%G %G\n", 0.000000123, 0.123); 输出: 1.23E-07 0.123
schar *字符串,输出字符串中的字符直到终止字符 \0printf("%s\n", "Hello World"); 输出: Hello World
pvoid *输出十六进制表示的指针printf("%p\n", "Hello World"); 输出: 0x400624
cchar字符型,将输入的数字转换为对应的 ASCII 字符输出printf("%c\n", 64); 输出: A

flags字段的含义如下:

字符名称作用
#井号对于 o 类型,输出字符串增加前缀 0;对于 xX 类型,输出前缀 0x0X。对于浮点数类型,强制输出小数点。
0数字 0当输出数字(非 cs 类型)时,在输出前补 0,直到达到指定最小宽度。
-减号左对齐输出,若宽度不足则在右边填充空格。若同时指定 0-- 会覆盖 0
' '空格输出正数时,在数字前加一个空格,负数则加负号 -
+加号输出时无论正数还是负数,前面都带符号。正数带 +,负数带 -+ 会覆盖 ' '(空格)。
宽度类型描述示例
数字指定输出的最小宽度,若实际输出位数小于指定宽度,前面会补充空格或 0printf("%06d", 1000); 输出: 001000
*不显示宽度数值,宽度由参数列表中的值指定。printf("%0*d", 6, 1000); 输出: 001000
描述类型示例
数字整型(d, i, o, u, x, X对于整型,指定输出的最小数字位数,不足时补前导零。 例如 printf("%8.5d", 100); 输出: 00100
浮点型(a, A, e, E, f, F对于浮点数,指定小数点后数字的个数。默认6位。 例如 printf("%.8f", 520.1314); 输出: 520.13140000
g, G对于 gG,表示最大有效数字位数。
字符串s指定最大输出字符数,超过则截断。 例如 printf("%.5s", "hello world"); 输出: hello
*星号精度由参数列表指定,例如 printf("%.*s", 5, "hello world"); 输出: hello

长度修饰符指明待转换数据的长度,因为 type 字段指定的的类型只有 int、unsigned int 以及 double 等几种数据类型,但是C 语言内置的数据类型不止这几种,譬如有 16bit 的 short、unsigned short,8bit 的char、unsigned char,也有64bit 的 long long 等,为了能够区别不同长度的数据类型,于是乎,长度修饰符(length)应运而生,成为转换说明的一部分。 length 长度修饰符也是使用字符(字母字符)来表示,结合type 字段以确定不同长度的数据类型:

typelength描述
d, inoneint 类型,输出有符号十进制整数。
u, o, x, Xnoneunsigned int 类型,输出无符号十进制、八进制、十六进制整数。
f, F, e, E, g, Gnonedouble 类型,输出浮点数,使用小数表示或科学计数法。
cnonechar 类型,输出一个字符。
snonechar * 类型,输出字符串。
pnonevoid * 类型,输出指针的十六进制表示。
hhsigned char, unsigned charsigned charunsigned char 类型,输出字符。
hshort int, unsigned short intshort intunsigned short int 类型,输出整数。
llong int, unsigned long intlong intunsigned long int 类型,输出整数。
wint_twchar_t宽字符类型(wint_twchar_t),用于宽字符处理。
lllong long int, unsigned long long intlong long intunsigned long long int 类型,输出整数。
Llong doublelong double 类型,输出浮点数。
jintmax_t, uintmax_tintmax_tuintmax_t 类型,输出整数。
zsize_t, ssize_tsize_tssize_t 类型,输出无符号或有符号整数。
tptrdiff_tptrdiff_t 类型,表示指针差值。

格式化输入是类似的,这里不加以赘述了。

相关文章:

嵌入式Linux入门具备:C语言基础与基本驱动学习(2):Linux GIibc IO基础

标准IO 标准 I/O 虽然是对文件 I/O 进行了封装&#xff0c;但事实上并不仅仅只是如此&#xff0c;标准 I/O 会处理很多细节&#xff0c;譬如分配 stdio 缓冲区、以优化的块长度执行 I/O 等&#xff0c;这些处理使用户不必担心如何选择使用正确的块长度。I/O 库函数是构建于文件…...

【微服务】Docker 容器化

一、初识Docker 1. 为什么需要 Docker 大型项目组件较多&#xff0c;运行环境也较为复杂&#xff0c;部署时会遇到一些问题&#xff1a; 依赖关系复杂&#xff0c;容易出现兼容性的问题开发、测试、生产环境有差异 Docker 如何解决依赖的兼容问题 将应用的Libs&#xff08;…...

[前端] 为网站侧边栏添加搜索引擎模块

前言 最近想给我的个人网站侧边栏添加一个搜索引擎模块&#xff0c;可以引导用户帮助本站SEO优化&#xff08;让用户可以通过点击搜索按钮完成一次对本人网站的搜索&#xff0c;从而实现对网站的搜索引擎优化&#xff09;。 最开始&#xff0c;我只是想实现一个简单的百度搜索…...

解决CORS (跨源资源共享) 错误

问题引入 前端代码 <template><div id"hello-vue" class"demo">{{ message }}</div><el-button type"primary" click"handleClick">我是一个按钮</el-button></template><script setup>//加…...

Redis 实现分布式缓存

一、引言 在当今互联网时代&#xff0c;随着业务的不断发展和用户量的持续增长&#xff0c;系统的性能和可扩展性成为了关键挑战。分布式缓存作为一种重要的技术手段&#xff0c;能够有效地缓解数据库压力、提高系统响应速度、增强系统的可扩展性。Redis 作为一种高性能的内存数…...

Chrome与火狐哪个浏览器的移动版本更流畅

在当今的数字化时代&#xff0c;移动设备已经成为我们生活中不可或缺的一部分。而浏览器作为我们访问互联网的重要工具&#xff0c;其性能和用户体验直接影响到我们的使用感受。本文将对比Chrome和火狐&#xff08;Firefox&#xff09;两款主流浏览器的移动版本&#xff0c;探讨…...

7篇Python爬虫实例,直接代码可运行,全网最全,注释超详细(适合收藏)——2、爬取图片信息。

7篇Python爬虫实例&#xff0c;可直接运行&#xff0c;适合收藏 python爬虫7篇实例&#xff0c;分七个文章进行发布&#xff1b;第二篇&#xff1a;爬取图片信息。 爬取图片信息&#xff0c;并将每张图片都下载下来。 爬虫主要三部分&#xff1a; 1、获取数据 2、数据解析 3、…...

25.停车场管理系统(基于web的Java项目)

目录 1.系统的受众说明 2.相关技术与方法 3.系统分析 3.1 可行性分析 3.1.1 技术可行性 3.1.2 经济可行性 3.1.3 操作可行性 3.2 需求分析 3.2.1 系统功能描述 3.2.2 用例图分析 4. 系统设计 4.1 系统类分析 5. 系统详细设计与实现 5.1 用户登录 5.2 系统信…...

展览搭建公司怎么跟展会主办打好交道

与展会主办打好交道的重要性 首先&#xff0c;我们得明白&#xff0c;展览搭建公司为何要跟展会主办打交道。简单地说&#xff0c;展会主办拥有大量的参展商信息。这些参展商是展览搭建公司潜在的客户群体&#xff0c;与主办打好交道&#xff0c;就等于拿到了通向这些客户的 “…...

软件开发方法

软件开发方法是一种用于指导软件开发过程的系统性方法,它涵盖了从需求分析、设计、编码、测试到维护的整个软件生命周期。软件开发方法通常包括一系列的步骤、技术和工具,以确保软件的质量、可维护性和可扩展性。 常见的软件开发方法有瀑布模型、敏捷开发、螺旋模型等。这些…...

「Mac畅玩鸿蒙与硬件24」UI互动应用篇1 - 灯光控制小项目

本篇将带领你实现一个互动性十足的灯光控制小项目&#xff0c;用户可以通过点击按钮来控制灯光的开关。该项目将涉及状态管理、动态图片加载以及按钮交互&#xff0c;是学习鸿蒙应用开发的重要基础。 关键词 UI互动应用状态管理动态图片加载用户交互 一、功能说明 在这个灯光…...

十二:java web(4)-- Spring核心基础

目录 创建项目 Spring 核心基础 Spring 容器 Spring 容器的作用 Spring 容器的工作流程 Bean Bean 的生命周期 IOC&#xff08;控制反转&#xff09;与依赖注入&#xff08;DI&#xff09; 控制反转的概念 依赖注入的几种方式&#xff08;构造器注入、Setter 注入、接…...

new和malloc有什么区别,他们的用法是什么?malloc分配失败会导致什么问题

1) new和malloc的区别&#xff0c;和他们的用法 new 和 malloc 主要有以下区别&#xff1a; 一、性质和来源 new &#xff1a;是 C 的运算符&#xff0c;在操作时会调用构造函数进行对象的初始化。它是 C 语言层面的操作&#xff0c;能更好地与 C 的面向对象特性结合。 malloc …...

了解SQLExpress数据库

SQLExpress&#xff08;Microsoft SQL Server Express&#xff09;是由微软公司开发的一款免费且轻量级的数据库管理系统。以下是关于SQLExpress的详细解释&#xff1a; 一、定义与特点 定义&#xff1a; SQLExpress是Microsoft SQL Server的一个缩减版或基础版&#xff0c;旨在…...

geoserver创建一个根据属性显示不同形状的点样式

geoserver创建一个根据属性显示不同形状的点样式 三角形 -triangle 圆形 - circle 正方形 - square 星形 - star 十字形 - cross 菱形 -diamond 代码&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <StyledLayerDescriptor version"…...

中国遗传学会2024全国学术研讨会在长沙成功召开

2024年11月3日至6日&#xff0c;备受瞩目的中国遗传学会2024全国学术研讨会在长沙盛大召开&#xff0c;此次盛会由中国遗传学会携手湖南省遗传学会共同主办&#xff0c;中南大学与南华大学共同承办。大会以“遗传学&#xff1a;前沿与交叉”为主题&#xff0c;吸引了来自全国各…...

Android Studio 多工程公用module引用

在Android Studio中&#xff0c;如果有多个工程需要共享同一个module&#xff0c;你可以通过以下步骤来实现module的公用&#xff1a; 1.将你想共享的module移动到一个单独的目录&#xff0c;比如一个新建的"libraries"文件夹。 2.修改module的build.gradle文件&am…...

(实战)WebApi第9讲:EFCore性能优化(IQueryable延迟查询、取消跟踪机制)

一、例子是第8讲的四、6&#xff08;EFCore的静态化处理 &#xff09;&#xff1a;分析ToList() ToList()在下图绿色框内。 二、在没有最终取数据的时候&#xff0c;使用 IQueryable<T> 延迟执行查询 &#xff08;1&#xff09;在没有最终取数据的时候&#xff0c;不要使…...

Java实现pdf转图片

第一步 <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.32</version> <!-- 请检查最新版本 --> </dependency> 第二步 package com.example.demo.file.pdf;import or…...

健身房管理新纪元:SpringBoot技术应用

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...