嵌入式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 类型,表示指针差值。

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P10 Pytorch入门实战——Pytorch实现车牌识别

一、前期准备 1. 设置device # import the necessary libraries import torch import torch.nn as nn import torchvision.transforms as transforms from torchvision import transforms, datasets import matplotlib.pyplot as plt import PIL,pathlib from PIL import Im…

基于SSM+小程序的宿舍管理系统(宿舍1)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 本宿舍管理系统小程序有管理员和学生两个角色。 1、管理员功能有个人中心&#xff0c;公告信息管理&#xff0c;班级管理&#xff0c;学生管理&#xff0c;宿舍信息管理&#xff0c;宿舍…

基于 JavaWeb 的宠物商城系统(附源码,文档)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

.NET周刊【11月第1期 2024-11-03】

国内文章 .NET 9 AOT的突破 - 支持老旧Win7与XP环境 https://www.cnblogs.com/lsq6/p/18519287 .NET 9 引入了 AOT 支持&#xff0c;使得应用程序能够在编译时优化&#xff0c;以在老旧 Windows 系统上运行。这项技术通过静态编译&#xff0c;消除运行时的 JIT 编译&#xf…

iptables 规则备份和恢复

保存IPiptables规则 使用 service 命令: 在 CentOS 7 中&#xff0c;您可以使用 service 命令来保存当前的 iptables 规则&#xff1a; iptables save 这将把当前的 iptables 规则保存到 /etc/sysconfig/iptables 文件中。 使用 iptables-save 命令: 另一种方法是使用 iptab…

知乎信息流广告推广开户流程及攻略!

无论是品牌推广、产品营销还是获取精准流量&#xff0c;知乎信息流广告都能成为企业和营销者的有力武器。云衔科技作为专业的服务提供商&#xff0c;为企业提供知乎广告开户及代运营服务。 一、知乎信息流广告 知乎拥有海量的高质量用户&#xff0c;他们来自各行各业&#xf…

6-解决Ubuntu系统与Windows系统双系统时间不同步问题

引言 &#xff1a; 你是不是每次切换系统之后&#xff0c;系统时间就混乱了&#xff1f;想设置一致但又无从下手。看完这篇文章&#xff0c;你就全懂了&#xff01;&#xff01; 学习目标&#xff1a; 帮助开发者理解并解决 Ubuntu 与 Windows 双系统中时间不同步的问题。通…

【大数据学习 | kafka】kafka的偏移量管理

1. 偏移量的概念 消费者在消费数据的时候需要将消费的记录存储到一个位置&#xff0c;防止因为消费者程序宕机而引起断点消费数据丢失问题&#xff0c;下一次可以按照相应的位置从kafka中找寻数据&#xff0c;这个消费位置记录称之为偏移量offset。 kafka0.9以前版本将偏移量信…

基于梯度的快速准确头部运动补偿方法在锥束CT中的应用|文献速递-基于深度学习的病灶分割与数据超分辨率

Title 题目 A gradient-based approach to fast and accurate head motion compensation in cone-beam CT 基于梯度的快速准确头部运动补偿方法在锥束CT中的应用 01 文献速递介绍 锥束计算机断层扫描&#xff08;CBCT&#xff09;系统在灵活性方面比螺旋多排探测器计算机断…

语音识别ic赋能烤箱,离线对话操控,引领智能厨房新体验

一、智能烤箱产品的行业背景 随着科技的飞速发展&#xff0c;智能家居已经成为现代家庭的新宠。智能烤箱作为智能家居的重要组成部分&#xff0c;正逐渐从高端市场走向普通家庭。消费者对于烤箱的需求不再仅仅局限于基本的烘焙功能&#xff0c;而是更加注重其智能化、便捷化和…

qt QWizard详解

1、概述 QWizard是Qt框架中提供的一个功能强大的向导对话框类。它帮助用户逐步完成复杂的任务或流程&#xff0c;通过一系列页面组成的向导界面&#xff0c;实现了交互式和响应式的用户体验。QWizard可以应用于多种场景&#xff0c;如安装向导、配置向导、数据导入向导等&…

如何看待AI技术的应用场景:现状与未来的全面解析

人工智能&#xff08;AI&#xff09;正在以惊人的速度改变我们的世界。从医疗诊断到自动驾驶&#xff0c;从虚拟助手到金融分析&#xff0c;AI的应用场景正日益扩展&#xff0c;影响着几乎每个行业。然而&#xff0c;AI的广泛应用也引发了关于隐私、安全、伦理等多方面的讨论。…

ONLYOFFICE 8.2深度体验:高效协作与卓越性能的完美融合

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ONLYOFFICE 8.2 &#x1f50d;引言&#x1f4d2;1. ONLYOFFICE 产品简介&#x1f4da;2. 功能与特点&#x1f341;协作编辑 PDF&#x1f342;…

使用SQLark如何将Oracle迁移到达梦数据库

​ 以上对话源于某位负责数据库适配的 ISV 工程师&#xff0c;他正在将数据从 Oracle 迁移到某国产数据库中。像这样的基础问题&#xff0c;每天在各个适配群、各个社区不断出现&#xff0c;比如&#xff1a; Oracle 迁移到 DM 后&#xff0c;数据有乱码&#xff0c;达梦如何设…

Unity3D学习FPS游戏(9)武器音效添加、创建敌人模型和血条

前言&#xff1a;虽然已经实现了基本玩家操作&#xff0c;但是游戏运行起来并没有音效。既然是FPS游戏有了玩家和武器&#xff0c;肯定还得有敌人。本篇演示如何给武器添加音效和创建敌人。 武器音效添加和创建敌人 武器音效添加Audio Source代码控制 创建敌人目标敌人模型敌人…

【算法】Floyd多源最短路径算法

目录 一、概念 二、思路 三、代码 一、概念 在前面的学习中&#xff0c;我们已经接触了Dijkstra、Bellman-Ford等单源最短路径算法。但首先我们要知道何为单源最短路径&#xff0c;何为多源最短路径 单源最短路径&#xff1a;从图中选取一点&#xff0c;求这个点到图中其他…

Docker安装MongoDB详解(mongo.latest)

一、MongoDB介绍 MongoDB是一种基于分布式文件存储的数据库&#xff0c;使用C语言开发&#xff0c;旨在为Web应用提供可扩展且高性能的数据存储解决方案。作为一种介于关系数据库和非关系数据库之间的技术&#xff0c;MongoDB具有强大的功能和高效的性能&#xff0c;特别适用于…

金箍棒变化-第15届蓝桥杯国赛Scratch初/中级组真题第1题

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第193讲。 如果想持续关注Scratch蓝桥真题解读&#xff0c;可以点击《Scratch蓝桥杯历年真题》并订阅合集&#xff0c;…

简单的 docker 部署ELK

简单的 docker 部署ELK 这是我的运维同事部署ELK的文档&#xff0c;我这里记录转载一下 服务规划 架构: Filebeat->kafka->logstash->ES kafka集群部署参照: kafka集群部署 部署服务程序路径/数据目录端口配置文件elasticsearch/data/elasticsearch9200/data/elas…

Unity XR Interaction Toolkit 开发教程(3)快速配置交互:移动、抓取、UI交互【3.0以上版本】

获取完整课程以及答疑&#xff0c;工程文件下载&#xff1a; https://www.spatialxr.tech/ 视频试看链接&#xff1a; 3.快速配置交互&#xff1a;移动、抓取、UI交互【Unity XR Interaction Toolkit 跨平台开发教程】&#xff08;3.0以上版本&#xff09; 系列教程专栏&…