C标准输入与标准输出——stdin,stdout

news2024/11/24 3:36:59

   🔗 《C语言趣味教程》👈 猛戳订阅!!!

—— 热门专栏《维生素C语言》的重制版 ——

  • 💭 写在前面:这是一套 C 语言趣味教学专栏,目前正在火热连载中,欢迎猛戳订阅!本专栏保证篇篇精品,继续保持本人一贯的幽默式写作风格,当然,在有趣的同时也同样会保证文章的质量,旨在能够产出 "有趣的干货" !本系列教程不管是零基础还是有基础的读者都可以阅读,可以先看看目录! 标题前带星号 (*) 的部分不建议初学者阅读,因为内容难免会超出当前章节的知识点,面向的是对 C 语言有一定基础或已经学过一遍的读者,初学者可自行选择跳过带星号的标题内容,等到后期再回过头来学习。值得一提的是,本专栏 强烈建议使用网页端阅读! 享受极度舒适的排版!你也可以展开目录,看看有没有你感兴趣的部分!希望需要学 C 语言的朋友可以耐下心来读一读。最后,可以订阅一下专栏防止找不到。

" 有趣的写作风格,还有特制的表情包,而且还干货满满!太下饭了!"

—— 沃兹基硕德

目录

Ⅰ. 输入和输出(Input & Output)

0x00 引入:I/O 的概念

0x01 标准 I/O 流

0x01 回顾:标准输入输出库 stdio.h

0x02 printf 函数初探

0x03 scanf 函数初探

0x04 常见报错 C4996:scanf 可能不安全

Ⅱ. 标准输出(stdout)

0x00 什么!printf 函数居然有返回值?

0x01 探索 printf 函数 “原型”

0x02 printf 支持格式化宽度 %xd

0x03 printf 浮点数精度控制

0x04 sprintf 函数

* 0x05 fprintf 函数

Ⅲ. 标准输入(stdin)

0x00 scanf 的返回值

0x01 scanf 自动跳过空白字符的 “特性”

* 0x02 缓冲区问题

* 0x03 scanf 函数安全性问题探讨

 0x04 sscanf 函数

 * 0x05 fscanf 函数


Ⅰ. 输入和输出(Input & Output)

0x00 引入:I/O 的概念

计算机中的输入和输出,简称 \color{}I/O,其中:

  • \color{}I 代表 Input,即输入。
  • \color{}O 代表 Output,即输出。

 IO 是指计算机系统与外部世界进行信息交流和数据传输的过程。

输入是指将外部信息引入计算机系统,而输出是将计算机系统处理后的信息传递回外部世界。

其本质是 计算机与外部世界之间的信息交流和数据传输过程。

0x01 标准 I/O 流

 C 语言中标准 I/O 流为 stdinstdout

它们分别用于标准输入和标准输出,stdin 就是输入,可以从键盘读取用户输入的内容,

 再利用 stdout 输出将结果打印到屏幕上,

(对于 stdin 和 stdout 的具体知识点我们将通过 printf 和 scanf 函数来展开讲解)

I/O 流的存在,使得 C 程序可以与用户进行交互,并通过控制台窗口进行输入和输出。

值得一提的是,在标准 C 库中,stdinstdout 是已经定义好的流,无需额外的设置或配置。

此外,还有一个标准错误流 stderr,用于将错误消息输出到屏幕,我们以后会讲解。

0x01 回顾:标准输入输出库 stdio.h

这里我们再回顾一下 C 标准库 <stdio.h>,其全名为 Standard Input/Output Library

(我们在第一章就介绍过该库了,既然本章我们展开学习输入输出,我们就重提一下)

是 C 语言中用于处理输入和输出操作的核心库之一,C语言本身是不自带输入输出的函数的。

​ 之所以叫做 stdio 是因为 standard input & output,而它表示了这库中最经典的两个函数:

  • printf:标准输入函数(input)
  • scanf:标准输出函数(output)

下面我们就先来介绍一下这两个函数,它们分别用来输入和输出!

0x02 printf 函数初探

在第一章中我们就简单介绍过这个函数了,我们在写第一个程序 HelloWorld 时就用到了它:

#include <stdio.h>

int main(void)
{
    printf("Hello, World!\n");

    return 0;
}

在使用 printf 函数之前,要添加 stdio.h 头文件,因为 printf 函数并不是 C 语言本身自带的。

对应了标准输出流 stdout 

💬 代码演示:printf 函数的用法

#include <stdio.h>
 
int main(void) 
{
    printf("Hello,World!\n");
    int a = 100;
    printf("a=%d", a);
 
    return 0;
}

🚩 运行结果如下:

 我们来看一下这个函数的 "原型":

int printf(const char* format [, argument] ...);

0x03 scanf 函数初探

对于输入,我们可以使用 C 标准库 stdio 中的 scanf 函数,针对标准输入流 stdin。

💬 代码演示:使用 scanf 接收用户输入的数据

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

🚩 运行结果如下:(假设用户输入 10 20)

其中 & 符号代表取地址,因为要读取数据,所以需要知道数据被存到了哪里。

 这里不带 & 则会 warning C4477: “scanf”: 格式字符串“%d”需要类型“int *”的参数,但可变参数 1 拥有了类型“int”。

这里学完指针之后,就能很好地理解了,对于初学者理解取地址的概念还是比较困难的。

scanf 函数需要使用 操作符来获取变量的地址,因为它需要知道在内存中存储用户输入的值的确切位置。

当你在 scanf 函数中使用一个变量作为参数时,你需要告诉 scanf 函数该变量在内存中的位置,以便将输入的值存储到正确的地方。这是通过使用 操作符来获取变量的地址来实现的。

例如,如果你有一个整数变量 x,要在 scanf 中读取它的值,我们就需要:

scanf("%d", &x);

(现在实在理解不了也没有关系,后续再回来理解即可)

0x04 常见报错 C4996:scanf 可能不安全

error C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

呵呵,这是 VS 编译器的安全提示,告诉我们输入的函数是不安全的,臭名昭著的 C4996!

大致意思就是告诉你:我 VS 觉得这个函数是不安全的,建议你用更安全的函数,于是乎......

VS 就推出了像 scanf_s 这样的函数,搞出了一揽子 _s 的版本,美名其曰 "安全版本的函数"。

所以,scanf_s 并不是标准 C 语言提供的,而是 VS 编译器提供的。

但考虑到代码跨平台,比如跨到 GCC 那,就会无法识别,这牺牲了代码的跨平台性和可移植性。

"仅个人观点,我觉得这完全是脱裤子放屁,弊大于利的!"

不想看到这种提示或不想听它喋喋不休的安全警告,解决方案也是多的一笔雕凿。

最常见的就是代码开头直接加上 #define _CRT_SECURE_NO_WARNINGS ,请阁下直接 CV:

#define _CRT_SECURE_NO_WARNINGS

不想每次创建新源文件都复制,想一劳永逸,可以在 VS 安装路径下搜索 newc++file.cpp 文件,

在文件开头添加这行代码,如此一来,每次创建新的源文件就会自动添加这玩意了。

还可以通过取消勾选安全开发生命周期 (SDL) 检查来解决,方法有很多这里就不多哔哔赖赖了。

Ⅱ. 标准输出(stdout)

0x00 什么!printf 函数居然有返回值?

"什么?printf 函数居然有返回值?"

 打开 MSDN,或者 C++ reference 我们可以看到:

int printf(const char* format [,argument]...);

首先我们可以看到 printf 函数是有返回值的,返回一个整型,表示成功打印的字符数。

我们先来试试接收一下 printf 函数的返回值,看看是否真的有这么个东西。

💬 代码演示:接收 printf 的返回值

#include <stdio.h>

int main(void)
{
    int ret = printf("Hello, World!\n");
    printf("%d", ret);

    return 0;
}

🚩 运行结果如下:

这里我们使用 ret 接收了调用 printf 之后的返回值,打印出来是 14,我们暂且不去关注它。

我们暂时只需要知道一点,就是 printf 函数是有返回值的,我们也用代码证明了这一点。

printf 输出输错错误时,会返回负值。

因此,我们可以通过检查 printf 的返回值来检测打印是否成功,返回值非负即打印成功。

通常情况下,我们并不需要关心它的返回值,因为 printf 函数在大多数情况下都会成功打印。

但在某些情况下,例如输出到一个已关闭的文件流或内存缓冲区已满的情况下,可能会失败。

💬 代码演示:判断 printf 函数是否打印成功

int res = printf("Hello, World!\n");

if (res >= 0) {
    printf("printf 成功打印了 %d 个字符。\n", result);
} 
else {
    printf("printf 打印失败。\n");
}

0x01 探索 printf 函数 “原型”

int printf(const char* format [,argument]...);

我们继续观察,其中 const char *format 是一个字符串参数,用于定义输出的格式。

包含了普通文本字符和格式控制符,格式控制符以百分号(%)开头,后面跟着一个字符,

表示将要输出的数据类型(如整数、浮点数、字符串等)以及如何格式化这些数据。

后面的 ... 表示 printf 函数可以接受任意数量的参数。

这些参数将与格式字符串中的格式控制符匹配,每个参数对应一个格式控制符,比如:

#include <stdio.h>

int main(void) 
{
    int a = 10;
    double b = 3.14159;

    printf("%d %f\n", a, b);
    
    return 0;
}

🚩 运行结果如下:

0x02 printf 支持格式化宽度 %xd

你可以在格式控制符中指定字段的宽度,以控制输出的对齐和填充: %xd

比如 %5d 表示输出一个宽度为 5 的整数字段,如果数字少于 5 位数,会在前面用空格进行填充。

printf("%5d\n", 42);

0x03 printf 浮点数精度控制

对于浮点数,而可以使用精度控制 .x 来限制小数点后面的位数:

printf("%.2lf\n", 3.14159);

其中,.2 表示保留两位小数,那么 printf 的结果将会是 3.14。

0x04 sprintf 函数

📂 头文件:#include <stdio.h>

📚 作用:把一个格式化的数据转换成字符串。

🔍 MSDN介绍:sprintf - C++ Reference

💬 代码演示:sprintf 的用法

#include <stdio.h>

struct S {
	char arr[10];
	int age;
	float f;
};

int main(void) {
	struct S s = { "hello", 20, 3.14f };
	char buffer[100] = { 0 }; // 用于存放

	sprintf(buffer, "%s %d %f", s.arr, s.age, s.f); // 把这些信息放到buffer中了
	printf("%s\n", buffer); // 将buffer打印出来

	return 0;
}

🚩 运行结果如下:

* 0x05 fprintf 函数

📂 头文件:#include <stdio.h>

📚 针对所有输出流的格式化输出语句 - stdout / 文件

🔍 MSDN介绍:fprintf - C++ Reference

💬 代码演示:随便创建一个文件,在文件中写入一段话

#include <stdio.h>

char data[] = "Hey, nice to meet you~";

int main(void) {

    FILE* pf = fopen("test1.txt", "w");
    if (pf == NULL) {
        perror("fopen");
        return 1;
    }
    // 使用fprintf写文件
    fprintf(pf, "%s", data);

    fclose(pf);
    pf = NULL;

    return 0;
}

🚩 (代码成功运行)

Ⅲ. 标准输入(stdin)

0x00 scanf 的返回值

我们还是来看看 scanf 的 "原型":

int scanf(const char* format [,argument]... );

我们可以看到,scanf 函数和 printf 函数一样,scanf 函数也是有返回值的。

  • 如果 scanf 成功读取了一个数据项 (按照格式字符串中的格式要求) ,则返回值为 1。这表示成功读取了一个数据项,并且该数据项已存储在相应的变量中。
  • 如果 scanf 未能成功读取任何数据项,即输入与格式字符串不匹配或者遇到了 EOF,则返回值为 0。
  • 如果在读取过程中发生错误,如无法打开文件或格式字符串中的格式不正确,返回值通常为 EOF(-1)。

对于具有多个格式化指令的 scanf 语句,返回值将是成功读取的数据项数量的总和。

举个例子,如果 scanf 语句包含两个 %d 格式化指令,而且成功读取了两个整数,返回值将是 2。

0x01 scanf 自动跳过空白字符的 “特性”

scanf 函数在 读取非字符串数据类型时会自动跳过空白字符 (空格、制表符、换行符等) 。

这意味着它会忽略输入中的空格等字符,直到找到一个非空白字符或达到格式字符串的结束。

💬 举个例子:scanf 自动跳过空白字符

int num1, num2;
scanf("%d %d", &num1, &num2);

用户可以在两个整数之间输入任意数量的空格、制表符或换行符,

scanf 都会正确读取这两个整数,可以自己放到编译器里,自己运行输入试试。

值得注意的是:虽然 scanf 会跳过空白字符,但它并不会在格式化指令中的空格之间进行跳过。

例如,如果格式字符串为 %d%d,那么输入中的空白字符将不会被跳过,会与格式精确匹配。

* 0x02 缓冲区问题

缓冲区问题在 C 语言中经常出现,尤其是在使用输入函数(如 scanf、gets 等)时。

这个问题主要涉及到输入函数与输入缓冲区之间的交互,可能会导致程序行为与预期不符。

以下是有关缓冲区问题的一些重要细节:

  • 输入缓冲区:输入函数(如 scanf)通常会将用户输入存储在一个缓冲区中,等待程序读取。这允许用户在按回车键之前输入多个字符,并且输入函数只会读取一个完整的数据项。缓冲区会自动刷新,将数据传递给程序。
  • 换行符(回车键):用户在终端输入时,通常会按下回车键(换行符)来提交输入。这个换行符也被存储在输入缓冲区中,并被看作是输入的一部分。

我们下面举一个使用 scanf 函数时出现的缓冲区问题的例子。

💬 代码演示:scanf 缓冲区问题

#include <stdio.h>

int main(void) 
{
    int num;
    printf("输入一个数字: ");
    scanf("%d", &num);
    printf("你输入了: %d\n", num);

    return 0;
}

💡 解读:如果用户输入 "42" 然后按下回车键,一切正常。但是,如果用户输入 "42abc" 然后按下回车键,scanf 将读取 "42" 作为整数,并将 "abc" 保留在输入缓冲区中,以供下一次输入使用,这可能导致未预期的行为。

🔍 解决方案:

  • 清空输入缓冲区:为了解决缓冲区问题,可以使用 fflush(stdin) 来清空输入缓冲区。然而,需要注意的是,fflush(stdin) 不是C标准的一部分,因此在不同的编译器和平台上表现可能不同,且可能不是可移植的方法。另外,fflush(stdin)在某些编译器中可能会导致未定义的行为,因此不建议使用。
  • 换一个安全的输入方法:为了避免缓冲区问题,可以使用安全的输入方法,如 fgets 函数读取一行输入,然后解析该行。这样可以更好地控制输入,并且不会留下未处理的字符在输入缓冲区中。

* 0x03 scanf 函数安全性问题探讨

scanf 函数的安全性问题主要涉及到缓冲区溢出和格式字符串漏洞。

首先是 缓冲区溢出,这个我们在刚才已经介绍过了。scanf 函数不提供对输入缓冲区大小的检查和限制,这意味着如果输入的数据超过了目标变量所分配的内存空间,就可能导致缓冲区溢出。这种情况可能会破坏程序的内存结构,导致程序崩溃或安全漏洞。

格式字符串漏洞:格式字符串参数在 scanf 中是非常强大的,但也容易受到恶意用户输入的攻击。如果用户能够控制格式字符串,就可以进行格式字符串漏洞攻击,可能导致程序信息泄漏、崩溃或被入侵。因此,应该避免使用来自用户的未经验证的格式字符串。

char format[20];
scanf("%s", format); // 恶意用户可以输入恶意格式字符串
scanf(format);       // 安全漏洞,用户可以控制程序行为

为了避免格式字符串漏洞,应该避免将用户输入直接用作格式字符串,或者使用格式化函数(如printf)时进行严格的格式化控制。

未处理的错误scanf 函数在输入不匹配格式字符串的情况下会返回失败,但它通常不提供足够的错误信息来帮助程序员精确定位问题。这可能导致难以调试的问题,尤其是在复杂的输入和格式字符串组合中。

缺乏输入验证scanf 不提供输入验证功能,因此程序员需要自行验证用户输入,以确保输入数据满足预期的条件。如果未进行适当的输入验证,可能会导致不安全的输入数据被接受。

因此,为了提高程序的安全性和可靠性,应该采取以下措施:

  • 使用带有长度限制的输入函数,如 fgets,以避免缓冲区溢出。
  • 不直接使用来自用户的输入作为格式字符串或者对格式字符串进行有效的验证。
  • 在使用 scanf 时,必要时可检查其返回值,以确保成功读取了所需的数据项。
  • 进行严格的输入验证,以确保输入数据满足预期的条件,防止不安全的输入被接受。
  • 在可能的情况下,使用更安全的输入函数或库,如 strtok、strtol 等,以减少潜在的安全风险。

 0x04 sscanf 函数

int sscanf (
    const char* buffer, 
    const char* format [, argument ] ...)

sscanf 函数比 scanf 多了一个 buffer。

📂 头文件:#include <stdio.h>

📚 作用:从一个字符串中读取一个格式化的数据。

🔍 MSDN介绍:sscanf - C++ Reference

💬 代码演示:利用 sscanf 从 buffer 字符串中还原出结构体的数据

#include <stdio.h>

struct S {
	char arr[10];
	int age;
	float f;
};

int main(void) {
	struct S s = { "hello", 20, 3.14f };
	struct S tmp = { 0 };

	char buffer[100] = { 0 };
	sprintf(buffer, "%s %d %f", s.arr, s.age, s.f); // 把这些信息放到buffer中了
	printf("%s\n", buffer);

	// 从buffer字符串中还原出一个结构体数据
	sscanf(buffer, "%s %d %f", tmp.arr, &(tmp.age), &(tmp.f));
	printf("%s %d %f\n", tmp.arr, tmp.age, tmp.f);

	return 0;
}

🚩 运行结果如下:

 * 0x05 fscanf 函数

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

 📂 头文件:#include <stdio.h>

📚 针对所有输入流的格式化输入语句 - stdin / 文件

🔍 MSDN介绍:fscanf - C++ Reference

💬 代码演示:fscanf 的用法

#include <stdio.h>

int data; // 存放读到的数据

int main(void) {
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL) {
        perror("fopen");
        return 1;
    }

    // 使用fscanf读文件
    fscanf(pf, "%d", &data);

    // 将读到的数据打印
    printf("%d\n", data);

    fclose(pf);
    pf = NULL;

    return 0;
}

 🚩 运行结果如下:

📌 [ 笔者 ]   王亦优 | 雷向明
📃 [ 更新 ]   2023.3.
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,
              本人也很想知道这些错误,恳望读者批评指正!

📜 参考文献:

- C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

- Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

- 百度百科[EB/OL]. []. https://baike.baidu.com/.

- 维基百科[EB/OL]. []. https://zh.wikipedia.org/wiki/Wikipedia

- R. Neapolitan, Foundations of Algorithms (5th ed.), Jones & Bartlett, 2015.

- B. 比特科技. C/C++[EB/OL]. 2021[2021.8.31]

- 林锐博士. 《高质量C/C++编程指南》[M]. 1.0. 电子工业, 2001.7.24.

- 陈正冲. 《C语言深度解剖》[M]. 第三版. 北京航空航天大学出版社, 2019.

- 侯捷. 《STL源码剖析》[M]. 华中科技大学出版社, 2002.

- T. Cormen《算法导论》(第三版),麻省理工学院出版社,2009年。

- T. Roughgarden, Algorithms Illuminated, Part 1~3, Soundlikeyourself Publishing, 2018.

- J. Kleinberg&E. Tardos, Algorithm Design, Addison Wesley, 2005.

- R. Sedgewick&K. Wayne,《算法》(第四版),Addison-Wesley,2011

- S. Dasgupta,《算法》,McGraw-Hill教育出版社,2006。

- S. Baase&A. Van Gelder, Computer Algorithms: 设计与分析简介》,Addison Wesley,2000。

- E. Horowitz,《C语言中的数据结构基础》,计算机科学出版社,1993

- S. Skiena, The Algorithm Design Manual (2nd ed.), Springer, 2008.

- A. Aho, J. Hopcroft, and J. Ullman, Design and Analysis of Algorithms, Addison-Wesley, 1974.

- M. Weiss, Data Structure and Algorithm Analysis in C (2nd ed.), Pearson, 1997.

- A. Levitin, Introduction to the Design and Analysis of Algorithms, Addison Wesley, 2003. - A. Aho, J. 

- E. Horowitz, S. Sahni and S. Rajasekaran, Computer Algorithms/C++, Computer Science Press, 1997.

- R. Sedgewick, Algorithms in C: 第1-4部分(第三版),Addison-Wesley,1998

- R. Sedgewick,《C语言中的算法》。第5部分(第3版),Addison-Wesley,2002

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

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

相关文章

【iVX】iVX的低代码未来发展趋势:加速应用开发的创新之路

简介&#xff1a; 随着数字化转型的飞速发展&#xff0c;企业和组织对快速开发和交付高质量应用的需求越来越迫切。低代码开发平台作为一种创新的解决方案&#xff0c;极大地简化了应用程序的开发过程。在这一领域&#xff0c;iVX低代码平台作为领先的创业公司&#xff0c;正在…

【kafka】kafka介绍

https://kafka.apachecn.org/intro.html Apache Kafka是一个分布式流处理平台。这到底意味着什么呢? 我们知道流处理平台需要具有以下三种特性&#xff1a; 可以发布和订阅流式的记录。这一方面与消息队列或者企业消息系统类似。可以储存流式的记录&#xff0c;并且有较好的…

初识自动驾驶技术之旅 第一课 学习笔记

​ &#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! ​ 目录 &#x1f4da; 前言 &#x1f4d8; 1. 自动驾驶人才需求与挑战 &#x1f4d8; 2. Apollo …

什么合同管理系统?4类合同管理软件评测

说到合同管理系统&#xff0c;前提还是弄清楚合同有哪些类型&#xff0c;合同管理有那些痛点&#xff0c;才好对症下药。 一、合同的类型和合同管理的痛点 从法律角度来说&#xff0c;合同可以分为&#xff1a;有名合同与无名合同、单务合同与双务合同、有偿合同与无偿合同、…

Redis7安装配置

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Java从入门到精通 ✨特色专栏&#xf…

硬件系统工程师宝典(39)-----如何使用ESD防护器件?

各位同学大家好&#xff0c;欢迎继续做客电子工程学习圈&#xff0c;今天我们继续来讲这本书&#xff0c;硬件系统工程师宝典。 上篇我们介绍了一些常用的视频接口DisplayPort、DVI和HDMI接口以及它们的特点。今天我们来讲一讲ESD防护器件。 1.ESD概念 ESD&#xff08;Electr…

约会怎么走到目的地最近呢?一文讲清所有最短路算法问题

&#x1f680;&#x1f680;&#x1f680;&#x1f680;&#x1f680;订阅专栏&#x1f449; 趣学算法(dog) &#x1f448; 带你学习算法原理 算法模板&#x1f680;&#x1f680;&#x1f680;&#x1f680;&#x1f680; write in front 朋友们好啊&#xff0c;好久没写过…

Android Studio开发入门教程:如何更改APP的图标?

更改APP的图标&#xff08;安卓系统&#xff09; 环境&#xff1a;Windows10、Android Studio版本如下图、雷电模拟器。 推荐图标库 默认APP图标 将新图标拉进src/main/res/mipmap-hdpi文件夹&#xff08;一般app的icon图标是存放在mipmap打头的文件夹下的&#xff09; 更改sr…

Java File类和IO流

1. File类 1.1 File对象创建 注意&#xff1a; 路径中"\"要写成"\\"&#xff0c; 路径中"/"可以直接用 File对象可以指代一个不存在的文件路径路径中带盘符是绝对路径&#xff0c;不带盘符是相对路径 1.2 File判断和获取方法 1.3 创建和删除方…

Kafka3.0.0版本——增加副本因子

目录 一、服务器信息二、启动zookeeper和kafka集群2.1、先启动zookeeper集群2.2、再启动kafka集群 三、增加副本因子3.1、增加副本因子的概述3.2、增加副本因子的示例3.2.1、创建topic(主题)3.2.2、手动增加副本存储 一、服务器信息 四台服务器 原始服务器名称原始服务器ip节点…

企业架构LNMP学习笔记15

客户端缓存&#xff1a; B/S架构里&#xff0c;Browser是浏览器&#xff0c;就是客户端。 客户端缓存告知浏览器获取服务段的信息是在某个区间时间段是有效的。 每次请求从服务器拿一遍数据&#xff0c;数据没有变化&#xff0c;影响带宽&#xff0c;影响时间。刷新又要去加载…

百度飞桨(武汉)人工智能产业赋能中心签约,推动AI技术与汉阳“1+6”产业深度融合

9月1日&#xff0c;“文心中国行”首站落地武汉汉阳。活动现场&#xff0c;武汉市汉阳区与百度正式签约&#xff0c;共同打造百度飞桨&#xff08;武汉&#xff09;人工智能产业赋能中心&#xff0c;助力武汉产业高质量跨越式发展。活动围绕“深入解读大模型产业实践&#xff0…

UWB学习——day1

UWB定义 UWB&#xff1a;Ultra Wideband&#xff08;超宽频&#xff09; UWB所谓的超宽频区别于其它近场通信技术可总结为时域上跳跃&#xff0c;频域上矮胖 从图中可以看出&#xff0c;时域上通过短且强的脉冲信号&#xff0c;频域上主要是超宽的频谱&#xff08;Spectrum&a…

979. 在二叉树中分配硬币;1136. 并行课程;759. 员工空闲时间

979. 在二叉树中分配硬币 核心思想&#xff1a;递归。定义dfs(node)&#xff0c;返回值为以当前节点为根节点的节点个数和硬币个数。 那么这棵树至少需要移入或者移出abs&#xff08;coins-nodes&#xff09;个硬币&#xff0c;也就是这么多步&#xff0c;然后累计它们的总和…

aarch64 arm64 部署 stable diffusion webui 笔记 【2】继续安装其他依赖 gfpgan

接上篇 aarch64 arm64 部署 stable diffusion webui 笔记 【1】准备 venv 安装pytorch 验证cuda_hkNaruto的博客-CSDN博客 编辑requirements_versions.txt&#xff0c;注释掉torch 启动webui.sh (venv) [rootceph3 stable-diffusion-webui]# useradd yeqiang useradd&#xf…

Pocket Yoga for mac:一个神奇的瑜伽助手,让你的身心更健康

Pocket Yoga for Mac&#xff08;口袋瑜伽&#xff09;是一款专为瑜伽爱好者设计的应用程序。无论您是初学者还是经验丰富的瑜伽修行者&#xff0c;这款应用都能帮助您在家中或办公室进行高效的瑜伽练习。 Pocket Yoga for Mac提供了一系列的瑜伽课程和练习&#xff0c;涵盖了不…

信息安全基础-技术体系-加密技术

系统安全 考点分析信息安全的基础知识&#xff08;重点&#xff09;信息安全系统的组成框架信息安全技术对称加密技术非对称加密对称密钥和非对称密钥对比 考点分析 一般不超纲 信息安全的基础知识&#xff08;重点&#xff09; 五个基本要素经常考察 机密性&#xff1a;加密报…

Python接口自动化测试框架介绍

之前在项目中搞了一套jmeter jenkins git ant接口自动化测试框架&#xff0c;在项目中运行了大半年了&#xff0c;效果还不错&#xff0c; 最近搞了一套requests unittest ddt pymysql BeautifulReport的接口自动化测试框架&#xff0c; 测试用例在yaml文件中&#xff0c…

Android后退堆栈

修改代码 现在的ItemClick使得用户单击其中一个项目时就会跳转&#xff0c;现在要修改其使得在一个小屏幕设备上才会这样做&#xff0c;在一个大屏幕设备上运行用户选择一个训练项目时在右边的片段显示响应的信息。 希望片段处理后退的方式&#xff1a;假设用户在手机上运行这…

游戏AI综述

1、游戏AI的特点 随着深度学习等技术的突破性进展&#xff0c;现代的人工智能技术进步神速&#xff0c;已经在自然语言处理、机器翻译和图像识别等众多方面取得了进步&#xff0c;而且已经影响到了现实生活。 如果把围棋也看作游戏&#xff0c;那么大名鼎鼎的AlphaGo系列人工…