循环和数组确实是联系比较紧密的两个基础语法,数组让我们管理大量同类对象,循环可以简单地遍历一个范围内的元素
本章我们可以学到:
Arrays
数组开辟一段连续空间存储同类元素,我们通过【】下标来访问某个元素
如果无符号整型占4个字节,那么数组大小就是4*6=24个字节
The for Loop
for循环的语法也不多说,注意分号;初始化部分不是必须的
首先说明一下size_t,这是个标准库定义的别名,不是int类的基础类型,它一般用来表示类型的大小,而且这是个很大的类型,表示范围足够大
我这里的环境是mingw-w64,可以看到头文件里定义的是unsigned long long的别名为size_t
下面是一段简单地计算平均值的程序
Determining the Size of an Array
获取数组大小有很多种方法,在size()引入之前,通常使用遍历维护count或者sizeof数组除以sizeof元素的方法:
虽然数组名会退化成指针,但是sizeof数组名返回的还是数组元素个数,这一点是符合直觉的
std::size, std::ssize - cppreference.com
size的实现也很有意思
这里就体现模板的强大了,我们不需要输入数组的元素类型和长度,T和N自动可以获取到
The Range-Based for Loop
这一小节之前有许多for-loop细节,都是大家讲烂了的语法细节,这里不多说
一般叫做range-for,用来遍历一整个range
这种for里也可以进行初始化
这是最通用的写法,当然如果有临时range,比如{},或者元素类型比较复杂,x类型写成auto也是可以的
Arrays of Characters 字符数组
当我们用单个字符初始化时,就是简单的char[];但是当我们用string liretal初始化时,char数组末尾会多一个\0,表示字符串的结尾
此时name数组内部存储的字符是这样的
# include <iostream>
# include <format>
# include <cmath>
using namespace std;int main() {const int max_length{100}; // Array sizechar text[max_length]{}; // Array to hold input stringstd::cout << "Enter a line of text:" << std::endl;// Read a line of characters including spacesstd::cin.getline(text, max_length);std::cout << "You entered:\n" << text << std::endl;size_t vowels{}; // Count of vowelssize_t consonants{}; // Count of consonantsfor (int i{}; text[i] != '\0'; i++) {if (std::isalpha(text[i])) // If it is a letter...{switch (std::tolower(text[i])) {// ...check lowercase...case 'a':case 'e':case 'i':case 'o':case 'u': ++vowels; // ...it is a vowelbreak;default: ++consonants; // ...it is a consonant}}}std::cout << "Your input contained " << vowels << " vowels and "<< consonants << " consonants." << std::endl;
}
这段代码就是简单地处理字符数组的例子,统计了一下字符串中元音辅音字母的数量
cin.getline可以用来向字符数组中写入数据
Allocating an Array at Runtime 动态创建数组
the array dimension must be a constant expression that can be evaluated by the compiler
数组长度必须是编译期可知的,constexpr
不过一些编译器兼容C标准,使得这个大小运行时获取也可以,比如gcc中:
这段代码是可以通过编译的
Alternatives to Using an Array
Using array<T,N> Containers
<array>中定义了改进版本的数组,和STL其他设施兼容,这个版本的类模板比原生数组要好用且直观
而且作为容器,array有这样的优势,支持了很多成员函数以及操作,比原生数组使用方便
std::array - cppreference.com
下面是一个综合例子,输出了一段范围内的身高和体重,以表格形式输出了BMI,并给出了建议范围
# include <iostream>
# include <format>using namespace std;int main() {const unsigned min_wt{100}; // Minimum weight in table (in pounds)const unsigned max_wt{250}; // Maximum weight in tableconst unsigned wt_step{10};const size_t wt_count{1 + (max_wt - min_wt) / wt_step};const unsigned min_ht{48}; // Minimum height in table (inches)const unsigned max_ht{84}; // Maximum height in tableconst unsigned ht_step{2};const size_t ht_count{1 + (max_ht - min_ht) / ht_step};const double lbs_per_kg{2.2}; // Pounds per kilogramconst double ins_per_m{39.37}; // Inches per meterstd::array<unsigned, wt_count> weight_lbs{};std::array<unsigned, ht_count> height_ins{};// Create weights from 100lbs in steps of 10lbsfor (unsigned i{}, w{min_wt}; i < wt_count; w += wt_step, ++i) { weight_lbs[i] = w; }// Create heights from 48 inches in steps of 2 inchesfor (unsigned i{}, h{min_ht}; h <= max_ht; h += ht_step) { height_ins.at(i++) = h; }// Output table headingsstd::cout << std::format("{:>8}", '|');for (auto w: weight_lbs) std::cout << std::format("{:^6}|", w);std::cout << std::endl;// Output line below headingsfor (unsigned i{1}; i < wt_count; ++i) std::cout << "--------";std::cout << std::endl;const unsigned int inches_per_foot{12U};for (auto h: height_ins) {const unsigned feet = h / inches_per_foot;const unsigned inches = h % inches_per_foot;std::cout << std::format("{:2}'{:2}\" |", feet, inches);const double h_m = h / ins_per_m; // Height in meterfor (auto w: weight_lbs) {const double w_kg = w / lbs_per_kg; // Weight in kilogramconst double bmi = w_kg / (h_m * h_m);std::cout << std::format(" {:2.1f} |", bmi);}std::cout << std::endl;}// Output line below tablefor (size_t i{1}; i < wt_count; ++i) std::cout << "--------";std::cout << "\nBMI from 18.5 to 24.9 is normal" << std::endl;
}
D:\clion_projects\cmake-build-default\clion_projects.exe| 100 | 110 | 120 | 130 | 140 | 150 | 160 | 170 | 180 | 190 | 200 | 210 | 220 | 230 | 240 | 250 |------------------------------------------------------------------------------------------------------------------------4' 0" | 30.6 | 33.6 | 36.7 | 39.8 | 42.8 | 45.9 | 48.9 | 52.0 | 55.0 | 58.1 | 61.2 | 64.2 | 67.3 | 70.3 | 73.4 | 76.4 |4' 2" | 28.2 | 31.0 | 33.8 | 36.6 | 39.5 | 42.3 | 45.1 | 47.9 | 50.7 | 53.5 | 56.4 | 59.2 | 62.0 | 64.8 | 67.6 | 70.5 |4' 4" | 26.1 | 28.7 | 31.3 | 33.9 | 36.5 | 39.1 | 41.7 | 44.3 | 46.9 | 49.5 | 52.1 | 54.7 | 57.3 | 59.9 | 62.5 | 65.1 |4' 6" | 24.2 | 26.6 | 29.0 | 31.4 | 33.8 | 36.2 | 38.7 | 41.1 | 43.5 | 45.9 | 48.3 | 50.7 | 53.2 | 55.6 | 58.0 | 60.4 |4' 8" | 22.5 | 24.7 | 27.0 | 29.2 | 31.5 | 33.7 | 35.9 | 38.2 | 40.4 | 42.7 | 44.9 | 47.2 | 49.4 | 51.7 | 53.9 | 56.2 |4'10" | 20.9 | 23.0 | 25.1 | 27.2 | 29.3 | 31.4 | 33.5 | 35.6 | 37.7 | 39.8 | 41.9 | 44.0 | 46.1 | 48.2 | 50.3 | 52.4 |5' 0" | 19.6 | 21.5 | 23.5 | 25.4 | 27.4 | 29.4 | 31.3 | 33.3 | 35.2 | 37.2 | 39.1 | 41.1 | 43.1 | 45.0 | 47.0 | 48.9 |5' 2" | 18.3 | 20.2 | 22.0 | 23.8 | 25.7 | 27.5 | 29.3 | 31.2 | 33.0 | 34.8 | 36.7 | 38.5 | 40.3 | 42.2 | 44.0 | 45.8 |5' 4" | 17.2 | 18.9 | 20.6 | 22.4 | 24.1 | 25.8 | 27.5 | 29.2 | 31.0 | 32.7 | 34.4 | 36.1 | 37.8 | 39.6 | 41.3 | 43.0 |5' 6" | 16.2 | 17.8 | 19.4 | 21.0 | 22.6 | 24.3 | 25.9 | 27.5 | 29.1 | 30.7 | 32.3 | 34.0 | 35.6 | 37.2 | 38.8 | 40.4 |5' 8" | 15.2 | 16.8 | 18.3 | 19.8 | 21.3 | 22.9 | 24.4 | 25.9 | 27.4 | 28.9 | 30.5 | 32.0 | 33.5 | 35.0 | 36.6 | 38.1 |5'10" | 14.4 | 15.8 | 17.3 | 18.7 | 20.1 | 21.6 | 23.0 | 24.4 | 25.9 | 27.3 | 28.8 | 30.2 | 31.6 | 33.1 | 34.5 | 35.9 |6' 0" | 13.6 | 14.9 | 16.3 | 17.7 | 19.0 | 20.4 | 21.7 | 23.1 | 24.5 | 25.8 | 27.2 | 28.5 | 29.9 | 31.3 | 32.6 | 34.0 |6' 2" | 12.9 | 14.2 | 15.4 | 16.7 | 18.0 | 19.3 | 20.6 | 21.9 | 23.2 | 24.4 | 25.7 | 27.0 | 28.3 | 29.6 | 30.9 | 32.2 |6' 4" | 12.2 | 13.4 | 14.6 | 15.9 | 17.1 | 18.3 | 19.5 | 20.7 | 22.0 | 23.2 | 24.4 | 25.6 | 26.8 | 28.1 | 29.3 | 30.5 |6' 6" | 11.6 | 12.7 | 13.9 | 15.1 | 16.2 | 17.4 | 18.5 | 19.7 | 20.8 | 22.0 | 23.2 | 24.3 | 25.5 | 26.6 | 27.8 | 29.0 |6' 8" | 11.0 | 12.1 | 13.2 | 14.3 | 15.4 | 16.5 | 17.6 | 18.7 | 19.8 | 20.9 | 22.0 | 23.1 | 24.2 | 25.3 | 26.4 | 27.5 |6'10" | 10.5 | 11.5 | 12.6 | 13.6 | 14.7 | 15.7 | 16.8 | 17.8 | 18.9 | 19.9 | 21.0 | 22.0 | 23.1 | 24.1 | 25.1 | 26.2 |7' 0" | 10.0 | 11.0 | 12.0 | 13.0 | 14.0 | 15.0 | 16.0 | 17.0 | 18.0 | 19.0 | 20.0 | 21.0 | 22.0 | 23.0 | 24.0 | 25.0 |------------------------------------------------------------------------------------------------------------------------BMI from 18.5 to 24.9 is normal
Using std::vector<T> Containers
除非知道大小,否则一律用vector代替数组,就这么简单
# include <iostream>
# include <format>
# include <vector>using namespace std;int main() {vector<double> x; // Stores data to be sortedwhile (true) {double input{}; // Temporary store for a valuestd::cout << "Enter a non-zero value, or 0 to end: ";std::cin >> input;if (input == 0) break;x.push_back(input);}if (x.empty()) {std::cout << "Nothing to sort..." << std::endl;return 0;}std::cout << "Starting sort." << std::endl;while (true) {bool swapped{false}; // Becomes true when not all values are in orderfor (size_t i{}; i < x.size() - 1; ++i) {if (x[i] > x[i + 1]) // Out of order so swap them{const auto temp = x[i];x[i] = x[i + 1];x[i + 1] = temp;swapped = true;}}if (!swapped) // If there were no swapsbreak; // ...all values are in order...} // ...otherwise, go round again.std::cout << "Your data in ascending sequence:\n";const size_t perline{10}; // Number output per linesize_t n{}; // Number on current linefor (size_t i{}; i < x.size(); ++i) {std::cout << std::format("{:8.1f}", x[i]);if (++n == perline) // When perline have been written...{std::cout << std::endl; // Start a new line and...n = 0; // ...reset count on this line}}std::cout << std::endl;
}
关于容器的部分后面我会专门介绍STL中的部分,这些不是语言核心但非常非常好用,某种程度上已经成为了C++的标志
如果书里没说我也会专门做专栏写的