C++第一章:开始

news2025/1/6 19:52:12

开始目录

  • 引言
  • 一、开发环境和参考书籍
  • 二、一个简单的C++程序
  • 三、初识输入和输出
    • 标准输入输出对象
  • 四、注释
  • 五、控制流
    • while循环
    • for循环
  • 六、数量不定数据的输入
  • 七、C++ 缩进和格式
  • 八、类简介
    • 使用一个类
    • 书店处理书籍信息程序
  • 九、术语表

引言

  • C++在人们的眼中通常是“复杂”一词的代表,但其实C++有严谨的体系结构,以C++构建起来的工程不仅严谨并且执行速度非常快。
  • 计算机科学本就是一门工程学科,C++就相当于是一种搭建房子的基础方法,学完C++我们将得到一把强而有力武器来武装我们自己。
  • 如果你想做游戏引擎开发,或者从事游戏相关行业,那么C++会是你最好的武器。当我在CSDN上不断查找C++相关知识,调试几十次程序依旧报错时,我知道我应该正视C++并且认真系统的去学习它了。
  • 本系列文章是我系统性学习C++的读书笔记,我具有C语言和Java编程基础。如果你没有编程基础,那么本文将引导你去思考:“我应该学会什么”。如果你和我一样,那么这会是一趟很美好的旅程!

一、开发环境和参考书籍

  • 本系列文章均使用Visual Studio2019编写、调试、运行程序,关于C++开发环境的配置不做阐述。
  • 本系列文章内容均参考数据《C++ Primer》第五版。

二、一个简单的C++程序

  • 本文将提及许多概念性的内容,比如函数是怎样定义的。如果你具有很丰富的编程经验,我想看一看也是非常好的,这将使你在一个全新的高度审视一门编程语言的本质。
  • 一个简单的C++程序如下:
int main()
{
	return 0;
}
  • 每个C++程序都包含一个或多个函数,其中一个必须命名为main,操作系统通过调用main来运行C++程序。
  • 一个函数的定义包含四部分:返回类型、函数名、形参列表、函数体,函数的定义格式如下:
返回值类型 函数名(参数列表)
{
	函数体
}
  • 参数列表用括号"()“包围,函数体使用花括号”{}“包围,其实 " { 函数体 } " 定义了一个语句块。C++中的语句以”;"结尾。
  • main函数的返回类型必须为int,即整数类型,这是一种内置类型,即C++语言自身定义的类型。
  • 本例main函数函数体里包含的语句只有一句,即 " return 0; " ,它的作用是结束函数的执行。由于main函数被定义为需要返回一个int类型的值,因此return语句即结束了函数的执行也需要返回一个值。函数将向调用者返回值,在本例中main函数返回了0,由于它的调用者是操作系统,因此它将返回给操作系统" 0 "。
  • 在大多数系统中,main函数的返回值被用来指示程运行的状态,返回0表示成功,非0返回值的含义由系统定义,通常用来指出错误的类型。
  • 数据的类型是一个重要的概念,它不仅定义了数据元素的内容,还定义了数据上可以进行的操作。
  • 程序所处理的数据都保存在变量中,每个变量都有自己的类型。
  • 改写程序,将main函数体中return语句的返回值修改为-1,程序运行后会得到如下结果:
    在这里插入图片描述

三、初识输入和输出

  • C++语言并未定义任何输入输出(IO)语句,而是包含了一个全面的标准库(standard library)来提供ID机制(以及很多其他设施)。
  • iostream库包含两个基础类型:istream和ostream。它们分别表示输入流和输出流。一个"流"就是一个字符序列,是从IO设备读出或写入IO设备的。术语"流"想要表达的是:随着时间的推移,字符是顺序生成或消耗的。

标准输入输出对象

  • 标准库定义了四个IO对象。为了处理输入,我们使用一个名为cin的istream类型对象,这个对象也被称为标准输入(standard input)。对于输出,我们使用一个名为cout的ostream类型对象,此对象也被称为标准输出(standard output)。标准库中还定义了其他两个ostream对象,名为cerr和clog,我们通常用cerr来输出警告和错误信息,因此它也被称为标准错误(standard error),而clog用来输出程序运行时的一般性消息。
  • 系统通常将程序所运行的窗口和上述输入输出对象关联起来。因此当我们读取cin时,数据将从程序正在运行的窗口读入。当我们向cout、cerr和clog写入数据时,将会写到同一个窗口。
  • 程序员使用cin输入消息、cout输出消息,但在操作系统看来,它应该使用cin读取用户的输入,使用cout写入到窗口上展示给用户。
  • 设计一个程序,使用标准输出提示用户输入,使用标准输入读取用户输入:
#include <iostream>

int main()
{
	std::cout << "请输入两个整数:";
	int n1, n2;
	std::cin >> n1 >> n2;
	std::cout << "它们的和为:" << n1 + n2;
	return 0;
}
  • 运行结果:
    在这里插入图片描述
  • 语句解析:
#include <iostream>
  • 这一行代码告诉编译器我们想要使用iostream库。语句尖括号中的名字指出了头文件(hander),"#include"指令和头文件的名字必须写在同一行中。通常情况下,#include指令必须出现在所有函数之外,我们一般将一个程序的所有#include指令都放在源文件的开始位置。
	std::cout << "请输入两个整数:";
	std::cin >> n1 >> n2;
	std::cout << "它们的和为:" << n1 + n2;
  • 语句"std::cout << “请输入两个整数:” “是一个表达式。在C++中一个表达式产生一个计算结果,它由一个或多个运算对象和(通常是)一个运算符组成。这条语句中的表达式使用了输出运算符”<<"在标准输出上打印消息。
  • "<<“运算符接受两个运算对象:左侧的运算对象必须是一个ostream对象,右侧对象是要打印的值,此运算符将给定的值写到给定的ostream对象中。输出运算符”<<"的计算结果就是其左侧运算对象,即计算结果就是我们写入给定值的那个ostream对象。
  • 语句"std::cout << “它们的和为:” << n1 + n2;“使用了两次输出运算符”<<",因为此运算符返回其左侧的运算对象,因此第一个运算符的结果成为了第二个运算符的左侧运算对象,这样我们就可以将输出对象连接起来。这条语句等价于:
	(std::cout << "它们的和为:") << n1 + n2;
  • 当然我们也可以将两次运算分开:
	std::cout << "它们的和为:";
	std::cout << n1 + n2;
  • "它们的和为"是一个字符串字面值常量,是用一对双引号包围的字符序列。而std::endl表示的endl是一个被称为操纵符的特殊值,将endl写入到标准输出对象的效果是:结束当前行,并将与设备关联的缓冲区(buffer)中的内容刷到设备中。缓冲刷新操作可以保证到目前为止程序所产生的所有输出真正的写入输出流中,而不是仅停留在内存中等待写入流。
  • 程序员常常在调试时添加打印语句,这类语句应该保证”一直“刷新流,否则如果程序崩溃,输出可能还留在缓冲区中,从而导致关于程序崩溃为止的错误推断。
  • "std::“前缀表示的是使用的cout和cin定义在名为std的命名空间中。标准库定义的所有名字都在命名空间std中。”::"符号为作用域运算符,作用是指出我们想使用的定义在哪个命名空间中。
  • 输入运算符">>"与输出运算符类似,接受一个istream作为其左侧运算对象,接受另一个对象作为其右侧运算对象。语句"std::cin >> n1 >> n2;"从给定的istream对象中读入数据,并保存进给定的对象中,输入运算符<<同样返回其左侧运算符对象作为其计算结果,因此上述语句等价于:
	std::cin >> n1;
	std::cin >> n2;
  • 有意思的是 “它们的和为:” 的类型是字符串字面值常量,而n1和n2的类型是int,但无论对于cin还是cout对象来说,它们之间够可以通过输入运算符>>和输出运算符<<进行运算。这是因为标准库定义了不同版本的输入输出运算符,来处理这些不同类型的运算对象。

四、注释

  • C++中有两种注释:单行注释和多行注释:
#include <iostream>

int main()
{
	// 单行注释
	/*
		多行注释
		我也是注释
	*/
	return 0;
}
  • 注释中的所有内容都将被编译器忽视。需要注意的是,注释界定符并不能嵌套,多行注释必须以 /* 开始,以 * / 结束。

五、控制流

  • 程序一般是顺序执行的,程序设计语言提供了多种不同的控制流语句,允许我们写出更为复杂的执行路径。

while循环

  • while循环伪代码如下,其中的"{}“表示代码块,如果循环体中只有一条语句,可以不写”{}"而直接在下一行写出循环语句。
while(判断条件)
{
	循环体
}

for循环

  • for循环和while循环一样使用花括号"{}“括起来的代码块来存储循环体(即循环语句集合),当只有一条循环语句时我们也可以取消代码块直接使用一条语句。for循环中 变量的定义 如"int i”,注意它只会在循环开始执行一次,以后循环都不会执行,并且定义的变量只在这个循环语句的代码块内有效(其作用域是循环的代码块)。
for(变量的定义;判断条件;变量的迭代)
{
	循环体
}
  • 所谓语句块(block)就是使用花括号包围的语句序列,语句块也是语句的一种,在任何要求使用语句的地方都可以使用语句块。
  • 运算符:<= 、+= 、++。 <=运算符比较左右两个数的大小,返回一个布尔值表示真假。+=是一种复合赋值运算符,此运算符将右侧的对象加到左侧运算对象上,它本质上与一个加法结合一个赋值是相同的。++是前缀递增运算符,会将运算对象的值增加1。

六、数量不定数据的输入

  • 如何读取数量不定的输入数据?实例代码如下:
#include <iostream>

int main()
{
	int value, sum = 0;
	while (std::cin >> value)
		sum += value;
	std::cout << sum;
	return 0;
}
  • 运行结果:
    在这里插入图片描述

  • 由于>>运算符返回的是左侧运算对象,因此循环检测的其实是std::cin。当我们使用一个istram对象作为条件时,其效果是检测流的状态,如果流是有效的,即流为遇到错误,那么检测成功。当遇到文件结束符(end-of-file)时,或遇到一个无效的输入(例如读入的值不是一个整数),istream对象的状态会变为无效。处于无效状态的istream对象会使条件变为假。

  • 当我们读取文件时,文件末尾会自带文件结束符,而当我们在控制台窗口输入时,在window平台下按住ctrl+z即可打印出文件结束符(即图中的^z,它们是一个整体)。再按下回车,这时就会将控制台中输入的内容送到输入缓冲区中,std::cin就会读取一个个int值出来(因为它们是被" "字符即空格分离的),然后进行循环,最后读取到文件结束符cin状态变为无效循环停止。

  • 我们说过当cin遇到无效类型时,也会变为无效状态,我们修改输入为" 1 2 3 4 a",运行结果如下:
    在这里插入图片描述

  • 编译器的一部分工作是寻找程序文本中的错误。编译器没有能力检查一个程序是否按照其作者的意图工作,但可以检查形式(form)上的错误。编译器最常见能检查出的错误有:语法错误、类型错误、声明错误。

七、C++ 缩进和格式

  • C++程序很大程度上是格式自由的,就比如main函数可写为:
int main()



{
	int value, sum = 0;
	while (std::cin >> value)
		sum += value;
	std::cout << sum;
	return 0;
}
  • 我们要根据程序的可读性去考虑程序的格式风格,思考它会对程序的可读性和易理解性有什么影响,而一旦选择了一种风格,就要坚持使用。

八、类简介

  • 我们通过定义一个类(class)来定义自己的数据结构,一个类定义了一个类型,以及与其相关联的一组操作。类类型(class type)。
  • 为了使用类必须了解三件事情:
  •  (1)类的名称是声明
  •  (2)类是在哪里定义的
  •  (3)类支持什么操作
  • 一般而言,类的作者决定了类类型对象上可以使用的所有操作。
  • 当我们调试程序时,可能需要反复从键盘输入,这是非常枯燥的。大多数操作系统支持文件重定向,这种机制允许我们将标准输入和标准输出与命名文件关联起来。

使用一个类

  • 类的代码如下(直接添加进VS STDIO项目即可,不用关心具体实现细节):
/*
 * This file contains code from "C++ Primer, Fifth Edition", by Stanley B.
 * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the
 * copyright and warranty notices given in that book:
 * 
 * "Copyright (c) 2013 by Objectwrite, Inc., Josee Lajoie, and Barbara E. Moo."
 * 
 * 
 * "The authors and publisher have taken care in the preparation of this book,
 * but make no expressed or implied warranty of any kind and assume no
 * responsibility for errors or omissions. No liability is assumed for
 * incidental or consequential damages in connection with or arising out of the
 * use of the information or programs contained herein."
 * 
 * Permission is granted for this code to be used for educational purposes in
 * association with the book, given proper citation if and when posted or
 * reproduced.Any commercial use of this code requires the explicit written
 * permission of the publisher, Addison-Wesley Professional, a division of
 * Pearson Education, Inc. Send your request for permission, stating clearly
 * what code you would like to use, and in what specific way, to the following
 * address: 
 * 
 *     Pearson Education, Inc.
 *     Rights and Permissions Department
 *     One Lake Street
 *     Upper Saddle River, NJ  07458
 *     Fax: (201) 236-3290
*/ 

/* This file defines the Sales_item class used in chapter 1.
 * The code used in this file will be explained in 
 * Chapter 7 (Classes) and Chapter 14 (Overloaded Operators)
 * Readers shouldn't try to understand the code in this file
 * until they have read those chapters.
*/

#ifndef SALESITEM_H
// we're here only if SALESITEM_H has not yet been defined 
#define SALESITEM_H

//#include "Version_test.h" 

// Definition of Sales_item class and related functions goes here
#include <iostream>
#include <string>

class Sales_item {
// these declarations are explained section 7.2.1, p. 270 
// and in chapter 14, pages 557, 558, 561
friend std::istream& operator>>(std::istream&, Sales_item&);
friend std::ostream& operator<<(std::ostream&, const Sales_item&);
friend bool operator<(const Sales_item&, const Sales_item&);
friend bool 
operator==(const Sales_item&, const Sales_item&);
public:
    // constructors are explained in section 7.1.4, pages 262 - 265
    // default constructor needed to initialize members of built-in type
#if defined(IN_CLASS_INITS) && defined(DEFAULT_FCNS)
    Sales_item() = default;
#else
    Sales_item(): units_sold(0), revenue(0.0) { }
#endif
    Sales_item(const std::string &book):
              bookNo(book), units_sold(0), revenue(0.0) { }
    Sales_item(std::istream &is) { is >> *this; }
public:
    // operations on Sales_item objects
    // member binary operator: left-hand operand bound to implicit this pointer
    Sales_item& operator+=(const Sales_item&);
    
    // operations on Sales_item objects
    std::string isbn() const { return bookNo; }
    double avg_price() const;
// private members as before
private:
    std::string bookNo;      // implicitly initialized to the empty string
#ifdef IN_CLASS_INITS
    unsigned units_sold = 0; // explicitly initialized
    double revenue = 0.0;
#else
    unsigned units_sold;  
    double revenue;       
#endif
};

// used in chapter 10
inline
bool compareIsbn(const Sales_item &lhs, const Sales_item &rhs) 
{ return lhs.isbn() == rhs.isbn(); }

// nonmember binary operator: must declare a parameter for each operand
Sales_item operator+(const Sales_item&, const Sales_item&);

inline bool 
operator==(const Sales_item &lhs, const Sales_item &rhs)
{
    // must be made a friend of Sales_item
    return lhs.units_sold == rhs.units_sold &&
           lhs.revenue == rhs.revenue &&
           lhs.isbn() == rhs.isbn();
}

inline bool 
operator!=(const Sales_item &lhs, const Sales_item &rhs)
{
    return !(lhs == rhs); // != defined in terms of operator==
}

// assumes that both objects refer to the same ISBN
Sales_item& Sales_item::operator+=(const Sales_item& rhs) 
{
    units_sold += rhs.units_sold; 
    revenue += rhs.revenue; 
    return *this;
}

// assumes that both objects refer to the same ISBN
Sales_item 
operator+(const Sales_item& lhs, const Sales_item& rhs) 
{
    Sales_item ret(lhs);  // copy (|lhs|) into a local object that we'll return
    ret += rhs;           // add in the contents of (|rhs|) 
    return ret;           // return (|ret|) by value
}

std::istream& 
operator>>(std::istream& in, Sales_item& s)
{
    double price;
    in >> s.bookNo >> s.units_sold >> price;
    // check that the inputs succeeded
    if (in)
        s.revenue = s.units_sold * price;
    else 
        s = Sales_item();  // input failed: reset object to default state
    return in;
}

std::ostream& 
operator<<(std::ostream& out, const Sales_item& s)
{
    out << s.isbn() << " " << s.units_sold << " "
        << s.revenue << " " << s.avg_price();
    return out;
}

double Sales_item::avg_price() const
{
    if (units_sold) 
        return revenue/units_sold; 
    else 
        return 0;
}
#endif
  • 主程序:
#include <iostream>
#include "H/Sales_item.h"
int main()
{
	Sales_item item1, item2;
	std::cin >> item1 >> item2;
	if (item1.isbn() == item2.isbn())
	{
		std::cout << item1 + item2;
	}
	return 0;
}
  • item.isbn() 调用了Sales_item类对象item的成员函数,成员函数是定义为类的一部分的函数,有时也叫方法。其中".“符号表示点运算符,点运算符只能用于类类型的对象,即”."左侧必须是类类型对象,右侧是该类型对象的一个成员名,运算结果为右侧运算对象指定的成员。
  • 当我们使用点运算符".“调用成员函数时,我们使用调用运算符”()"来调用一个函数。调用运算符是一对圆括号。

书店处理书籍信息程序

  • 编写一个程序,包含类Sales_item。通过输入 唯一ID编号、销售数量、销售单价 来输入一个类对象的信息。一种书籍可能销售多次,即连续读入的书籍对象可能是一本书,如果它们的唯一ID相同,我们就把它们相加。最后输出所有书籍统计出的销售信息,格式为:ID号、销售总量、销售总额、平均单价。
#include <iostream>
#include "H/Sales_item.h"
int main()
{
	// 定义第一本书籍类对象item1
	Sales_item item1;
	// 处理数据信息
	if(std::cin >> item1)
	{
		// 定义第二本书籍类对象item2
		Sales_item item2;
		while (std::cin >> item2)
		{
			// 如果两本书的IBN编号一样(即是一本书)
			if (item1.isbn() == item2.isbn())
				// 合并记录
				item1 += item2;
			else
				// 否则直接输出第一本书的信息
				std::cout << item1 << std::endl;
		}
		// 当没有第二本书时直接输出第一本书的信息
		std::cout << item1 << std::endl;
	}
	// 如果一本数据的信息都没有
	else
	{
		// 提示错误
		std::cerr << "No data!" << std::endl;
		// 返回-1表示处理失败
		return -1;
	}
	return 0;
}
  • 运行结果:
    在这里插入图片描述
  • 如果没有书籍数据:
    在这里插入图片描述

九、术语表

  • 参数(实参):向函数传递的值
  • 赋值,抹去一个对象的当前值,用一个新值取代
  • 缓冲区:一个存储区域,用于保存数据。IO设施通常将输入或输出数据保存在一个缓冲区中,读写缓冲区的动作与程序中的动作是无关的。我们可以显式的刷新缓冲,以便强制将缓冲区中的数据写入输出设备。默认情况下,读cin会刷新cout缓冲;程序非正常终止也会刷新cout。
  • 记住在调试输出的最后记得写endl,因为它会将与设备关联的缓冲区(buffer)中的内容刷新到设备中。缓冲刷新保证了到目前为止程序的所有输出都真正写入输出流中,而不是仅停留在内存中等待写入流。
  • 默认情况下写到cerr的数据是不缓存的,写到clog的数据是被缓冲的。
  • 条件:0表示假,非零值表示真。
  • 花括号:划定程序块的边界。
  • 数据结构:数据及其上所允许的操作的一种逻辑组合。
  • 编辑-编译-调试:使程序能正确执行的开发过程。
  • 文件结束符:系统特定的标识,指出文件中无更多数据了。
  • 头文件:使类或其他名字的定义可被多个程序使用的一种机制。程序通过 #include 指令使用头文件。
  • 初始化:在一个对象创建的时候就给它赋值。
  • 源文件:包含C++程序的文件。

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

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

相关文章

软考高级架构师笔记-4中间件、嵌入式技术

目录 1. 前言 & 考情分析2. 中间件3. 微处理器4. 嵌入式软件5. 嵌入式系统6. 嵌入式软件设计6. 结语1. 前言 & 考情分析 前文回顾: 软考高级架构师笔记-1计算机硬件软考高级架构师笔记-2计算机软件(操作系统)软考高级架构师笔记-3数据库本章考情: 本章节偶尔会考到…

多电商平台订单整合,库存同步ERP系统,为何不用电商API对接?

还有不到1个月就是618购物狂欢节了&#xff0c;这个节日对很多电商来说是重头戏&#xff0c;一年中销售额暴涨的机会。现在电商们会在多平台开直播&#xff0c;挂小黄车&#xff0c;如抖音、拼多多、小红书等。数据资源大户电商们通常会把这些不同类型的海量数据分散存储在各个…

如何快速使用 WeUI 组件库?

1、如何快速应用 WeUI 组件库 快速应用 WeUI 组件库的步骤如下&#xff1a; 1、进入即时设计社区资源广场&#xff1a;访问即时设计社区资源广场&#xff0c;该资源广场提供免费使用的 WeUI 组件库&#xff0c;包括深色版和浅色版。设计师可以根据产品风格选择合适的组件库。…

[C++]octomap安装后测试

测试环境&#xff1a; vs2019 octomap1.9.6 release x64 代码&#xff1a; #include <octomap/octomap.h> #include <octomap/OcTree.h> using namespace std; using namespace octomap; void print_query_info(point3d query, OcTreeNode* node) { if (…

使用JS来实现轮播图的效果

最好今天分享一个使用JS制作的轮播图效果 个人名片&#xff1a; &#x1f60a;作者简介&#xff1a;一名大一在校生&#xff0c;web前端开发专业 &#x1f921; 个人主页&#xff1a;几何小超 &#x1f43c;座右铭&#xff1a;懒惰受到的惩罚不仅仅是自己的失败&#xff0c;…

mjpg-streamer实现细节分析

mjpg-streamer实现细节分析 文章目录 mjpg-streamer实现细节分析输入初始化input_initinit_videoIninit_v4l2 启动摄像头输入线程cam_threaduvcGrabcompress_yuyv_to_jpegmemcpy_picture 输出初始化output_init启动摄像头输出线程server_thread设置 SO_REUSEADDR 选项。设置 IP…

数据库 查询执行(1) 多路归并

用户输入一个sql语句 sql解析器 将sql语句转换成一个 关系代数 但是同时也会附加一些 操作 (下方未体现)。 外存排序 原理 外部数据元素太多无法一次性的读入内存 通常设计者 会让磁盘块的大小和缓冲区的大小相等 。 首先构造初始的归并段 分别从横向和纵向 体会这…

单片机GD32F303RCT6 (Macos环境)开发 (二十七)—— 蓝牙透传模块HC-08的调试

蓝牙透传模块HC-08的调试 1、模块为汇承HC-08&#xff0c;GD32我们之前已经把usart1 配置成了dmaidle的方式接收数据&#xff0c;我们的hc-08模块连接的就是这一路usart。 所以&#xff0c;与GD32的连接比较简单&#xff0c;如下图&#xff1a; GD32 HC-08 TX(PA2 ) RX RX(PA3…

弘基笔记本电脑怎么使用U盘重装系统?

弘基笔记本电脑怎么使用U盘重装系统&#xff1f;有的用户的弘基笔记本电脑使用过程中出现了蓝屏的情况&#xff0c;系统频繁的出现蓝屏问题导致自己的使用受到了影响&#xff0c;那么这个情况怎么去进行问题的解决呢&#xff1f;一起来看看以下的解决方法吧。 准备工作&#xf…

挂耳式蓝牙耳机排行,四款挂耳式耳机盘点

现在耳机的更新换代也是相当快的&#xff0c;普通的入耳式耳机在长期佩戴的舒适度方面饱受诟病&#xff0c;所以新近流行的开放式耳机很好的避免这个问题&#xff0c;它拥有不入耳不伤耳佩戴设计&#xff0c;解放双耳的同时也更不易丢失。面对市面上款式多样的开放式耳机&#…

Qt基础 自定义消息框

ps&#xff1a;忘记copy那位大佬tip代码了&#xff0c;后面新增可以点选的控件 #pragma once#include <QWidget> #include <QHBoxLayout>#define SHADOW_WIDTH 15 // 窗口阴影宽度; #define TRIANGLE_WIDTH 15 // 小三角的宽度; #de…

优化 docker 容器性能慢问题

问题&#xff1a; 部署环境下tomcat容器启动缓慢&#xff0c;耗时10多分钟&#xff0c;性能较差&#xff0c;同时后端服务响应较慢。 排查&#xff1a; 宿主环境&#xff1a; docker使用情况&#xff1a; 对比结果CPU、内存使用率都不高。 针对docker环境进行检查&#xff…

浅析变电站无人值守管理的模式与特点

安科瑞虞佳豪 近年来&#xff0c;随着电网的发展&#xff0c;变电站实行无人值班管理模式已成为电网的发展方向。自1998年始&#xff0c;辉县市就开始了变电站综合自动化改造&#xff0c;截止目前全局所属24座变电站&#xff08;其中35kV19座、110kV5座&#xff09;已全部实现…

对话 ONES 联合创始人兼 CTO 冯斌:技术管理者如何打造一支自驱型团队?

熟悉冯斌的人&#xff0c;大都直接称呼其网名 Kid&#xff0c;包括他在 ONES 的同事。人如其名&#xff0c;Kid 的寓意就是「用孩子的眼光看世界」&#xff0c;返璞归真的思维方式才能发现新大陆。正如毕加索说的&#xff1a;「我一生都在向孩子学习。」 在 ONES 联合创始人兼…

基因注释R包——annotatr介绍

目录 简介安装annotatr包使用annotatr进行注释CpG注释基因注释自定义注释读取基因组区域注释区域 简介 下一代测序实验和生物信息学管道产生的基因组区域在注释基因组特征时更有意义。出现在外显子或增强子中的SNP可能比出现在基因间区域的SNP更令人感兴趣。有趣的是&#xff…

Tomcat安装与启动和配置

目录 Tomcat 简介 Tomcat 安装 Tomcat 启动和配置 文件夹作用 启动&#xff0c;关闭Tomcat&#xff1b; 常见问题 配置 环境变量 IDEA中配置Tomcat Tomcat 简介 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在…

CSDN铁粉攻略

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

DataX-一款稳定高效的数据同步工具-从安装、启动、配置、使用总结,看这篇让你一步到位

前言 大数据部门现阶段ETL按同步方式分为两种&#xff1a; 实时同步&#xff1a;DTS、CloudCanal离线同步&#xff1a;dataworks-DI节点 但CloudCanal在使用中出现了部分问题&#xff0c;归纳总结后主要为以下几点&#xff1a; 部分使用场景获取不到binlog点位停止任务&…

【面试题】中高级前端工程师都需要熟悉的技能--前端缓存

前端缓存 一、前言二、web缓存分类1. HTTP缓存&#xff1a;2. 浏览器缓存&#xff1a;3. Service Worker&#xff1a;4. Web Storage缓存&#xff1a;5. 内存缓存&#xff1a; 三、http缓存详解1、http缓存类型a. 基于有效时间的缓存控制&#xff1a;b. 基于资源标识的缓存&…

从复杂到简单:通用CRM客户管理系统改变企业管理方式

一、概述 CRM客户管理系统是通过对客户生命周期的有效管理&#xff0c;是一种重要的客户管理工具&#xff0c;可以帮助企业更好的了解客户的需求&#xff0c;提升客户满意度&#xff0c;优化销售流程、提高销售业绩等&#xff0c;随着数字经济的不断发展和普及&#xff0c;CRM…