C++ Primer 第三章 Strings, Vectors, and Arrays

news2025/2/2 18:47:14

C++ Primer 第三章 Strings, Vectors, and Arrays

  • 3.1. Namespace using Declarations
  • 3.2. Library string Type
    • 3.2.1. Defining and Initializing strings
      • Direct and Copy Forms of Initialization
    • 3.2.2. Operations on strings
      • Reading and Writing strings
      • Using getline to Read an Entire Line
      • The string empty and size Operations
      • Comparing strings
      • Assignment for strings
      • Adding Two strings
      • Adding Literals and strings
    • 3.2.3. Dealing with the Characters in a string
      • Range-Based for
      • Change the Characters in a string
      • Processing Only Some Characters
  • 3.3. Library vector Type
    • 3.3.1. Defining and Initializing vectors
      • List Initializing a vector
      • Creating a Specified Number of Elements
      • Value Initialization
      • List Initializer or Element Count
    • 3.3.2. Adding Elements to a vector
      • vectors Grow Efficiently
    • 3.3.3. Other vector Operations
      • Computing a vector Index
      • Subscripting Does Not Add Elements
  • 3.4. Introducing Iterators
    • 3.4.1. Using Iterators
      • Iterator Operations
      • Iterator Types
      • The begin and end Operations
    • 3.4.2. Iterator Arithmetic
  • 3.5. Arrays
    • 3.5.1. Defining and Initializing Built-in Arrays
      • Complicated Array Declarations
    • 3.5.3. Pointers and Arrays
      • The Library begin and end Functions
      • Pointer Arithmetic
      • Subscripts and Pointers
  • 3.6. Multidimensional Arrays
    • Using a Range for with Multidimensional Arrays
    • Pointers and Multidimensional Arrays

3.1. Namespace using Declarations

Namespaces

  • A using declaration lets us use a name from a namespace without qualifying the name with a namespace_name :: prefix.
using namespace::name;
  • Code inside headers ordinarily should not use using declarations.

3.2. Library string Type

  • A string is a variable-length sequence of characters.

  • To use the string type, we must include the string header.

  • Because it is part of the library, string is defined in the std namespace.

#include <string>
using std::string;

3.2.1. Defining and Initializing strings

string s1; // default initialization; s1 is the empty string
string s2 = s1; // s2 is a copy of s1
string s3 = "hiya"; // s3 is a copy of the string literal
string s4(10, 'c'); // s4 is cccccccccc

在这里插入图片描述

Direct and Copy Forms of Initialization

  • When we initialize a variable using =, we are asking the compiler to copy initialize the object by copying the initializer on the right-hand side into the object being created.

  • Otherwise, when we omit the =, we use direct initialization.

  • When we have a single initializer, we can use either the direct or copy form of initialization.

  • When we initialize a variable from more than one value, such as in the initialization of s4 above, we must use the direct form of initialization:

string s5 = "hiya"; // copy initialization
string s6("hiya"); // direct initialization
string s7(10, 'c'); // direct initialization; s7 is cccccccccc
string s8 = string(10, 'c'); // copy initialization; s8 is cccccccccc

Difference between direct and copy Initialization: Is there a difference between copy initialization and direct initialization?

3.2.2. Operations on strings

1

Reading and Writing strings

// Note: #include and using declarations must be added to compile this code
int main()
{
string s; // empty string
cin >> s; // read a whitespace-separated string into s
cout << s << endl; // write s to the output
return 0;
}
  • The string input operator reads and discards any leading whitespace (e.g., spaces, newlines, tabs).

  • Like the input and output operations on the built-in types, the string operators return their left-hand operand as their result.

string s1, s2;
cin >> s1 >> s2; // read first input into s1, second into s2
cout << s1 << s2 << endl; // write both strings

Reading an Unknown Number of strings:

int main()
{
string word;
while (cin >> word) // read until end-of-file
cout << word << endl; // write each word followed by a new line
return 0;
}

Using getline to Read an Entire Line

This function reads the given stream up to and including the first newline and stores what it read—not including the newline—in its string argument.

If the first character in the input is a newline, then the resulting string is the empty string.

The string empty and size Operations

std::string::size

// read input a line at a time and discard blank lines
while (getline(cin, line))
if (!line.empty())
cout << line << endl;
string line;
// read input a line at a time and print lines that are longer than 80 characters
while (getline(cin, line))
if (line.size() > 80)
cout << line << endl;

Return: size returns a string::size_type value.

Although we don’t know the precise type of string::size_type, we do know that it is an unsigned type big enough to hold the size of any string.

Admittedly, it can be tedious to type string::size_type. Under the new standard, we can ask the compiler to provide the appropriate type by using auto or decltype.

auto len = line.size(); // len has type string::size_type

sizelength 相同,返回字符串长度(不包括末尾的空字符)。

Comparing strings

  • The equality operators (== and !=) test whether two strings are equal or unequal, respectively.

  • The relational operators <, <=, >, >= test whether one string is less than, less than or equal to, greater than, or greater than or equal to another.

  • These operators use the same strategy as a (case-sensitive) dictionary:

    • If two strings have different lengths and if every character in the shorter string is equal to the corresponding character of the longer string, then the shorter string is less than the longer one.

    • If any characters at corresponding positions in the two strings differ, then the result of the string comparison is the result of comparing the first character at which the strings differ.

Assignment for strings

string st1(10, 'c'), st2; // st1 is cccccccccc; st2 is an empty string
st1 = st2; // assignment: replace contents of st1 with a copy of st2
// both st1 and st2 are now the empty string

Adding Two strings

string s1 = "hello, ", s2 = "world\n";
string s3 = s1 + s2; // s3 is hello, world\n
s1 += s2; // equivalent to s1 = s1 + s2

Adding Literals and strings

string s1 = "hello", s2 = "world"; // no punctuation in s1 or s2
string s3 = s1 + ", " + s2 + '\n';

When we mix strings and string or character literals, at least one operand to each + operator must be of string type:

string s4 = s1 + ", "; // ok: adding a string and a literal
string s5 = "hello" + ", "; // error: no string operand
string s6 = s1 + ", " + "world"; // ok: each + has a string operand
string s7 = "hello" + ", " + s2; // error: can't add string literals
string s6 = (s1 + ", ") + "world";

The subexpression s1 + ", " returns a string, which forms the left-hand operand of the second + operator. It is as if we had written:

string tmp = s1 + ", "; // ok: + has a string operand
s6 = tmp + "world"; // ok: + has a string operand
string s7 = ("hello" + ", ") + s2; // error: can't add string literals

3.2.3. Dealing with the Characters in a string

cctype Functions:
cctype

Range-Based for

The body of a range for must not change the size of the sequence over which it is iterating.

for (declaration : expression)
statement
string str("some string");
// print the characters in str one character to a line
for (auto c : str) // for every char in str
	cout << c << endl; // print the current character followed by a newline

On each iteration, the next character in str will be copied into c.

string s("Hello World!!!");
// punct_cnt has the same type that s.size returns; see § 2.5.3 (p. 70)
decltype(s.size()) punct_cnt = 0;
// count the number of punctuation characters in s
for (auto c : s) // for every char in s
	if (ispunct(c)) // if the character is punctuation
		++punct_cnt; // increment the punctuation counter

cout << punct_cnt
	 << " punctuation characters in " << s << endl;

Change the Characters in a string

string s("Hello World!!!");
// convert s to uppercase
for (auto &c : s) // for every char in s (note: c is a reference)
	c = toupper(c); // c is a reference, so the assignment changes the char in s

cout << s << endl;

Processing Only Some Characters

if (!s.empty()) // make sure there's a character to print
	cout << s[0] << endl; // print the first character in s

3.3. Library vector Type

vector vs. list in STL
Standard Template Library Programmer’s Guide
C++ benchmark – std::vector VS std::list VS std::deque
c++ vector
STL Containers

  • A vector is a collection of objects, all of which have the same type.
  • A vector is a class template.
    Templates are not themselves functions or classes.
    Instead, they can be thought of as instructions to the compiler for generating classes or functions.
  • The process that the compiler uses to create classes or functions from templates is called instantiation.
vector<int> ivec; // ivec holds objects of type int
vector<Sales_item> Sales_vec; // holds Sales_items
vector<vector<string>> file; // vector whose elements are vectors

3.3.1. Defining and Initializing vectors

1

vector<int> ivec; // initially empty
// give ivec some values
vector<int> ivec2(ivec); // copy elements of ivec into ivec2
vector<int> ivec3 = ivec; // copy elements of ivec into ivec3
vector<string> svec(ivec2); // error: svec holds strings, not ints

List Initializing a vector

vector<string> articles = {"a", "an", "the"};

Creating a Specified Number of Elements

vector<int> ivec(10, -1); // ten int elements, each initialized to -1
vector<string> svec(10, "hi!"); // ten strings; each element is "hi!"

Value Initialization

vector<int> ivec(10); // ten elements, each initialized to 0
vector<string> svec(10); // ten elements, each an empty string

There are two restrictions on this form of initialization:

  1. Some classes require that we always supply an explicit initializer.
    If our vector holds objects of a type that we cannot default initialize, then we must supply an initial element value;

  2. When we supply an element count without also supplying an initial value, we must use the direct form of initialization.

List Initializer or Element Count

  • When we use parentheses, we are saying that the values we supply are to be used to construct the object.

  • When we use curly braces, {…}, we’re saying that, if possible, we want to list initialize the object.

vector<int> v1(10); // v1 has ten elements with value 0
vector<int> v2{10}; // v2 has one element with value 10
vector<int> v3(10, 1); // v3 has ten elements with value 1
vector<int> v4{10, 1}; // v4 has two elements with values 10 and 1
  • On the other hand, if we use braces and there is no way to use the initializers to list initialize the object, then those values will be used to construct the object.
vector<string> v5{"hi"}; // list initialization: v5 has one element
vector<string> v6("hi"); // error: can't construct a vector from a string literal
vector<string> v7{10}; // v7 has ten default-initialized elements
vector<string> v8{10, "hi"}; // v8 has ten elements with value "hi"

Although we used braces on all but one of these definitions, only v5 is list initialized.

3.3.2. Adding Elements to a vector

vector<int> v2; // empty vector
for (int i = 0; i != 100; ++i)
	v2.push_back(i); // append sequential integers to v2
// at end of loop v2 has 100 elements, values 0 . . . 99
// read words from the standard input and store them as elements in a vector
string word;
vector<string> text; // empty vector
while (cin >> word) {
	text.push_back(word); // append word to text
}

vectors Grow Efficiently

If differing element values are needed, it is usually more efficient to define an empty vector and add elements as the values we need become known at run time.

3.3.3. Other vector Operations

1


To use size_type, we must name the type in which it is defined. A vector type always includes its element type:

vector<int>::size_type // ok
vector::size_type // error

Computing a vector Index

// count the number of grades by clusters of ten: 0--9, 10--19, . .. 90--99, 100
vector<unsigned> scores(11, 0); // 11 buckets, all initially 0
unsigned grade;
while (cin >> grade) { // read the grades
	if (grade <= 100) // handle only valid grades
		++scores[grade/10]; // increment the counter for the current cluster
}

Subscripting Does Not Add Elements

vector<int> ivec; // empty vector
for (decltype(ivec.size()) ix = 0; ix != 10; ++ix)
	ivec[ix] = ix; // disaster: ivec has no elements
for (decltype(ivec.size()) ix = 0; ix != 10; ++ix)
ivec.push_back(ix); // ok: adds a new element with value ix

3.4. Introducing Iterators

3.4.1. Using Iterators

// the compiler determines the type of b and e; 
// b denotes the first element and e denotes one past the last element in v
auto b = v.begin(), e = v.end(); // b and e have the same type

Iterator Operations

1


string s("some string");
if (s.begin() != s.end()) { // make sure s is not empty
	auto it = s.begin(); // it denotes the first character in s
	*it = toupper(*it); // make that character uppercase
}

Iterator Types

vector<int>::iterator it; // it can read and write vector<int> elements
string::iterator it2; // it2 can read and write characters in a string
vector<int>::const_iterator it3; // it3 can read but not write elements
string::const_iterator it4; // it4 can read but not write characters

The begin and end Operations

If the object is const, then begin and end return a const_iterator; if the object is not const, they return iterator:

vector<int> v;
const vector<int> cv;
auto it1 = v.begin(); // it1 has type vector<int>::iterator
auto it2 = cv.begin(); // it2 has type vector<int>::const_iterator
auto it3 = v.cbegin(); // it3 has type vector<int>::const_iterator

3.4.2. Iterator Arithmetic

1

We can also subtract two iterators so long as they refer to elements in, or one off the end of, the same vector or string.

The result is the distance between the iterators.

The result type is a signed integral type named difference_type.

A classic algorithm that uses iterator arithmetic is binary search.

// text must be sorted
// beg and end will denote the range we're searching
auto beg = text.begin(), end = text.end();
auto mid = text.begin() + (end - beg)/2; // original midpoint
// while there are still elements to look at and we haven't yet found sought
while (mid != end && *mid != sought) {
	if (sought < *mid) // is the element we want in the first half?
		end = mid; // if so, adjust the range to ignore the second half
	else // the element we want is in the second half
		beg = mid + 1; // start looking with the element just after mid
	
	mid = beg + (end - beg)/2; // new midpoint
}

3.5. Arrays

  • Like a vector, an array is a container of unnamed objects of a single type that we access by position.

  • Unlike a vector, arrays have fixed size; we cannot add elements to an array.

3.5.1. Defining and Initializing Built-in Arrays

  • The dimension must be known at compile time, which means that the dimension must be a constant expression.
unsigned cnt = 42; // not a constant expression
constexpr unsigned sz = 42; // constant expression
// constexpr see § 2.4.4 (p. 66)
int arr[10]; // array of ten ints
int *parr[sz]; // array of 42 pointers to int
string bad[cnt]; // error: cnt is not a constant expression
string strs[get_size()]; // ok if get_size is constexpr, error otherwise
string strs[3];
  • We cannot use auto to deduce the type from a list of initializers.

  • As with vector, arrays hold objects. Thus, there are no arrays of references.

const unsigned sz = 3;
int ia1[sz] = {0,1,2}; // array of three ints with values 0, 1, 2
int a2[] = {0, 1, 2}; // an array of dimension 3
int a3[5] = {0, 1, 2}; // equivalent to a3[] = {0, 1, 2, 0, 0}
string a4[3] = {"hi", "bye"}; // same as a4[] = {"hi", "bye", ""}
int a5[2] = {0,1,2}; // error: too many initializers
int a2[] = {0, 1, 2}; // an array of three elements, not three-dimensional
  • Character arrays have an additional form of initialization: We can initialize such arrays from a string literal。
char a1[] = {'C', '+', '+'}; // list initialization, no null
char a2[] = {'C', '+', '+', '\0'}; // list initialization, explicit null
char a3[] = "C++"; // null terminator added automatically
const char a4[6] = "Daniel"; // error: no space for the null!

The dimension of a1 is 3; the dimensions of a2 and a3 are both 4. The definition of a4 is in error.

  • We cannot initialize an array as a copy of another array, nor is it legal to assign one array to another:

Complicated Array Declarations

int *ptrs[10]; // ptrs is an array of ten pointers to int
int &refs[10] = /* ? */; // error: no arrays of references
int (*Parray)[10] = &arr; // Parray points to an array of ten ints
int (&arrRef)[10] = arr; // arrRef refers to an array of ten ints
int *(&arry)[10] = ptrs; // arry is a reference to an array of ten pointers

3.5.3. Pointers and Arrays

  • When we use an array as an initializer for a variable defined using auto, the deduced type is a pointer, not an array:
int ia[] = {0,1,2,3,4,5,6,7,8,9}; // ia is an array of ten ints
auto ia2(ia); // ia2 is an int* that points to the first element in ia
ia2 = 42; // error: ia2 is a pointer, and we can't assign an int to a pointer
  • It is worth noting that this conversion does not happen when we use decltype. The type returned by decltype(ia) is array of ten ints:
// ia3 is an array of ten ints
decltype(ia) ia3 = {0,1,2,3,4,5,6,7,8,9};
ia3 = p; // error: can't assign an int* to an array
ia3[4] = i; // ok: assigns the value of i to an element in ia3

The Library begin and end Functions

arrays are not class types, so these functions are not functions. Instead, they take an argument that is an array:

int ia[] = {0,1,2,3,4,5,6,7,8,9}; // ia is an array of ten ints
int *beg = begin(ia); // pointer to the first element in ia
int *last = end(ia); // pointer one past the last element in ia

begin returns a pointer to the first, and end returns a pointer one past the last element in the given array. These functions are defined in the iterator header.

Pointer Arithmetic

int *b = arr, *e = arr + sz;
while (b < e) {
	// use *b
	++b;
}
int i = 0, sz = 42;
int *p = &i, *e = &sz;
// undefined: p and e are unrelated; comparison is meaningless!
while (p < e)

 

Although the utility may be obscure at this point, it is worth noting that pointer arithmetic is also valid for null pointers and for pointers that point to an object that is not an array.

If p is a null pointer, we can add or subtract an integral constant expression whose value is 0 to p.

In the latter case, the pointers must point to the same object, or one past that object.

Subscripts and Pointers

int *p = &ia[2]; // p points to the element indexed by 2
int j = p[1]; // p[1] is equivalent to *(p + 1),
// p[1] is the same element as ia[3]
int k = p[-2]; // p[-2] is the same element as ia[0]

3.6. Multidimensional Arrays

Strictly speaking, there are no multidimensional arrays in C++. What are commonly referred to as multidimensional arrays are actually arrays of arrays.

Using a Range for with Multidimensional Arrays

constexpr size_t rowCnt = 3, colCnt = 4;
int ia[rowCnt][colCnt];
size_t cnt = 0;
for (auto &row : ia) // for every element in the outer array
	for (auto &col : row) { // for every element in the inner array
		col = cnt; // give this element the next value
		++cnt; // increment cnt
}

note
To use a multidimensional array in a range for, the loop control variable for all but the innermost array must be references.

Had we neglected the reference and written these loops as:

for (auto row : ia)
	for (auto col : row)

our program would not compile.
As before, the first for iterates through ia, whose elements are arrays of size 4. Because row is not a reference, when the compiler initializes row it will convert each array element (like any other object of array type) to a pointer to that array’s first element.
As a result, in this loop the type of row is int*. The inner for loop is illegal. Despite our intentions, that loop attempts to iterate over an int*.

Pointers and Multidimensional Arrays

int ia[3][4]; // array of size 3; each element is an array of ints of size 4
int (*p)[4] = ia; // p points to an array of four ints
p = &ia[2]; // p now points to the last element in ia
// print the value of each element in ia, with each inner array on its own line
// p points to an array of four ints
for (auto p = ia; p != ia + 3; ++p) {
	// q points to the first element of an array of four ints; that is, q points to an int
	for (auto q = *p; q != *p + 4; ++q)
		cout << *q << ' ';
	
	cout << endl;
}
// p points to the first array in ia
for (auto p = begin(ia); p != end(ia); ++p) {
	// q points to the first element in an inner array
	for (auto q = begin(*p); q != end(*p); ++q)
		cout << *q << ' '; // prints the int value to which q points
	
	cout << endl;
}

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

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

相关文章

【图像处理】opencv | 形态学运算:腐蚀,膨胀,开运算,闭运算| 二值图像处理

文章目录前言一、腐蚀和膨胀1.1腐蚀1.2膨胀二、开运算与闭运算三、礼帽与黑帽前言 参考视频&#xff1a;opencv教学 参考教材&#xff1a;《数字图像处理基础》 我的代码基本是跟着B站的视频里面敲了一遍&#xff0c;然后结合教材对指定区域做了一些加强学习 一、腐蚀和膨胀 …

华为云APIArts:API全生命周期一体化解决方案,帮助您端到端呵护您的API

摘要&#xff1a;华为云API Arts是API设计、API开发、API测试、API托管、API运维、API变现一体化协作平台&#xff0c;通过维护API各开发阶段数据高度一致&#xff0c;支持开发者高效实现API全流程一站式体验。 伴随数字化浪潮的到来&#xff0c;应用编程接口(API)已经成为一个…

【MySQL】2.MySQL库操作

文章目录1.0 MySQL基本使用1.1 理解数据库操作2.0 MySQL数据库操作详解2.1创建数据库2.2 字符集和校验规则2.2修改数据库2.3删除数据库2.4查看数据库链接1.0 MySQL基本使用 1.1 理解数据库操作 查看数据库配置文件 指令: vim /etc/my.cnf 登录数据库 指令&#xff1a; mysql…

[第十三届蓝桥杯/java/算法]A——排列字母

&#x1f9d1;‍&#x1f393;个人介绍&#xff1a;大二软件生&#xff0c;现学JAVA、Linux、MySQL、算法 &#x1f4bb;博客主页&#xff1a;渡过晚枫渡过晚枫 &#x1f453;系列专栏&#xff1a;[编程神域 C语言]&#xff0c;[java/初学者]&#xff0c;[蓝桥杯] &#x1f4d6…

机器人开发--设计范式

机器人开发--设计范式1 概念范式特点2 三种范式2.1 机器人基元&#xff1a;感知&#xff08;sense&#xff09;、规划&#xff08;plan&#xff09;、执行&#xff08;act&#xff09;2.2 范式分类分级范式 hierarchical paradigm反应范式 reactive paradigm混合范式 hybrid pa…

程序的动态链接(5):使用动态库

前言 Linux下动态库文件的命名规范是以lib开头&#xff0c;紧接着是动态库名&#xff0c;以.so为后缀名&#xff0c;即lib 动态库名.so。 动态库查找过程 在Linux下&#xff0c;动态库的搜索的优先级顺序为&#xff1a; 编译目标代码时指定的动态库搜索路径&#xff0c;保…

达梦数据库(DM8)常用SQL学习

达梦产品手册 1.检查数据库版本及服务状态 1.1 查看达梦数据库运行状态 SELECT status$ as 状态 FROM v$instance;1.2 查看达梦数据库版本 SELECT banner as 版本信息 FROM v$version;2.创建用户并授权 2.1 创建用户 -- 使用 CREATE USER 语句创建 DM 用户&#xff0c;登…

Python爬虫详解

从今天开始&#xff0c;给大家介绍Python爬虫相关知识&#xff0c;今天主要内容是爬虫的基础理论知识。 一、爬虫简介 爬虫是指通过编写程序&#xff0c;来模拟浏览器访问Web网页&#xff0c;然后通过一定的策略&#xff0c;爬取指定内容。因此&#xff0c;爬虫的编写通常分为…

Nature Communications:人类丘脑的基因结构及其与十种常见大脑疾病的重叠

丘脑是位于大脑中心的重要交流中枢&#xff0c;由不同的核组成&#xff0c;对意识和高级皮层功能至关重要。丘脑结构和功能的改变涉及到常见的大脑疾病的发病机制&#xff0c;但丘脑的遗传结构仍然很大程度上未知。在这里&#xff0c;使用来自30114个个体的大脑扫描和基因型数据…

【Linux】进程创建、进程终止、进程等待

目录 一、进程创建 1.1 深入 fork 函数 1.2 写时拷贝 二、进程终止 2.1 进程退出码 2.2 exit 与 _exit 三、进程等待 3.1 进程等待必要性 3.2 进程等待 3.2 wait 与 waitpid 3.3 获取子进程 status 3.4 非阻塞等待 一、进程创建 1.1 深入 fork 函数 在 Linux 中…

如何对图片进行旋转?这些工具能将图片进行旋转

大家平时在日常生活中有没有遇到这种情况&#xff1a;从网上保存下来的图片发现角度方向是错误的&#xff0c;或者是从相机导入拍摄的图片&#xff0c;打开图片发现它们的方向不统一&#xff0c;不方便我们进行观看。这时需要我们对图片进行旋转操作&#xff0c;才能将图片摆正…

图表控件LightningChart.NET 系列教程(四):安装

LightningChart.NET SDK 是一款高性能数据可视化插件工具&#xff0c;由数据可视化软件组件和工具类组成&#xff0c;可支持基于 Windows 的用户界面框架&#xff08;Windows Presentation Foundation&#xff09;、Windows 通用应用平台&#xff08;Universal Windows Platfor…

Linux 内核网络栈分析: 接收数据

引言 对于内核网络栈的分析我在大二听了李勇大神来小组的讲座以后就想干了&#xff0c;但像很多主题的文章一样&#xff0c;始终没有勇气&#xff0c;也没有时间动手&#xff0c;我终究还是把这个话题从大二延到大三&#xff0c;从大三延到大四了。冥冥之中某种东西好像早已是…

Python 帮同事用pandas快速筛选Excel文件

同事正在为怎样处理一个18万行的全年财务Excel文件发愁&#xff0c;文件足足有30M&#xff0c;打开文件也要两三分钟&#xff0c;于是他就向我求助。大概意思就是要筛选出Data工作簿“源数据”Sheet中所有收款人对应的付款人及付款笔数、金额小计&#xff0c;于是我简化做了一个…

【RuoYi-Vue-Plus】学习笔记 45 - Spring 事件监听器 @EventListener 注解简单分析

文章目录前言参考目录测试方法配置说明测试方法功能调用流程分析事件监听器初始化事件发布流程前言 因为之前比较忙所以匿了一段时间&#xff0c;顺便当了神雕大侠&#xff08;“阳过”&#xff09;。前段时间框架已经发布了新版本 V4.4.0&#xff0c;而在最新的 dev 分支中使…

labelImg数据标注及yolov5的训练和测试

labelImg数据标注及yolov5的训练和测试 一、labelImg数据标注的使用 数据标注主要针对于哪个地方是什么&#xff0c;一般像隐私类的是不能标注的&#xff0c;如鲁迅的故居可以标&#xff0c;但是张三的住所就不能进行标注。 labelImg是数据标注主要使用的工具。 1、首先使用…

第十四章 概率图模型

14.1 隐马尔可夫模型 机器学习最重要的任务&#xff0c;是根据一些已观察到的证据&#xff08;例如训练样本&#xff09;来对感兴趣的未知变量&#xff08;例如类别标记&#xff09;进行估计和推测。概念模型提供了一种描述框架&#xff0c;将学习任务归结于计算变量的概率分布…

ffmpeg-AVPacket

目录 引子 翻译一下官方注释&#xff1a; 成员变量&#xff1a; AVBufferRef *buf pts dts data size stream_index flag side_data side_data_elems duration pos opaque opaque_ref time_base 引子 AVPacket是ffmpeg基础且非常重要的数据结构…

我国脐橙行业现状:种植面积、产量及市场规模不断增长 江西赣州是最大生产区

根据观研报告网发布的《2022年中国脐橙市场分析报告-市场全景评估与发展定位研究》显示&#xff0c;脐橙是芸香科&#xff0c;属柑橘亚科&#xff0c;是柑橘属植物甜橙的一类栽培品种&#xff0c;果皮难或稍易剥离&#xff0c;瓢囊9-12瓣&#xff0c;果心实或半充实&#xff0c…

ChatGPT

ChatGPT是由OpenAI开发的一个人工智能聊天机器人程序&#xff0c;于2022年11月推出。该程序使用基于GPT-3.5架构的大型语言模型并通过强化学习进行训练。目前&#xff0c;有部分地区&#xff08;例如中国大陆、香港&#xff09;无法使用此项服务&#xff0c;这里我就介绍一下中…