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

   🔗 《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.mzph.cn/news/69871.shtml

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

相关文章

iOS系统下轻松构建自动化数据收集流程

在当今信息爆炸的时代&#xff0c;我们经常需要从各种渠道获取大量的数据。然而&#xff0c;手动收集这些数据不仅耗费时间和精力&#xff0c;还容易出错。幸运的是&#xff0c;在现代科技发展中有两个强大工具可以帮助我们解决这一问题——Python编程语言和iOS设备上预装的Sho…

动态规划之简单多状态

简单多状态 1. 按摩师&#xff08;easy&#xff09;2. 打家劫舍II &#xff08;medium&#xff09;3. 删除并获得点数&#xff08;medium&#xff09;4. 买卖股票的最佳时机含冷冻期&#xff08;medium&#xff09;5. 买卖股票的最佳时机III&#xff08;hard&#xff09; 1. 按…

c++(c语言)通用版本的单链表的头插法创建

我们创建一个长度为n的链表时&#xff0c;可以采取头插法创建或者尾插法创建&#xff0c;本篇博客我们采取头插法来创建&#xff0c;&#xff08;作者只学了头插&#xff0c;尾插等以后来补qwq)。 我们先来画图来看看头插的创建形式把&#xff0c;会了原理再写代码。 首先是我…

自定义TimeLine实现卡拉OK轨

系列文章目录 自定义TimeLine 自定义TimeLine 系列文章目录前言正文UI部分代码部分Data&#xff08;数据&#xff09;Clip&#xff08;片段&#xff09;Track&#xff08;轨道&#xff09;Mixer&#xff08;混合&#xff09;被控制物体 总结 前言 自定义TimeLine实际上就是自定…

Redis缓存的高并发问题

Redis 做缓存虽减轻了 DBMS 的压力&#xff0c;减小了 RT&#xff0c;但在高并发情况下也是可能会出现各 种问题的。 1 缓存穿透 当用户访问的数据既不在缓存也不在数据库中时&#xff0c;就会导致每个用户查询都会“穿透” 缓存“直抵”数据库。这种情况就称为缓存穿透。一个…

OpenCV(十):图像缩放、翻转、拼接的介绍与使用

目录 &#xff08;1&#xff09;图像缩放&#xff1a;resize() &#xff08;2&#xff09;图像翻转&#xff1a; flip() &#xff08;3&#xff09;图像拼接&#xff1a;hconcat() 和vconcat() &#xff08;1&#xff09;图像缩放&#xff1a;resize() 使用 cv2.resize() 函…

sql:SQL优化知识点记录(十一)

&#xff08;1&#xff09;用Show Profile进行sql分析 新的一个优化的方式show Profile 运行一些查询sql&#xff1a; 查看一下我们执行过的sql 显示sql查询声明周期完整的过程&#xff1a; 当执行过程出现了下面这4个中的时&#xff0c;就会有问题导致效率慢 8这个sql创建…

搬家快递服务小程序的便利性

在当今快节奏的生活中&#xff0c;搬家可能是很多人都需要面对的问题。无论是新房子还是新办公室&#xff0c;都需要高效、便捷的搬家服务。本文将介绍如何使用第三方小程序制作平台&#xff0c;如乔拓云平台&#xff0c;开发一款高效便捷的搬家服务小程序。 1. 注册登录第三方…

【易售小程序项目】修改“我的”界面前端实现;查看、重新编辑、下架自己发布的商品【后端基于若依管理系统开发】

文章目录 “我的”界面修改效果界面实现界面整体代码 查看已发布商品界面效果商品数据表后端上架、下架商品ControllerMapper 界面整体代码back方法 编辑商品、商品发布、保存草稿后端商品校验方法Controller 页面整体代码 同项目其他文章 “我的”界面修改 效果 界面实现 界…

【C++设计模式】详解装饰模式

2023年8月31日&#xff0c;周四上午 这是我目前碰到的最难的设计模式..... 非常难以理解而且比较灵活多半&#xff0c;学得贼难受&#xff0c;写得贼费劲..... 2023年8月31日&#xff0c;周四晚上19:48 终于写完了&#xff0c;花了一天的时间来学习装饰模式和写这篇博客。 …

序列到序列学习(seq2seq)

permute(1,0,2)&#xff0c;将batch_size 放在中间state 最后一个时刻&#xff0c;每个层的输出

数学建模--Subplot绘图的Python实现

目录 1.Subplot函数简介 2.Subplot绘图范例1:绘制规则子图 3.Subplot绘图范例2:绘制不规则子图 4.Subplot绘图范例3:gridspec辅助实战1 5.Subplot绘图范例4:gridspec辅助实战2 1.Subplot函数简介 """ 最近在数学建模种需要绘制多张子图,发现对于subplot函…

QT文件对话框,将标签内容保存至指定文件

一、主要步骤 首先&#xff0c;通过getSaveFileName过去想要保存的文件路径及文件名&#xff0c;其次&#xff0c;通过QFile类实例化一个文件对象&#xff0c;再读取文本框中的内容&#xff0c;最后将读取到的内容写入到文件中&#xff0c;最后关闭文件。 1.txt即为完成上述操作…

laragon 为 php 安装 Xdebug 扩展

众所周知&#xff0c;php 自带的 var_dump() 输出格式很不直观 而 laragon 作为很好的 windos 下开发环境很受欢迎&#xff0c;本文就介绍如何快速为 laragon 的 php 安装 Xdebug&#xff0c;方便开发调试 一&#xff1a;启动开发环境&#xff0c;在任意可访问 php 页面中输出 …

蓝桥杯备赛(Day5)——二叉树

二叉树存储 普通做法,二叉树一个节点包括结点的数值以及指向左右子节点的指针 在class Node中 def __init__(self,s,l=None,r=None):self.val=Noneself.l=lself.r=r 在竞赛中,我们往往使用静态数组实现二叉树,定义一个大小为N的静态结构体数组,使用其来存储一棵二叉树。…

python 学习笔记(4)—— webdriver 自动化操作浏览器(基础操作)

安装 web driver&#xff1a; 使用 driver 前&#xff0c;需要下载与浏览器版本相对应的 driver。如要在 Chrome 浏览器上操作&#xff0c;就要下载Chrome Driver。 几个常用浏览器的参考和下载地址&#xff1a; Edge Driver&#xff1a;https://developer.microsoft.com/en…

密码学入门——环游密码世界

文章目录 参考书目一、基本概念1.1 本书主要角色1.2 加密与解密 二、对称密码与公钥密码2.1 密钥2.2 对称密码和公钥密码2.3 混合密码技术 三、其他密码技术 参考书目 图解密码技术 第三版 一、基本概念 1.1 本书主要角色 1.2 加密与解密 加密 解密 密码破译 二、对称密…

Ansible之playbook详解和应用实例

目录 一、playbook简介 1.什么是playbook 2.playbook组成 二、应用实例 1.使用playbook安装启用httpd服务 2.使用playbook安装启用nginx服务 三、ansible-playbook其他用法 1.检查yaml文件的语法是否正确 2.检查tasks任务 3.检查指定的主机 4.指定从某个task开始运行…

Playwright for Python:断言

一、支持的断言 Playwright支持以下几种断言&#xff1a; 断言描述expect(locator).to_be_checked()复选框被选中expect(locator).to_be_disabled()元素是禁用状态expect(locator).to_be_editable()元素是可编辑状态expect(locator).to_be_empty()容器是空的expect(locator).…

Python列表排序

介绍一个关于列表排序的sort方法&#xff0c;看下面的案例&#xff1a; """ 列表的sort方法来对列表进行自定义排序 """# 准备列表 my_list [["a", 33], ["b", 55], ["c", 11]]# 排序&#xff0c;基于带名函数 …