C++學習-入門到精通-【3】控制語句、賦值、自增和自減運算符

C++學習-入門到精通-【3】控制語句、賦值、自增和自減運算符


控制語句、賦值、自增和自減運算符

  • C++學習-入門到精通-【3】控制語句、賦值、自增和自減運算符
  • 一、什么是算法
  • 二、偽代碼
  • 三、控制結構
    • 順序結構
    • 選擇結構
      • if語句
      • if...else語句
      • switch語句
    • 循環結構
      • while語句
  • 四、算法詳述:計數器控制的循環
  • 五、算法詳述:標記控制的循環
  • 六、算法詳述:嵌套的控制語句
  • 七、關于變量的定義和聲明兩個概念
  • 八、for循環的應用
  • 九、使用switch語句繼續優化GradeBook類
  • 十、流操縱符boolalpha


一、什么是算法

對任何可求解的問題來說,都能夠以一種特定的順序執行一系列動作來完成。解決問題的步驟稱為算法,它包含兩方面的含義:

  1. 執行的動作
  2. 這些動作的執行順序

舉個例子來說明動作的執行順序是非常重要的。
一個人早上會按照下面的算法:①起床;②脫掉睡衣;③沐浴;④更衣;⑤吃早飯;
如果上面動作的執行順序發生改變:①起床;②脫掉睡衣;③更衣;④沐浴;⑤吃早飯;
這個從如果按照改變之后的順序執行,那么他將會濕瀌瀌的吃早飯。
所以在程序執行過程中,語句的執行順序也是非常重要的,所謂的程序控制,就是指定語句(動作)的執行順序。

下面我們會討論如何使用控制語句來進行程序控制。

二、偽代碼

偽代碼語句通常只描述可執行語句。所謂的可執行語句,是指轉換為C++程序的代碼之后會引起特定動作的語句。注意,沒有涉及初始化和構造函數的聲明并不是可執行語句。例如:int number;該語句僅是告訴編譯器有一個類型為int的變量,需要你為它預留空間,但并沒有導致任何動作的發生。

一個偽代碼例子:
在這里插入圖片描述

三、控制結構

C++程序中語句的執行順序一般都是按照書寫順序,這種執行方式也被稱為是順序執行。但是在實際問題中只有順序執行是不夠,比如當只有滿足條件A時,才執行語句A,否則跳過它,所以在最初的C++中使用goto語句來控制程序的語句執行順序,這種由程序員自己指定程序下一句要執行的語句的方式被稱為控制轉移。但是使用goto語句程序代碼,因為條理復雜,非常容易出錯,所以這種使用goto控制語句執行順序的方式被淘汰了,取而代之的是三種控制結構:順序結構選擇結構循環結構。只使用這三種結構,也可以實現所有的代碼需求,且使用這種方式的代碼條理清晰、易于調試,使得程序員的工作效率變高。

順序結構

正常書寫(非選擇、非循環語句)的程序代碼都是順序結構。

選擇結構

C++中提供3種選擇語句:if語句(單路選擇語句),if...else語句(雙路選擇語句),switch語句(多路選擇語句)。嚴格來說,還可以使用if...else if...else語句作為多路選擇語句。

if語句

判斷一個人是否成年,我們需要根據他的年齡來進行判斷,超過18歲就是成年
下面給出該選擇語句的偽代碼:

如果年齡大于等于18歲輸出已成年

下面給出該選擇語句的UML活動圖。
在這里插入圖片描述
其中實心圓點表示活動的起始位置,空心圓圈包圍的實心圓點表示結束位置。菱形(判斷符號)、圓角矩形(動作狀態符號)、和小圓圈表示活動。這些符號通過箭頭連接,箭頭方向表示活動的流向。

if…else語句

繼續上面的例子,超過18歲就是成年,不滿18歲為未成年;
偽代碼:

如果年齡大于等于18歲輸出已成年
否則輸出未成年

UML活動圖:
在這里插入圖片描述

else搖擺問題
如果沒有圓括號強制指定if和else的匹配關系,else會和上一個距離最近的if進行匹配。

語句塊
包含在花括號{}內部的一組語句稱為一個語句塊。

switch語句

UML活動圖:
在這里插入圖片描述

循環結構

C++中提供3種循環語句,while循環,for循環,do...while循環。在需要重復多次的執行某些語句時使用這種語句。

while語句

當變量i小于10時i增加1

UML活動圖
在這里插入圖片描述
上圖中有兩個菱形符號,第一個是合并符號,它的作用是將兩個工作流(活動)合并成一個工作流。有多個流入,單個流出。第二個是判斷符號,作用是判斷條件是否成立,單個流入,多個流出。

注意,在switch的case標簽中只能使用整型常量值(單個字符或整型數)

上面提到的if,else,switch,while,for,do都是C++中的關鍵字。在程序中不可以使用關鍵字作為標識符(例如:變量的名字)。所以大家需要了解到底有哪些關鍵字。
在這里插入圖片描述
在這里插入圖片描述

控制結構的小結
C++中只有三種控制結構,分別是順序語句、選擇語句、循環語句。每個C++程序都是由這些控制語句組建起來的。可以將每個控制語句用一張活動圖表示。這樣每張圖都包含一個初始狀態和結束狀態,分別代表控制語句的入口點和出口點。使用這些單入口/單出口的控制語句可以很方便的構建程序,將一個語句的出口點與下一個語句的入口點連接在一起即可,因此稱控制語句的這種連接方式為控制語句的堆疊。還會有另一種控制語句的連接方式——控制語句的嵌套,這種方式中,一個控制語句位于另一個控制語句的體內。

四、算法詳述:計數器控制的循環

現在為了解決一個實際問題:10個學生,,打印他們的總成績,計算并打印他們的平均成績。

偽代碼:

設置總數為0
設置成績計數器為1當成績計數器小于等于10時提示輸入下一個成績輸入下一個成績將該成績加到總數中成績計數器加1用總數除以10得到全班的平均成績
打印總數
打印平均成績

在之前的GradeBook類中增加上述功能:

// GradeBook.h
#include <iostream>
#include <string>class GradeBook
{
public:explicit GradeBook(std::string);void setCourseName(std::string);std::string getCourseName() const;void display() const;void determineClassAverage() const;
private:std::string courseName;
};
// GradeBook.cpp
#include "GradeBook.h"
using namespace std;GradeBook::GradeBook(string name)
{setCourseName(name);
}
void GradeBook::setCourseName(string name)
{// size()是string類的一個成員函數,返回調用它的對象的長度,// 還有一個相同作用的函數length(),這兩個函數在這里的作用完全相同,你喜歡哪個就用哪個// 字符串的長度不超過25,該字符串有效if (name.size() <= 25){courseName = name;}else // 長度不合法{courseName = name.substr(0, 25); // 將name的前25個字符截斷,賦值給數據成員cerr << "Name \"" << name << "\" exceeds maximum length(25).\n"<< "limiting courseName to firse 25 characters.\n" << endl;}
}
string GradeBook::getCourseName() const
{return courseName;
}
void GradeBook::display() const
{cout << "Welcome to the Grade Book for " << getCourseName() << " !" << endl;
}void GradeBook::determineClassAverage() const
{// 設置總數int sum = 0;// 設置計數器int count = 1;while (count <= 10){cout << "Enter Grade:>";int grade = 0;cin >> grade;sum += grade;count++;}// 輸出總成績cout << "Total of all grades is " << sum << endl;// 輸出平均成績cout << "Class Average is " << sum / 10 << endl;
}

五、算法詳述:標記控制的循環

上面的代碼是存在缺陷的,不可能所有的班級的人數都是10人。那么我們應該如何修改,使得該程序可以處理任何個數的學生數量呢?

解決該問題的一種方法是利用一種被稱為標記值(又稱啞值、信號值、或標志值)的特殊值,來指示循環結束。用戶在輸入完所有的合法成績之后,輸入標記值來表示數據輸入結束。標記控制的循環往往被稱為不定數循環,因為循環的執行次數在執行之前都是未知的。顯然這個標記值不可以與可接受的值相混淆,合法的成績都是非負數,所以可以使用一個負值來作為標記值,通常使用-1作為標記值。

采用自頂向下、逐步求精的方法開發偽代碼算法:頂層和第一層求精

為了開發出良好結構化的程序,自頂向下逐步求精的方法是一種非常有用的方法。我們最開始給出的是頂層的偽代碼表示,即一條概括了程序總體功能的單語句:
計算全班的平均成績
實際頂層偽代碼是一個程序的總體描述。但是僅有頂層的偽代碼的遠遠不夠的,它無法表達出可以作為程序編寫依據的細節。因為需要對其進行細化:將上層偽代碼分解成一系列小的任務,并將它們按照要執行的順序列出。這就是所謂的第一級求精。它的結果如下:

初始化變量
輸入、求和和計算成績的個數
計算并打印全班的總成績和平均成績

提示:許多程序在邏輯上可以分為三個階段:初始化程序變量的初始化階段,輸入數據的值和程序變量做相應調整的處理階段,計算和打印最終結果的收尾階段

繼續進行第二級求精

首先指定特定的變量。我們需要一個變量來保存輸入的成績的累加和,還需要一個變量來保存輸入的成績的數量。
所以偽代碼初始化變量可以細化為:

初始化total為0
初始化count為0

偽代碼輸入、求和和計算成績的個數需要一個循環語句來接收連續輸入的每個成績,由于此時不知道會輸入多少個成績,所以使用標記控制的循環。用戶在輸入完所有的成績之后輸入一個標記值來終止循環。
所以這句偽代碼細化為:

提示用戶輸入第一個成績
輸入第一個成績,可能為標記值 
當用戶輸入的值不是標記值時將該成績累加入total中count增1提示用戶輸入下一個成績輸入下一個成績,可能為標記值

對于偽代碼計算并打印全班的總成績和平均成績可以細化為

如果count不等于0用total除以count的值設置平均成績打印全班的總成績打印全班的平均成績
否則打印“未輸入任何成績”

當偽代碼算法足以轉換成C++代碼時,這種自頂向下逐步求精的過程便可以結束。

在GradeBook類中實現標記控制的循環

僅有下面的函數發生變化

#include <iomanip>void GradeBook::determineClassAverage() const
{// 設置總數int sum = 0;// 設置計數器int count = 0;int grade = 0; // 接收輸入的成績cout << "Enter Grade or -1 to quit:>";cin >> grade;// -1作為標記值while (grade != -1){sum += grade;count++;cout << "Enter Grade or -1 to quit:>";cin >> grade;}if (count != 0){double average = static_cast<double>(sum) / count;// 輸出總成績cout << "Total of all grades is " << sum << endl;// 設置浮點數格式cout << setprecision(2) << fixed;// 輸出平均成績cout << "Class Average is " << average << endl;}else{cout << "There are no valid grades" << endl;}
}

注意在最后的if…else語句中,使用了一個double類型的變量來接收平均值,這是因為整數除法結果出現小數會直接舍去。導致結果不準確。所以在這段代碼中使用double類型的的變量來接收計算得到的平均成績。并使用static_cast<>將int類型的sum強制轉換為double類型。這里如果不使用強制類型轉換將兩個操作數之一轉換為浮點數,那么變量average仍然會被一個int類型的值賦值(之后隱式轉換為double類型)。

使用static_cast操作符稱為顯式轉換。使用語法為static_cast<type>()

提示:浮點數是一個近似值,將一個浮點數當作精確值來使用可能會導致錯誤,比如:比較兩個浮點數的大小

在上面的函數輸出平均值之前,使用一個語句cout << setprecision(2) << fixed來設置浮點數的輸出格式。這里的setprecision是一個參數化的流操縱符,它的參數為2,所以這里輸出的浮點數保留小數點后兩位數字。要使用該流操縱符必須使用預處理指令包含一個頭文件#define <iomanip>。如果沒有使用這個語句手動設置浮點數的精度,那么輸出的浮點數一般保留小數點后面6位有效數字(默認精度為6)。

流操縱符fixed的作用是控制浮點數值以所謂的定點格式輸出。類似于科學計數法,定點格式強制浮點數顯示特定數量的位數,而且一旦采用了定點格式,那么就一定要顯示小數點及為補足小數點后的位數會補0,即使這個浮點數是一個整數量,例如,66.00。如果沒有設置定點格式,那么就會輸出66。當程序中同時設置了流操縱符fixed和setprecision時,顯示的值是一個四舍五入到指定小數位置的數,這個位置是由setprecision的參數決定的(僅輸出發生變化,內存中的值不變)。例如:87.638輸出為87.64,91.773輸出為91.77。

除了使用fixed之外,還可以使用showpoint這個流操縱符強制輸出小數點。如果只設置了showpoint沒有設置fixed,則小數點后面的不會補0。showpoint也是一個無參的流操縱符。這些無參的流操縱符是不需要頭文件iomanip的,在iostream中就有它們的定義。

六、算法詳述:嵌套的控制語句

問題:

在這里插入圖片描述

對上面的問題進行分析:

  1. 程序需要處理10個數據,所以可以使用計數器控制的循環;
  2. 每個考試結果都是一個數字,要么是1,要么是2;每次讀入一個考試結果,程序都需要判斷輸入的數據是1還是2;
  3. 使用兩個計數器來跟蹤考試結果,一個記錄輸入的考試結果數量,另一個記錄不合格的人數;
  4. 程序處理完所有的考試結果之后,需要判斷是否有8個以上的學生通過考試;

下面我們使用自頂向下逐步求精的方法來分析上面的問題。

頂層
分析考試結果,并決定是否給予獎金;

這是該程序總體功能的描述。需要對其進行多次細化才能得到可以順利轉換為C++代碼的偽代碼。

第一層求精
該層將頂層分成三個部分:初始化,數據處理,輸出結果;

所以該層的偽代碼為:

初始化變量
輸入10個考試結果,并對通過和未通過的人數進行計數
輸出考試結果,并決定是否給予獎金

第二層求精

初始化變量的細化:

初始化變量student count為0
初始化變量failures為0

輸入10個考試結果,并對通過和未通過的人數進行計數的細化:

(while)student count小于10時提示輸入一個考試結果輸入一個考試結果student count增加1如果(if)考試結果為2failures增加1

輸出考試結果,并決定是否給予獎金的細化:

顯示通過人數的值(student count - failures)
顯示failures的值
如果failures小于等于2輸出"Bonus to instructor"

上面的偽代碼的詳細程序已經達到轉換為C++代碼的程度了,細化結束。

C++代碼如下:

#include <iostream>
using namespace std;int main()
{int student_count = 0;int failures = 0;while (student_count < 10){cout << "Enter result:>";int result = 0;cin >> result;student_count++;if(result == 2)failures++;}cout << "Passes is " << (student_count - failures) << endl;cout << "failures is " << failures << endl;if (failures <= 2){cout << "Bonus to instructor" << endl;}
}

運行結果:
在這里插入圖片描述

C++11的列表初始化

C++11中引入了一種新的變量初始化語法。列表初始化又稱統一初始化,使得程序員可以使用同一種語法來初始化任何類型的變量。

例如:

int number = 1;
// 可以寫成
int number = { 1 };
// 或
int number{1};

{}表示列表初始化器。對于一個基本數據類型的變量,只放置一個值在列表初始化器中。對于一個對象,列表初始化器中可以是逗號分隔的值的列表,這些值傳遞給對象的構造函數。

比如一個雇員類,它有三個數據成員,雇員的名字,雇員的性別,雇員的薪水。

// 使用列表初始化器初始化一個雇員類的對象
Employee enployee = { "zhangsan", "male", 12345 };
// 或
Employee enployee{ "zhangsan", "male", 12345 };

使用列表初始化器來進行初始化還可以阻止“縮小轉換”的發生,這種轉換可能會導致數據的損失。例如,之前使用int i = 3.14試圖將一個浮點數賦值給int類型的變量i,這個浮點數的浮點部分(.14)會被截掉,保存在變量i中的值其實是3,這導致了數據的損失——這就是一次縮小轉換。這樣的語句,編譯器會發生警告,但是仍可以編譯通過。

如果是使用列表初始化器進行這樣的初始化,就無法編譯通過,可以幫助程序員避免這種可能發生的非常微妙的邏輯錯誤。

比如:int i = { 3.14 },error。
在這里插入圖片描述

七、關于變量的定義和聲明兩個概念

聲明是對一個變量命名,如上面35行聲明了i是一個int類型的變量,為其在內存中預留了空間,并設置它的值為1。
在C++中同時預留內存空間的變量聲明,應該換個更確切的說法,變量定義
由于定義也是聲明,所以除非這種聲明特別重要,否則一般情況下還是使用術語“聲明”

八、for循環的應用

問題:
在這里插入圖片描述

#include <iostream>
#include <iomanip>
#include <cmath>using namespace std;int main()
{// 年利率double rate = { 0.05 };// 年數double n = { 10 };// 本金double principal = { 1000.0 };// 總金額double amount{ 0 };// 打印表頭// setw操作符設置輸出域的寬度cout << "Year" << setw(22) << "Amount on deposit" << endl;// 初始化計數器為0int i{ 0 };for (i = 1; i <= n; i++){amount = principal * pow((1 + rate), i);cout << setw(4) << i << setw(22) << amount << endl;}
}

運行結果:
在這里插入圖片描述
可以看到這樣輸出的浮點數格式整齊,設置其格式cout << setprecision(2) << fixed;,再次輸出:
在這里插入圖片描述

代碼中使用到的兩個新函數/操作符:

計算冪:
在這里插入圖片描述
該函數要求兩個double類型的實參。返回一個double類型的值。需要包含cmath這個頭文件。

流操縱符格式化數值的輸出

在這里插入圖片描述

該流操縱符的作用是設置下一個輸出值應占用的域寬,代碼中的setw(4)表示下一個輸出值會占用4個字符的空間。

代碼中使用兩個有參數的流操縱符setprecisionsetw,所以必須包含頭文件<iomanip>。如果輸出的值小于規定字符位置的寬度,在默認情況下,輸出值在域寬范圍內右對齊;輸出的值大于規定字符位置的寬度,則擴展到整個輸出值的寬度。可以使用無參流操縱符left設置左對齊,這是一種黏性設置(沒有手動修改的情況下,之后的輸出都是左對齊)。可以使用無參流操縱符right恢復右對齊。

測試代碼:

#include <iostream>
#include <iomanip>using namespace std;int main()
{// 驗證setw流操縱符只影響下一個輸出值cout << setw(5) << "Year" << 'a' << endl;// 記憶性的左對齊cout << setw(5) << left << "Year" << setw(4) << 'a' << endl;// 使用right恢復右對齊cout << setw(5) << left << "Year" << setw(4) << right << 'a' << endl;
}

運行結果:
在這里插入圖片描述

性能提示
在循環中1+rate這個表達式是不會發生變化的,所以它應該放在循環外面以避免不必要的開銷。雖然計算一個表達式的開銷很小,但放在循環中時,當循環次數很多時會導致這種開銷被放大,使得性能下降。

九、使用switch語句繼續優化GradeBook類

現在需要在GradeBook類中增加一些功能,包括接收用戶輸入的用字母表示(A、B、C、D、E)的成績,輸出每級成績對應的學生人數的總結。

GradeBook.h

// GradeBook.h
#include <string>class GradeBook
{
public:explicit GradeBook(std::string); // 初始化課程名void setCourseName(std::string); // 設置課程名std::string getCourseName() const; // 獲取課程名void display() const; // 打印歡迎信息void inputGrades(); // 輸入任意個學生成績void displayGradeReport() const; // 打印輸入的成績報告
private:std::string courseName;unsigned int aCount; // 成績為A的學生人數unsigned int bCount; // 成績為B的學生人數unsigned int cCount; // 成績為C的學生人數unsigned int dCount; // 成績為D的學生人數unsigned int eCount; // 成績為E的學生人數
};

GradeBook.cpp

#include <iostream>
#include "GradeBook.h"using namespace std;GradeBook::GradeBook(string name):aCount(0),bCount(0), cCount(0), dCount(0), eCount(0)
{// 調用set成員函數初始化課程名// 需要進行有效性檢驗setCourseName(name);
}void GradeBook::setCourseName(string name)
{// 課程名長度小于等于25時,合法if (name.size() <= 25){courseName = name;}else{// 為了程序的健壯性,就算課程名長度不合法// 也會截取前25個字符存入數據成員courseName = name.substr(0, 25);// 進行異常處理cerr << "Name \"" << name << "\" is exceeds miximum length(25)\n" << "Limits courseName to first 25 Characters.\n" << endl;}
}string GradeBook::getCourseName() const
{// 返回數據成員courseName的值return courseName;
}void GradeBook::display() const
{// 打印歡迎信息cout << "Welcome to the GradeBook for " << getCourseName() << "!" << endl;
}void GradeBook::inputGrades()
{// 定義變量int grade{0}; // 暫存輸入的成績// 打印提示信息cout << "Enter the letter grades(A、B、C、D、E)." << endl<< "Enter the EOF character to end input." << endl;// 使用標記控制的循環來接收輸入的成績while ((grade = cin.get())/*讀取一個字符*/ != EOF){switch (grade){case 'A': case 'a':aCount++;break;case 'B':case 'b':bCount++;break;case 'C':case 'c':cCount++;break;case 'D':case 'd':dCount++;break;case 'E':case 'e':eCount++;break;case '\n': // 忽略換行符case '\t': // 忽略制表符case ' ': // 忽略空格break;default:cerr << "Incorrect letter grade entered." << "Enter a new grade." << endl;break;}} 
}void GradeBook::displayGradeReport() const
{// 輸入結果cout << "Number of students who received each letter grade:" << "\nA:" << aCount << "\nB:" << bCount<< "\nC:" << cCount<< "\nD:" << dCount<< "\nE:" << eCount<< endl;
}

test.cpp

#include <iostream>
#include "GradeBook.h"using namespace std;int main()
{GradeBook myGradeBook("CS1201 C++ programming");myGradeBook.display();myGradeBook.inputGrades();myGradeBook.displayGradeReport();
}

運行結果:

在這里插入圖片描述

讀入輸入的字符

上面代碼中使用cin.get從鍵盤讀入一個字符,并把他保存在變量grade中。可能有些剛接觸編程的同學有疑惑,字符不是應該由char類型的變量來保存嗎,為什么這里使用一個整型類型的變量來保存呢?這是因為在內存中字符是以二進制的形式儲存的,它們是通過ASCII編碼轉換成字符的。本質上整型類型和字符類型在內存中都是以二進制的形式保存,且整型類型的長度大于字符類型,所以可以使用整型類型的變量來保存字符。

一般情況下,賦值表達式的值就是賦值運算符左邊的值。因此,賦值表達式grade = cin.get()的值等于cin.get()賦給grade的值。

輸入EOF指示符

頭文件中定義了EOF,它的值是-1,在程序執行中我們怎么輸入一個EOF呢?直接輸入-1?還是輸入EOF

都不是,“文件結束”的輸入是通過在一行上輸入組合鍵來實現的,在Linux/UNIX/OS X這些系統中是使用<ctrl> d,同時按下ctrl鍵和d鍵;在Windows系統中是使用<ctrl> z來實現的。

忽略輸入的換行符、制表符和空格

往程序輸入字符時,為了讓程序讀入字符,必須通過按鍵盤的回車鍵的方式,將它們送入計算機。每次輸入一個字符,計算機其實讀入了兩個字符,一個有效成績字符,一個換行符。當使用cin.get()讀取一個字符時,會出現讀入換行符的情況,為了避免每次讀入這些符號都由default子句打印打印一條錯誤信息,所以在switch語句中包含了處理這些情況的子句。

C++11的類內初始化器

C++11允許程序員在類聲明中的聲明數據成員的同時,為它們提供默許值。

例如:

	// 使用類內初始化器,將下面的數據成員的值初始化為0unsigned int aCount = 0; // 成績為A的學生人數unsigned int bCount = 0; // 成績為B的學生人數unsigned int cCount = 0; // 成績為C的學生人數unsigned int dCount = 0; // 成績為D的學生人數unsigned int eCount = 0; // 成績為E的學生人數

這不同于上面例子中的在類的構造函數對數據成員進行初始化。在之后的章節中我們會對該初始化器進行更詳細的介紹。

十、流操縱符boolalpha

在C++程序中使用流插入運算符輸出布爾值truefalse時,程序輸出會是10。如果想要讓程序以單詞形式輸出,可以使用流操縱符boolalpha

示例代碼:

#include <iostream>using namespace std;int main()
{cout << boolalpha << "Logical AND (&&)"<< "\nfalse && false: " << (false && false) << "\nfalse && true: " << (false && true)<< "\ntrue && false: " << (true && false)<< "\ntrue && true: " << (true && true)<< endl;cout <<  "\nLogical OR (||)"<< "\nfalse || false: " << (false || false)<< "\nfalse || true: " << (false || true)<< "\ntrue || false: " << (true || false)<< "\ntrue || true: " << (true || true)<< endl;cout << "\nLogical NOT (!)"<< "\n!false: " << (!false)<< "\n!true: " << (!true)<< endl;
}

運行結果:
在這里插入圖片描述

從結果中可以看出流操縱符boolalpha也是黏性設置;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/79381.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/79381.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/79381.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

父子組件雙向綁定

v-model 語法糖實現 vue中我們在input中可以直接使用v-model來完成雙向綁定,這個時候 v-model 通常會幫我們完成兩件事: v-bind:value的數據綁定@input的事件監聽如果我們現在封裝了一個組件,其他地方在使用這個組件時,是否也可以使用v-model來同時完成這兩個功能呢? 當我…

用Selenium開啟自動化網頁交互與數據抓取之旅

用Selenium開啟自動化網頁交互與數據抓取之旅 在當今數字化時代&#xff0c;數據的價值不言而喻&#xff0c;而網頁作為海量數據的重要載體&#xff0c;如何高效獲取其中的關鍵信息成為眾多開發者和數據愛好者關注的焦點。Selenium這一強大工具&#xff0c;為我們打開了自動化…

VB.net序列化和反序列化的使用方法和實用場景

引言 相信很多初學編程的人都會提出過這個疑問&#xff1a;“既然我的變量可以存在內存之中&#xff0c;那么是否也可以存在硬盤之中呢” 其實我想回答的是&#xff0c;完全可以而且方法不止一種&#xff0c;而今天講的是序列化最經典的——二進制序列化 由于序列化的部分已…

Android OTA

一、OTA運行原理 Android 平臺提供 Google diff arithmetic 差分機制&#xff0c;升級包支持完整升級以及差分升級&#xff0c;OTA 運行原理圖如下所示。 1. OTA Server 負責對更新包進行上傳&#xff0c;下載以及版本的管理。 2. 開發者在修改 Android 系統后&#xff0c;通…

Untiy基礎學習(三)Untiy中編寫腳本的基本規則

一、怎么創建腳本 在Project窗口下&#xff0c;右鍵Create C#Script 即可創建腳本 創建腳本的注意事項 &#xff1a; 1&#xff09;類名和文件名必須一致,不然不能掛載&#xff08;因為反射機制創建對象&#xff0c;會通過文件名去找Type&#xff09; 2&#xff09;沒有特殊需…

VBA宏即根據第一列的內容和第二列的數字,按照數字數量生成對應內容并依次放在第三列、第四列等

打開你的 Excel 工作表。按下 Alt F11 組合鍵&#xff0c;打開 VBA 編輯器。在 VBA 編輯器中&#xff0c;點擊 插入 -> 模塊。在模塊窗口中&#xff0c;輸入以下 VBA 代碼&#xff1a; Sub GenerateItems()Dim lastRow As LongDim i As Long, j As LongDim item As String…

深度學習系統學習系列【1】之基本知識

文章目錄 說明基礎知識人工智能、機器學習、深度學習的關系機器學習傳統機器學習的缺陷選擇深度學習的原因深度學習的關鍵問題深度學習的應用深度學習的加速硬件GPU環境搭建主流深度學習框架對比 說明 文章屬于個人學習筆記內容&#xff0c;僅供學習和交流。內容參考深度學習原…

論文筆記-基于多層感知器(MLP)的多變量橋式起重機自適應安全制動與距離預測

《IET Cyber-Systems and Robotics》出版山東大學 Tenglong Zhang 和 Guoliang Liu 團隊的研究成果&#xff0c;文章題為“Adaptive Safe Braking and Distance Prediction for Overhead Cranes With Multivariation Using MLP”。 摘要 橋式起重機的緊急制動及其制動距離預測是…

DeepSeek實戰--各版本對比

1.對比 版本參數量優勢劣勢使用場景競品DeepSeek-V36710億&#xff08;MoE架構&#xff0c;激活370億&#xff09;開源、高效推理&#xff08;60 TPS&#xff09;、低成本&#xff08;API費用低&#xff09;、中文處理能力突出&#xff08;90%準確率多模態能力有限通用任務&am…

從0開始建立Github個人博客(hugoPaperMod)

從0開始建立Github個人博客(hugo&PaperMod) github提供給每個用戶一個網址&#xff0c;用戶可以建立自己的靜態網站。 一、Hugo hugo是一個快速搭建網站的工具&#xff0c;由go語言編寫。 1.安裝hugo 到hugo的github標簽頁Tags gohugoio/hugo選擇一個版本&#xff0c…

【AI論文】WebThinker:賦予大型推理模型深度研究能力

摘要&#xff1a;大型推理模型&#xff08;LRMs&#xff09;&#xff0c;如OpenAI-o1和DeepSeek-R1&#xff0c;展示了令人印象深刻的長期推理能力。 然而&#xff0c;他們對靜態內部知識的依賴限制了他們在復雜的知識密集型任務上的表現&#xff0c;并阻礙了他們生成需要綜合各…

Linux_sudo命令的使用與機制

1、sudo命令的作用 sudo&#xff08;全稱 superuser do&#xff09;是 Linux/Unix 系統中權限管理的核心工具。 允許普通用戶在授權下以其他用戶&#xff08;默認是 root&#xff09;的權限執行命令&#xff0c;而無需直接登錄賬戶。 2、sudo命令的典型使用場景 sudo 覆蓋了系…

Scrapy框架之 中間件的使用

爬蟲中間件 特點&#xff1a;主要處理蜘蛛&#xff08;Spider&#xff09;和下載器&#xff08;Downloader&#xff09;之間的請求和響應。可以對蜘蛛生成的請求進行攔截、修改或過濾&#xff0c;也可以對下載器返回給蜘蛛的響應進行處理。適用場景&#xff1a; 請求過濾與修改…

供應鏈算法整理(一)--- 銷量預估

在供應鏈管理領域有較多的預估場景&#xff0c;例如送達時長預估、銷量預估、用電量預估。特別的在智能供應鏈領域&#xff0c;銷量和庫存的管理的智能化也依賴銷量預估&#xff0c;因此在本文我們整理了 銷量預估的算法詳細的技術方案。 時間序列預測在最近兩年內發生了巨大的…

第4篇:服務層抽象與復用邏輯

在業務系統復雜度指數級增長的今天&#xff0c;服務層&#xff08;Service Layer&#xff09;的合理設計直接影響著系統的可維護性和擴展性。本文將深入剖析 Egg.js 框架中的服務層架構設計&#xff0c;從基礎實現到高級封裝&#xff0c;全方位講解企業級應用的開發實踐。 一、…

Java學習手冊:Spring 數據訪問

一、Spring JDBC JdbcTemplate &#xff1a;Spring JDBC 提供了 JdbcTemplate 類&#xff0c;它簡化了數據庫操作&#xff0c;提供了豐富的 API 來執行數據庫訪問任務。JdbcTemplate 可以自動處理數據庫連接的獲取、釋放&#xff0c;SQL 語句的執行&#xff0c;結果集的處理等…

遞歸、搜索和回溯算法《遞歸》

在之前的優選算法當中我們已經學習了一些基本的算法&#xff0c;那么接下來我們就要來學習算法當中的一大重要章節——遞歸、搜索和回溯算法&#xff0c;其實也就是大家常常聽到的dfs、bfs&#xff1b;其實本質就是遞歸&#xff0c;在學習搜索、回溯等算法的過程當中我們會先來…

Java進階--設計模式

設計模式是一套被反復使用的、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。設計模式使代碼編制真正工程化&#xff0c;設計模式是軟件工程的基石&#xff0c;如同大廈的一塊塊磚石一樣&#xff0…

如何禁止AutoCAD這類軟件聯網

推薦二、三方法&#xff0c;對其他軟件影響最小 一、修改Hosts文件 Hosts文件是一個存儲域名與IP地址映射關系的文本文件&#xff0c;通過修改Hosts文件可以將AutoCAD的域名指向本地回環地址&#xff08;127.0.0.1&#xff09;&#xff0c;從而實現禁止聯網的目的。具體步驟如…

深度學習框架搭建(Vscode/Anaconda/CUDA/Pytroch)

目錄 ??????一 Vscode安裝 二、Anaconda安裝 三、更新顯卡驅動 四、安裝CUDA 五、安裝Pytorch 六、Vscode配置 七、出現的問題匯總 ??????一 Vscode安裝 在 Windows 上安裝 訪問 VS Code 官網 https://code.visualstudio.com/&#xff0c;點擊 "Downl…