C++ Primer 学习笔记 第五章 语句

2023-11-01

C++中大多语句以分号;结束。一个表达式,如ival + 5,末尾加上分号就变成了表达式语句。表达式语句的作用是执行表达式并丢弃掉求值结果:

ival + 5;    // 一条没什么用的表达式语句
cout << ival;    // 一条有用的表达式语句

最简单的语句是空语句:

;    // 空语句中只含有一个分号

如果在程序中某个地方,语法上需要一条语句但逻辑上不需要,此时应该使用空语句。还有当循环的全部工作在条件部分就可以完成时,通常需要空语句:

// 重复读入数据直至到达文件末尾或某次输入的值等于sought
while (cin >> s && s != sought)
    ;    // 空语句

使用空语句时应该加上注释,表示有意忽略该语句。

多余的空语句并非总是无害的,如无意加到循环体或判断语句后会出现错误。

复合语句指用花括号括起来的(可能为空的)语句和声明的序列,复合语句也被称为块。一个块就是一个作用域,在块中引入的名字只能在块内部以及嵌套在块中的子块里访问。

在程序某个地方,语法上需要一条语句,但逻辑上需要多条语句,则应该使用复合语句,如while或for的循环体必须是一条语句,但我们通常要在循环内干很多事情,因此需要将多条语句用花括号括起来,从而把语句序列转变成块。

块不以分号作为结束。

空块指内部没有任何语句的一对花括号,作用等价于空语句。

可以在if、switch、while和for语句的控制结构内定义变量,定义在控制结构当中的变量只在相应语句的内部可见:

while (int i = get_num())    
    cout << i << endl;
i = 0;    // 错误,循环外不能访问i

以上代码中i只会定义一次,定义是在编译阶段完成,但每次循环是否会重复创建并销毁变量,取决于是内置类型还是类类型。对于循环来说,内置类型一般编译器都会优化避免每次重复分配空间;对于类类型,最好在循环体外定义,否则每次循环都会经历变量的销毁和创建。

if语句:

// 形式一:
if (condition)
    statement
// 形式二:
if (condition)
    statement
else
    statement2

也可以嵌套if语句:

if (condition)
    statement
else if (condition)
    statement2
else 
    statement3

为避免因丢失了在if语句后的花括号而引起的错误,有些编码风格要求在if和else(对while、for也有此要求)后必须写上花括号。

悬垂else:当程序中出现多个else和if时,else与最近的if相匹配。可以使用花括号改变此规则。

switch语句:

// 为每个元音字母计数
    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
	char c;
	while (cin >> c) {
		switch (c) {
		case 'a':
			++aCnt;
			break;
		case 'e':
			++eCnt;
			break;
		case 'i':
			++iCnt;
			break;
		case 'o':
			++oCnt;
			break;
		case 'u':
			++uCnt;
			break;
		}
	}
	cout << aCnt << " " << eCnt << " " << iCnt << " " << oCnt << " " << uCnt << endl;

switch语句首先对括号里的表达式求值,该表达式可以是一个初始化的变量声明。表达式的值转化成整数类型,然后与每个case标签的值比较。如果和某个case标签的值匹配成功,程序从该标签之后的第一条语句开始执行,直到到达了switch的结尾或者是遇到一条break语句为止。

break语句作用是中断当前的控制流,此例中break语句将控制权移到switch语句外面。

如果switch语句的表达式和所有case都没有匹配上,将直接跳到switch结构之后第一条语句。

case关键字和它的对应值一起被称为case标签,case标签必须是整型常量表达式:

char ch = getVal();
int ival = 42;
switch(ch) {
case 3.14:    // 错误,case标签不是一个整数
case ival:    // 错误:case标签不是一个常量
}

case标签的值不能相同,否则会引发错误。default也是一种特殊的case标签。

// 当我们想统计所有元音字母出现总次数
	unsigned cnt = 0;
	char c;
	while (cin >> c) {
		switch (c) {
		case 'a':
		case 'e':
		case 'i':
		case 'o':
		case 'u':
			++cnt;
			break;
		}
	}
// switch语句部分也可以写成:
    switch (c) {
    case 'a': case 'e': case 'i': case 'o': case 'u':
		++cnt;
		break;
	}

一般不要省略case分支最后的break语句。如果没写break语句,最好加一段注释。

如果没有任何一个case标签能匹配上switch表达式的值,程序将执行紧跟在default标签后边的语句:

// 统计输入的字母不是元音的个数和元音的个数
	unsigned cnt = 0, cnt2 = 0;
	char c;
	while (cin >> c) {
		switch (c) {
		case 'a':
		case 'e':
		case 'i':
		case 'o':
		case 'u':
			++cnt;
			break;
		default:
			++cnt2;
			break;
		}
	}
	cout << cnt << " " << cnt2 << endl;

defalut标签可以不在最后面:

	unsigned cnt = 0, cnt2 = 0;
	char c;
	while (cin >> c) {
		switch (c) {
		case 'a':
		case 'e':
		case 'i':
		default:
			++cnt2;
			break;
		case 'o':
		case 'u':
			++cnt;
			break;
		}
	}
	cout << cnt << " " << cnt2 << endl;    // 当输入aeiouv时,输出2 4

即使不准备在default标签下做任何操作,定义一个default标签也有用,目的在于告诉程序读者已经考虑到了默认情况,只是目前什么也没有做。

标签不应该孤零零地出现,它后面必须跟上一条语句或另外一个case标签,如果switch结构以一个空的default标签作为结束,则该default标签后面必须跟一条空语句或空块。(我自己测试时,当default语句不在最后一个case出现时,其后可以不加空语句或空块)。

switch内部如果有变量定义,由于程序可能会跳过某些分支,如果被跳过的分支中有变量定义时,C++不允许跨过变量的初始化语句直接跳转到该变量所在作用域的另一个位置:

case true:
    string file_name;    // 错误,控制流可能绕过该处一个隐式初始化的变量
    int ival = 0;    // 错误,控制流可能绕过该处一个显式初始化的变量
    int jval;    // 正确,jval未初始化
case false:
    jval = next_num();    // 正确,即使程序没有进入true标签,jval也被定义了,在使用jval前必须赋值,否则报错使用了未初始化的变量

如果需要为某个case分支定义并初始化一个变量,需要将变量定义在块内:

case true:
    {
        string file_name = get_file_name();
    }
    break;
case false:
    if (file_name.empty());    // 错误,file_name作用域不涉及到此处

使用一系列if语句统计从cin读入的文本中有多少元音字母:

	char c;
	int aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
	while (cin >> c) {
		if (c == 'a') {
			++aCnt;
		}
		if (c == 'e') {
			++eCnt;
		}
		if (c == 'i') {
			++iCnt;
		}
		if (c == 'o') {
			++oCnt;
		}
		if (c == 'u') {
			++uCnt;
		}
	}
	cout << "有" << aCnt << "个a." << endl;
	cout << "有" << eCnt << "个e." << endl;
	cout << "有" << iCnt << "个i." << endl;
	cout << "有" << oCnt << "个o." << endl;
	cout << "有" << uCnt << "个u." << endl;

统计各个元音字母数量,大小写都要统计:

	unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
	char c;
	while (cin >> c) {
		switch (c) {
		case 'a':
		case 'A':
			++aCnt;
			break;
		case 'e':
		case 'E':
			++eCnt;
			break;
		case 'i':
		case 'I':
			++iCnt;
			break;
		case 'o':
		case 'O':
			++oCnt;
			break;
		case 'u':
		case 'U':
			++uCnt;
			break;
		}
	}
	cout << aCnt << " " << eCnt << " " << iCnt << " " << oCnt << " " << uCnt << endl;

统计元音字母数量的同时,统计空格、制表符和回车的数量:

	unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0, spaceCnt = 0, tabCnt = 0, lineBreakCnt = 0;
	char c;
	while ((c = cin.get()) != '#') {    // 以#作为输入结束符
		switch (c) {
		case 'a':
		case 'A':
			++aCnt;
			break;
		case 'e':
		case 'E':
			++eCnt;
			break;
		case 'i':
		case 'I':
			++iCnt;
			break;
		case 'o':
		case 'O':
			++oCnt;
			break;
		case 'u':
		case 'U':
			++uCnt;
			break;
		case ' ':
			++spaceCnt;
			break;
		case '\t':
			++tabCnt;
			break;
		case '\n':
			++lineBreakCnt;
			break;
		}
	}
	cout << aCnt << " " << eCnt << " " << iCnt << " " << oCnt << " " << uCnt << " " << spaceCnt << " " << tabCnt << " " << lineBreakCnt << endl;

cin.get函数可以获取到空白字符,但这时不能再用Ctrl+Z(文件结束符)再按回车来终止输入了。

统计元音字母的同时,也统计含有以下两个字符的字符序列的数量:ff、fl和fi:

	unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0, flCnt = 0, fiCnt = 0, ffCnt = 0;
	char c = 0, prec = 0;    // prec为上个字符
	bool flag = false;    // 引入flag确保fff不会被算成两个ff
	while (cin >> noskipws >> c) {    // noskipws表示不会忽略空白字符,即被空白字符隔开的双字符匹配不会成功
		switch (c) {
		case 'a':
		case 'A':
			++aCnt;
			break;
		case 'e':
		case 'E':
			++eCnt;
			break;
		case 'i':
			if (prec == 'f') {
				++fiCnt;
				flag = true;    //记录两个字符的条件匹配成功
			}
		case 'I':
			++iCnt;
			break;
		case 'o':
		case 'O':
			++oCnt;
			break;
		case 'u':
		case 'U':
			++uCnt;
			break;
		case 'f':
			if (prec == 'f') {
				++ffCnt;
				flag = true;
			}
			break;
		case 'l':
			if (prec == 'f') {
				++flCnt;
				flag = true;
			}
			break;
		}
		
		if (flag) {    // 如果本次匹配成功
			prec = 0;    // 初始化prec
			flag = false;    // 初始化flag
		} else {    // 如果本次匹配失败
			prec = c;    // 继续正常匹配
		}
	}
	cout << aCnt << " " << eCnt << " " << iCnt << " " << oCnt << " " << uCnt << " " << ffCnt << " " << flCnt << " " <<  fiCnt << endl;

while语句:

while (condition)
    statement

只要condition求值结果为真就一直执行statement(常常是一个块)。条件部分可以是一个表达式或者是一个带初始化的变量声明。

定义在while条件部分或者while循环体内的变量每次迭代都经历从创建到销毁的过程。(一般编译器会优化内置类型,每次循环不会创建和销毁,但对于类类型,还是会每次循环创建和销毁)。

当不确定要迭代多少次时,使用while循环比较合适。

从标准输入读取若干string对象,并输出最大连续出现的string及其连续出现的次数,如不存在重复,输出一条消息说明没有单词重复过:

	string s, pres, res;    // 记录当前串、当前串之前的串、出现次数最多的串
	int count = 1, maxCount = 0; 
	bool flag = 0;    // flag记录是否出现过连续重复字符串
	while (cin >> s) {
		if (s == pres) {    // 如果与上个字符串相同
			++count;
			flag = true;
			if (count > maxCount) {    // 如果当前串连续重复出现的次数创纪录
				maxCount = count;    // 更新记录
				res = pres;    // 更新创纪录的串
			}
		} else {
			count = 1;    // 初始化count
		}
		pres = s;
	}

	if (flag == false) {
		cout << "没有连续重复的字符串。" << endl;
	} else {
		cout << res << "出现了" << maxCount << "次。" << endl;
	}

传统for语句:

for (init-statement; condition; expression)
    statement

关键字for及括号里的部分称作for语句头。init-statement必须是声明语句、表达式语句、空语句其中一个。

执行过程:
1.首先执行一次init-statement。
2.判断condition,为true时才进入循环。
3.执行statement。
4.最后执行expression。
第一步只有在循环开始时执行一次,二三四步会重复执行直到condition为假。

for语句头中定义的对象只在for循环体内可见。

init-statement可以定义多个对象,但init-statement只能有一条声明语句,因此,所有变量的基础类型必须相同。

for语句头能省略掉三项中的任何项,但分号必须保留。省略condition的效果等价于在condition处写了一个true。

检验短vector是否是长vector的前缀:

    vector<int> ivec1 = { 1,2,3,4,5,6,7,8,9 };
	vector<int> ivec2 = { 1,2,3,4,5 };
	int i = 0;
	for ( ; i < ivec2.size(); ++i) {
		if (ivec1[i] != ivec2[i]) {
			cout << "匹配失败。" << endl;
			break;
		}
	}
	if (i == ivec2.size()) {
		cout << "匹配成功。" << endl;
	}

C++11新标准引入了范围for语句,可以遍历容器或其他序列的所有元素:

for (declaration : expression) 
    statement

expression必须是一个序列,如花括号括起来的初始值列表、数组或者vector、string等类型的对象,这些类型的共同特点是拥有能返回迭代器的begin和end成员(数组有非成员的begin、end函数)。

declaration定义一个变量,序列中的每个元素都得能转换成该变量的类型。如需要对序列中的元素执行写操作,循环变量需声明成引用类型。

每次迭代都会重新定义循环控制变量,并将其初始化成序列中的下一个值,之后才会执行statement。

不能通过for语句增加vector对象(或其他容器中的对象)的元素,因为在范围for语句中,预存了end()函数的值。

do while语句先执行循环体后检查条件:

do
    statement
while (condition);

对于do while语句来说,先执行statement再判断condition,因此条件部分不允许定义变量。

在do while循环体中定义的变量的作用域不包括条件部分:

do {
    int i = 2;
} while (i);    // 错误,i未定义

就像for循环一样:

	for ( ; k < 5; ++k) {    // 错误,k未定义
		int k = 0;
	}

循环重复地输入两个string对象,然后挑出短的输出:

    do {
		string s1, s2;
		cin >> s1 >> s2;
		if (s1.size() < s2.size()) {
			cout << s1 << endl;
		} else {
			cout << s2 << endl;
		}
	} while (1);

break语句负责终止离它最近的while、do while、for、或switch语句。

从标准输入读取非空string直到连续出现两个相同串或所有单词都读完,输出连续出现的那个串或输出消息说明没有连续出现的串:

	string s, pres;
	bool flag = false;
	while (cin >> s) {
		if (s == pres) {
			flag = true;
			cout << s << endl;
			break;
		} else {
			pres = s;
		}
	}
	if (!flag) {
		cout << "没有连续重复的字符串。" << endl;
	}

continue终止最近的循环中的当前迭代并立即开始下一次迭代。

从标准输入读取非空string直到连续出现两个相同串并且该串以大写字母为开头或所有单词都读完,输出连续出现的那个以大写为开头的串或输出消息说明没有出现的这样的串:

	string s, pres;
	bool flag = false;
	while (cin >> s) {
		if (s == pres) {
			if (!isupper(s[0])) {
				continue;
			}
			flag = true;
			cout << s << endl;
			break;
		} else {
			pres = s;
		}
	}
	if (!flag) {
		cout << "没有连续重复的以大写为开头的字符串。" << endl;
	}

goto作用是从goto语句跳转到同一函数内的另一条语句。不要在程序中使用goto语句,它使得程序既难理解又难修改:

goto label;

label是用于标识一条语句的标识符。带标签语句是一种特殊的语句:

end: return;    // 带标签语句,可以作为goto的目标

标签标识符独立于其他标识符的名字。

和switch相似,它也不能跳过变量的声明初始化语句:

goto end;
int ix = 10;    // 错误,跳过了带初始化的变量定义
end: ix = 42;

向后跳过一个已经执行的定义是合法的,跳回到变量的定义之前会销毁该变量,然后重新定义它:

begin: int sz = get_size();
if (sz <= 0) {
    goto begin;    // 执行后会销毁sz,sz将重新定义并初始化
}

改写以上代码:

int sz = get_size();
while (sz <= 0) {
    sz = get_size();
}

异常处理机制为程序中异常检测和异常处理的协作提供支持。C++中,异常处理机制包括:
1.throw表达式,异常检测部分使用throw表达式来表示它遇到了无法处理的问题。我们说throw引发了异常。
2.try语句块,异常处理部分使用try语句块处理异常。try语句块以关键字try开始,并以一个或多个catch子句结束。try语句块中代码抛出的异常通常会被某个catch子句处理。因为catch子句处理异常,它们也被称为异常处理代码。
3.一套异常类,用于在throw表达式和相关catch子句间传递异常的具体信息。

throw表达式包含关键字throw和紧随其后的一个表达式,表达式的类型就是抛出异常的类型。throw表达式后面通常紧跟一个分号,构成一条表达式语句:

if (a != b) {
    throw runtime_error("Data must be same");
}

这段代码中,如果a与b不相等就抛出一个异常,该异常是类型runtime_error的对象。抛出异常将终止当前函数,并把控制权转移给能处理该异常的代码。

类型runtime_error是标准库异常类型的一种,定义在stdexcept头文件中。我们必须初始化runtime_error类型对象,方式是给它提供一个string对象或一个C风格的字符串。

try语句块语法形式:

try {
    program-statements
} catch (exception-declaration) {
    handler-statements
} catch (exception-declaration) {
    handler-statements
} //...

catch后的括号中是一个(可能未命名的)对象的声明(异常声明)。try块中声明的变量在块外无法访问,特别在catch子句中也无法访问。

编写异常处理代码:

    int a, b;
    cin >> a >> b;
    try {
        if (a != b) {
            throw runtime_error("a != b");
        }
    } catch (runtime_error err) {
        cout << "进入异常处理代码。" << endl;
        cout << err.what() << endl;
    }

程序执行try块内代码时,抛出了类型为runtime_error的异常,接下来程序控制权交给了catch子句中异常处理代码。异常处理代码中用到了what函数,在这里它是runtime_error类的一个成员函数。实际上每个标准库异常类都定义了名为what的成员函数,这些函数没有参数,返回值是抛出并初始化异常时所用的字符串副本。

复杂系统中,程序在遇到抛出异常的代码前,其执行路径可能已经经过了多个try语句块,如在一个try语句块中可能调用了包含另一个try语句块的函数,这个函数中的try块中可能又调用了另一个包含try语句块的函数。在寻找处理代码时的过程与函数调用链刚好相反,异常被抛出时,首先搜索抛出该异常的函数。如果没找到匹配的catch子句,终止该函数,并在调用该函数的函数中继续寻找。如果还是没有找到,重复以上步骤直到找到适当类型的catch子句,如还是没有找到匹配的catch子句,程序转到名为terminate的标准库函数,该函数行为与操作系统有关,一般情况下该函数会导致程序非正常退出。对于没有try块的异常来说,也按以上步骤处理,没有try块意味着当前函数没有匹配的catch子句。

异常会中断程序的正常流程,可能函数的一部分计算已经完成,会导致对象处于无效或未完成的状态,或者资源没有正常释放,在异常期间正确执行了清理工作的程序被称为异常安全的代码。编写这种代码非常困难。

C++标准库定义了一组类,用于报告标准库函数遇到的问题,这些异常类也可以在用户编写的程序中使用,它们定义在四个头文件中:
1.exception:定义了最通用的异常类exception。它只报告异常的发生,不提供额外信息。
2.stdexcept:定义了常用的异常类,内容在以下表格中。
3.new:定义了bad_alloc异常类型。
4.type_info:定义了bad_cast异常类型。

头文件stdexcept中定义的异常类:

类型 说明
exception 最常见的问题
runtime_error 只有在运行时才能检测的问题
range_error 运行时错误,生成的结果超出了有意义的值域范围
overflow_error 运行时错误:计算上溢
underflow_error 运行时错误:计算下溢
logic_error 程序逻辑错误
domain_error 逻辑错误:参数对应的结果值不存在
invalid_ argument 逻辑错误:无效参数
length_error 逻辑错误:试图创建一个超出该类型最大长度的对象
out_of_range 逻辑错误:使用一个超出有限范围的值

以上的异常类型与catch子句的匹配关系:throw出的类型是运行时(程序逻辑)错误的,要么进入与异常类型完全相同的catch子句,要么进入runtime_error(logic_error)的catch子句,要么进入exception的catch子句。进入顺序优先选最近的catch子句。

如以下代码会进入第二个catch子句:

    int a = 3, b = 5;
    try {
        if (a != b) {
            throw runtime_error("a != b");
        }
    } catch (range_error err) {
        cout << "进入range_error异常处理代码。" << endl;
        cout << err.what() << endl;
    } catch (exception err) {    // 会进入这个异常处理代码
        cout << "进入exception异常处理代码。" << endl;
        cout << err.what() << endl;
    } catch (runtime_error err) {
        cout << "进入runtime_error异常处理代码。" << endl;
        cout << err.what() << endl;
    }

标准库定义的异常类只定义了创建或拷贝异常类型的对象以及为异常类型的对象赋值的方法。

我们只能默认初始化exception(但我测试时可以用一个string或C风格字符串初始化)、bad_alloc和bad_cast对象,不允许为这些对象提供初始值。而头文件stdexcept中的异常恰好相反,应该使用string或C风格字符串初始化这类对象,不能默认初始化,创建时必须提供初始值,初始值中包含与错误相关的信息。

异常类型只定义了一个名为what的成员函数,该函数没有任何参数,返回值是一个指向C风格字符串的const char *,用以提供关于异常的一些文本信息。如果该异常类型有一个字符串类型的初始值,则what返回该字符串,对于无初始值的异常类型,what返回内容由编译器决定。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ Primer 学习笔记 第五章 语句 的相关文章

  • 微信小程序+uni-app知识点总结

    微信小程序知识点合集 1 小程序的优势和劣势有哪些 优势 1 容易推广 在微信中 小程序拥有众多入口 例如附近的小程序 小程序码 分享 发现 小程序等五十多个的入口 这些都有助于推广小程序 2 使用便捷 用户在使用小程序时 只需要轻轻点一下
  • Varnish的简单配置及使用

    一 Varnish的简单介绍 1 varnish是什么 Varnish是一个web加速器 被安装在web应用程序前面 缓存web应用程序 并响应用户请求 是一款具有高性能的开源HTTP加速器 具有方向代理及缓存的功能 功能与squid服务器
  • 基于STM32emWin5.32的移植

    基于STM32emWin532版本的移植 移植前提 1 下载所需源码 2 直接拷贝Cubemx的STemwin 文件说明 2 需已完成底层绘制LCD的驱动调试 移植 在项目工程目录增加以下文件夹及文件 配置单次图像刷写最大允许字节 配置驱动
  • 【ARIMA-WOA-LSTM】差分自回归移动平均方法-鲸鱼优化算法-LSTM预测研究(python代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Python代码实现 1 概述 差分自回归移动平均模型 ARIMA 是一种
  • 加速读取——三式(getchar,std::ios::sync_with_stdio(false)、cin.tie(0))

    在一些题目中会出现数据输入很大的情况 如果我们运用不好读取数据工具的话 那么很可能会在读取数据上花费较多的时间 甚至还没读完就超时了 读取速度 cin lt cin 关闭流同步 lt scanf lt getchar cin 关闭流同步 为
  • mysql让自增的id重新从0开始的命令

    1 清空表 2 TRUNCATE TABLE 表名
  • Linux下的压缩zip,解压缩unzip命令详解及实例

    http www cnblogs com zdz8207 p 3765604 html
  • Python爬虫分布式架构 - Redis/RabbitMQ工作流程介绍

    在大规模数据采集和处理任务中 使用分布式架构可以提高效率和可扩展性 本文将介绍Python爬虫分布式架构中常用的消息队列工具Redis和RabbitMQ的工作流程 帮助你理解分布式爬虫的原理和应用 为什么需要分布式架构 在数据采集任务中 单
  • 列举工作中常用的几个git命令?

    列举工作中常用的几个git命令 新增文件的命令 git add file或者git add 提交文件的命令 git commit m或者git commit a 查看工作区状况 git status s 拉取合并远程分支的操作 git fe
  • React16入门

    环境搭建 安装node 安装官方脚手架create react app npm install g create react app 创建项目 进入文件夹 进入cmd运行命令 mkdir ReactDemo 创建ReactDemo文件夹 c
  • 固态硬盘和机械硬盘的区别

    固态硬盘的应用范围要比机械硬盘的使用范围更广泛 固态硬盘在电子世界中起着非常重要的部件 而机械硬盘使用范围就不像固态硬盘那样灵活了 目前固态硬盘中最大的容量体积为1 6TB 传言IBM公司开始测试4TB的高速固态硬盘组了 和机械硬盘相比按T
  • jmeter配置java版本,Jmeter 在windows下的安装配置方法

    Jmeter通常用于并发测试 本文介绍Jmeter工具的安装步骤 2 安装jdk 下载完成后 双击安装 2 步骤二 配置jdk环境变量 右键计算机属性 gt 高级系统设置 gt 系统属性 gt 高级 gt 环境变量 gt 添加如下的系统变量

随机推荐

  • 2021-12-5 《聪明的投资者》学习笔记

    摘自 聪明的投资者 The Intelligent Investor 第4版 本杰明 格雷厄姆 第一章 投资与投机 聪明投资者的预期收益 第二章 投资者与通货膨胀 第三章 一个世纪的股市历史 1972年年初的股价水平 股市周期性 股价 利润
  • 【千律】C++基础:获取数组中的最大值和最小值

    include
  • springboot中的json、gson、fastjson如何使用与日期格式转换

    关于如何引用json gson fastjson srpngboot中默认用的是json格式 如果需要使用gson和fastjson其中一种格式的话 首先需要在pom文件中排除对json格式的依赖 再去引入你想要gson或者fastjson
  • CSS样式——div居中方法

    1 绝对居中 给div设置样式 div默认显示位置为body的左上方 width 400px height 300px background color orange 如下图所示 首先给div添加绝对定位 并设置上下左右边距为0 然后使用m
  • 【git国内镜像地址】【速度快】

    重申一下 此处说的是git客户端下载 而不是github网站 github网站请绕路 git官网地址 官网地址 大家可以打开试试 每秒几十或者只有几kb 下完要一个月 大家可以试试国内地址 5秒之内下载完成 git国内镜像地址 git国内镜
  • C++泛型基础

    1 泛型的基本思想 泛型编程 Generic Programming 是一种语言机制 通过它可以实现一个标准的容器库 像类一样 泛型也是一种抽象数据类型 但是泛型不属于面向对象 它是面向对象的补充和发展 在面向对象编程中 当算法与数据类型有
  • c语言fwrite函数的总结

    头文件 include
  • 华东地区响应最快的DNS服务排名

    223 5 5 5 阿里DNS 约 29 ms 114 114 115 115 114DNS 约 30 ms 114 114 115 119 114DNS 约 30 ms 114 114 114 114 114DNS 约 31 ms 114
  • OpenGL学习脚印: 环境搭建

    写在前面 如果你正在阅读本文 那么你和我一样可能喜欢图形学或者游戏编程 想尝试编写自己的图形App 图形学的初学者往往非常着急 希望能立即编写出丰富生动 逼真又富有交互性的3D应用 至少我是这样 笔者翻看了图形学教材 红宝书 3D数学基础等
  • 【Shiro】SpringBoot继承Shiro

    项目版本 springboot2 x shiro 1 3 2 Maven配置
  • 【OLAP(联机分析处理)】简单理解

    OnLine Analysis Processing 联机分析处理 功能 支持复杂的分析操作 侧重决策支持 并且提供直观易懂的查询结果 原理 OLAP联机分析首先是把数据预处理成数据立方 Cube 并把有可能的汇总都预先算出来 即预聚合处理
  • android卸载应用程序代码,android-关闭应用程序并从最近的应用程序中删除/

    我的解决方案基于上述的guest 以及下面的gilsaints88的评论 用于Android L兼容性 将此活动添加到您的AndroidManifest xml文件中 android name com example ExitActivit
  • Linux下安装mysql5.7.25,rpm安装方式保姆级教程!

    目录 前言 一 下载mysql5 7 25rpm安装压缩包 1 进入mysql官网的下载主页MySQL 2 进入社区下载 3 找到社区版服务器 4 进入历史版本库找到目标版本 二 检查并卸载已有的MySQL数据库 三 解压安装MySQL5
  • K8s(kubernetes)集群搭建及dashboard安装、基础应用部署

    基础介绍 概念 本质是一组服务器集群 在集群每个节点上运行特定的程序 来对节点中的容器进行管理 实现资源管理的自动化 功能 自我修复 弹性伸缩 服务发现 负载均衡 版本回退 存储编排 组件 控制节点 master 控制平面 APIserve
  • 解决VScode中无法激活conda虚拟环境的问题

    1 点击 终端 gt 新建终端 2 默认新建的终端是PowerShell 我们可以对其进行修改 3 此时进入cmd模式 就可以正常激活虚拟环境啦
  • 活动代码页简介

    代码页是字符集编码的别名 也有人称 内码表 早期 代码页是IBM称呼电脑BIOS本身支持的字符集编码的名称 当时通用的操作系统都是命令行界面系统 这些操作系统直接使用BIOS供应的VGA功能来显示字符 操作系统的编码支持也就依靠BIOS的编
  • 考虑设备动作损耗的配电网分布式电压无功优化(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 文献来源 摘要 电压无功控制是保证配电网经
  • Acwing 282. 石子合并

    区间DP循环一般是 区间长度从小到大来循环 然后再循环区间的左端点 然后再枚举我们的决策 f i j 表示将所有第i堆石子到第j堆石子合并成一堆石子的合并方式 这些方式中代价的最小值 我们可以以最后一次合并的分界线来划分集合 k i j 1
  • el-table使用时,获取index索引

    因为本人对vue不熟悉 特此记录开发时遇到的这个问题 1 获取表格列的索引 2 table选项卡点击事件
  • C++ Primer 学习笔记 第五章 语句

    C 中大多语句以分号 结束 一个表达式 如ival 5 末尾加上分号就变成了表达式语句 表达式语句的作用是执行表达式并丢弃掉求值结果 ival 5 一条没什么用的表达式语句 cout lt lt ival 一条有用的表达式语句 最简单的语句