《Beginning C++20 From Novice to Professional》第五章 Arrays and Loops

循环和数组确实是联系比较紧密的两个基础语法,数组让我们管理大量同类对象,循环可以简单地遍历一个范围内的元素

本章我们可以学到:

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数组内部存储的字符是这样的

cpp 复制代码
# include <iostream>
# include <format>
# include <cmath>
using namespace std;

int main() {
    const int max_length{100}; // Array size
    char text[max_length]{};   // Array to hold input string
    std::cout << "Enter a line of text:" << std::endl;
    // Read a line of characters including spaces
    std::cin.getline(text, max_length);
    std::cout << "You entered:\n" << text << std::endl;
    size_t vowels{};     // Count of vowels
    size_t consonants{}; // Count of consonants
    for (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 vowel
                    break;
                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,并给出了建议范围

cpp 复制代码
# 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 table
    const 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 table
    const 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 kilogram
    const double ins_per_m{39.37}; // Inches per meter
    std::array<unsigned, wt_count> weight_lbs{};
    std::array<unsigned, ht_count> height_ins{};
    // Create weights from 100lbs in steps of 10lbs
    for (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 inches
    for (unsigned i{}, h{min_ht}; h <= max_ht; h += ht_step) { height_ins.at(i++) = h; }
    // Output table headings
    std::cout << std::format("{:>8}", '|');
    for (auto w: weight_lbs) std::cout << std::format("{:^6}|", w);
    std::cout << std::endl;
    // Output line below headings
    for (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 meter
        for (auto w: weight_lbs) {
            const double w_kg = w / lbs_per_kg; // Weight in kilogram
            const double bmi  = w_kg / (h_m * h_m);
            std::cout << std::format(" {:2.1f} |", bmi);
        }
        std::cout << std::endl;
    }
    // Output line below table
    for (size_t i{1}; i < wt_count; ++i) std::cout << "--------";
    std::cout << "\nBMI from 18.5 to 24.9 is normal" << std::endl;
}
bash 复制代码
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代替数组,就这么简单

cpp 复制代码
# include <iostream>
# include <format>
# include <vector>

using namespace std;

int main() {
    vector<double> x; // Stores data to be sorted
    while (true) {
        double input{}; // Temporary store for a value
        std::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 order
        for (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 swaps
            break;    // ...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 line
    size_t n{};               // Number on current line
    for (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++的标志

如果书里没说我也会专门做专栏写的

相关推荐
Neituijunsir4 分钟前
2024.06.28 校招 实习 内推 面经
c++·python·算法·面试·自动驾驶·汽车·求职招聘
JY9406 分钟前
使用Qt制作一个简单的界面
开发语言·qt
萝卜地里的兔子13 分钟前
面向对象编程思想新解 第二章 编程的本质
java·开发语言
xw-pp14 分钟前
回溯法的小结与概述
java·数据结构·c++·python·算法·递归
weixin_3077791317 分钟前
C#实现求解函数在某一点的切线与法线函数
开发语言·c#
“抚琴”的人19 分钟前
C#——Path类详情
开发语言·数据库·microsoft·c#
回家吃月饼24 分钟前
python中unittest框架和pytest框架区别
开发语言·python·pytest
虫小宝25 分钟前
Java中的服务化架构设计与实现
java·开发语言
请叫我青哥25 分钟前
第二十条:与抽象类相比,优先选择接口
java·开发语言
Hellc00727 分钟前
OCR 技术来实现图片文字识别 [C#]
开发语言·c#·ocr