【C++】基础2——数组、字符串、文件操作

1. 数组

1.1 一维数组

1.1.1 固定长度数组

指定数组长度的表达式应该为字面量,而非变量(C++98/03标准)。C++11及以后的标准,引入可变数组,但以变量作为数组长度并非标准规定。

// 声明时就初始化
int arr[5] = {1, 2, 3, 4, 5};
int arr[5] = {1, 2, 3};  // arr = {1, 2, 3, 0, 0}

// 先声明,后初始化
int arr[5];
for( int i=0; i<5; i++){
    arr[i] = i;
}

// 用变量指定数组长度之一:依赖于特定编译器支持,非标准
const int arrSize = 10;
int arr[arrSize] = {1, 2, 3, 4, 5};

// 用变量指定数组长度之二:定义编译时常量来
constexpr int arrSize = 5;
int arr[arrSize];

1.1.2 动态数组

/* 使用malloc */
int arrSize = 10;
int *arr = reinterpret_cast<int*>(malloc(sizeof(int) * arrSize));
for( int i=0; i<arrSize; i++){
    arr[i] = i;
}
// 销毁
free(arr);
arr = nullptr;


/* 使用new关键字 */
int arrSize = 10;
int *arr = new int[arrSize];
for( int i=0; i<arrSize; i++){
    arr[i] = i;
}
delete[] arr;  // delete[] 专门用于释放动态数组内存

1.2 二维数组

1.2.1 固定形式

在定义多维数组时,除了最左边的维度可以省略,其他维度都必须明确指定大小。

// 指定行列长度
int rowNum = 5;
int colNum = 5;
int arr[rowNum][colNum];
for(int i=0; i<=rowNum; i++){
    for(int j=0; j<=colNum; j++){
        arr[i][j] = i+j;
    }
}

// 仅指定列长度,必须声明时初始化
int arr[][5] = {
    {1, 2, 3, 4, 5},
    {1, 2, 3 },
    {1, 2,}
};  // 得到3行5列的矩阵

1.2.2 动态形式

/* malloc */
int rowNum = 5;
int colNum = 5;
int **arr = reinterpret_cast<int**>(malloc(sizeof(int *) * rowNum));
for(int i=0; i<rowSize; i++){
    arr[i] = reinterpret_cast<int*>(malloc(sizeof(int) * colNum));
    for(int j=0; j<colNums; j++){
        arr[i][j] = i+j;
    }
}
// 释放内存
for(int i=0; i<rowNum; i++){
    free(arr[i]);
}
free(arr);
arr = nullptr;

/* new */
int rowNum = 5;
int colNum = 5;
int **arr = new int*[rowNum];
for(int i=0; i<rowSize; i++){
    arr[i] = new int[colNum];
    for(int j=0; j<colNum; j++){
        arr[i][j] = i+j;
    }
}
for(int i=0; i<rowNum; i++){
    delete[] arr[i];
}
delete[] arr;
arr = nullptr;

1.3 数组作为函数参数

1.3.1 函数参数之一维数组

像int[9], int[]这样的函数参数声明,在执行中将会退化为int *
而传入int[n]类型的实参,将隐式类型转换为int *

// 数组形式
void printArr1(int arr[], int arrSize){
    for(int i=0; i<arrSize; i++){
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}

// 指针形式
void printArr2(int *arr, int arrSize){
    for(int i=0; i<arrSize; i++){
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}

// 调用
const int arrSize = 10;
int arr[arrSize] = {1, 2, 3};
printArr1(arr, arrSize);  // 实参类型int [10], 函数参数为int[]类型,退化为int *类型,隐式类型转换:int[10] -> int *
printArr2(arr, arrSize);  // 实参类型int [10], 函数参数类型为int *,隐式类型转换:int[10] -> int *

1.3.2 函数参数之二维数组

二维数组作为函数参数时也会退化为指针。具体来说,int [m][n]int [][n] 都会退化为指向长度为 n 的一维数组的指针,即 int (*)[n]

// 只在C语言C99标准以后允许这种参数形式:int [][cols],cols为同一参数列表中的参数
void printArr1_2(const int rows, const int cols, int arr[][cols]){
    for(int i=0; i<rows; i++){
        for(int j=0; j<cols; j++){
            std::cout << arr[i][j] << " ";
        }
        std::cout << std::endl;
    }
}


// C++中作为函数参数的二维数组:二维指针形式
void printMatrix1(int rows, int cols, int **arr){
    for(int i=0; i<rows; i++){
        for(int j=0; j<cols; j++){
            std::cout << arr[i][j] << " ";
        }
        std::cout << std::endl;
    }
}

// C++中作为函数参数的二维数组:int[m][n]形式,其中m,n为字面量
void printMatrix2(int rows, int cols, int arr[5][5]){  // int [5][5] -> int (*)[5]
    for(int i=0; i<rows; i++){
        for(int j=0; j<cols; j++){
            std::cout << arr[i][j] << " ";
        }
        std::cout << std::endl;
    }
}

// C++中作为函数参数的二维数组:int[m][n]形式,其中m,n为字面量
void printMatrix3(int rows, int cols, int arr[][5]){  // int [][5] -> int (*)[5]
    for(int i=0; i<rows; i++){
        for(int j=0; j<cols; j++){
            std::cout << arr[i][j] << " ";
        }
        std::cout << std::endl;
    }
}

int main(){
    // 调用
    const int rows = 3;
    const int cols = 5;
    int mat1[][5] = {
        {1, 2, 3},
        {1, 2},
        {1}
    };
    int mat2[3][5] = {
        {1, 2, 3},
        {1, 2},
        {1}
    };
    int **mat3 = new int*[5];
    for(int i=0; i<5; i++){
        mat3[i] = new int[5];
    }
    for(int i=0; i<5; i++){
        for(int j=0; j<5; j++){
            mat3[i][j] = i+j;
        }
    }

    printMatrix1(3, 5, mat1);  // error: int[3][5] -/-> int **
    printMatrix1(3, 5, mat2);  // error: int[3][5] -/-> int **
    printMatrix1(3, 5, mat3);  // int ** --> int **
    printMatrix2(3, 5, mat1);  // int [3][5] --> int (*)[5]
    printMatrix2(3, 5, mat2);  // int [3][5] --> int (*)[5]
    printMatrix2(3, 5, mat3);  // error: int ** -/-> int (*)[5]
    printMatrix3(3, 5, mat1);  // int [3][5] --> int (*)[5]
    printMatrix3(3, 5, mat2);  // int [3][5] --> int (*)[5]
    printMatrix3(3, 5, mat3);  // error: int ** -/-> int (*)[5]
}

1.4 数组作为返回值

返回值类型不能是int[]或者int [][4]这种类型,函数要返回数组只能通过

int* careateArr(int arrSize){
    int *arr = new int[arrSize];
    for(int i = 0; i < arrSize; i++){
        arr[i] = i;
    }
    return arr;
}

// 调用
const int arrSize = 10;
int *arr = createArr(arrSize);

1.5 补充

1.5.1 reinterpret_cast和static_cast的区别

reinterpret_cast:不做类型检查,不安全。一般用于转换指针的类型,指针和整数类型之间互换。

static_cast:做类型价差,安全。一般用于转换数值类型,基类和派生类转换,显式地做隐式类型转换。

// reinterpret_cast: 转换指针类型
void *p1 = nullptr;
int *p2 = reinterpret_cast<int *>(p);


// static_cast:转换数值类型
int a = 10;
float af = static_cast<float>(a);

// static_cast:基类和派生类之间转换(向上转安全(派生类指针转基类指针),向下转不安全(基类指针转派生类指针))
class Base {};
class Derived : public Base {};
Derived derived;
Base* basePtr = static_cast<Base*>(&derived); // 向上转换,安全

1.5.2 多维数组一维化

i n d = i 1 ⋅ ∏ j > 1 n j + i 2 ⋅ ∏ j > 2 n j + . . . + i q − 1 ⋅ n q + i q ,   j ∈ N ; i k = 0 , 1 , 2 , . . . , n k − 1 , 其中 k = 1 , 2 , . . . , q ind = i_1\cdot\prod_{j>1}n_j+i_2\cdot\prod_{j>2}n_j+...+i_{q-1}\cdot n_q+i_q, \space j\in N; i_k=0,1,2,...,n_{k-1},其中k=1,2,...,q ind=i1j>1nj+i2j>2nj+...+iq1nq+iq, jN;ik=0,1,2,...,nk1,其中k=1,2,...,q

2 string字符串

2.1 转换

2.1.1 C字符串和string字符串互换

char s1[32] = "Hello, World!";
std::string s2(s1);				// C字符串转string
const char *s3 = s2.c_str();    // string转C字符串

2.1.2 数值类型转和string字符串互换

仅限数值类型

#include<string>

// 数值类型转换为string类型
int a = 10;
float b = 1.11;
string aStr = to_string(a);
string bStr = to_string(b);

// string类型转换为数值类型:stringstream
#include <sstream>
string s = "1.1";
float a = 0.0;
stringstream ss(s);
ss >> a;    
string s = "1.1";
float a = 0.0;
stringstream ss(s);
ss >> a;

2.1.3 sstream用法

读取sentence,将word放在string数组里


#include <sstream>

vector<string> words;
string word;
string sentence = "hello world in C++"
stringstream ss(sentence);
while(ss >> word){
	words.push_back();
}

stringstream对象绑定到新的string

#include <sstream>

string s1 = "hello";
string s2 = "world";
stringstream ss(s1);
string rStr;
ss >> rStr;

// ss绑定到新的string对象s2上,绑定后最好重置流状态再使用
ss.str(s2)
ss.clear();
ss >> rStr;

2.2 子串

2.2.1 查找

// 查找函数原型
size_t find (constchar* s, size_t pos = 0) const;
size_t find (charc, size_t pos = 0) const;
size_t rfind (constchar* s, size_t pos = npos) const;
size_t rfind (charc, size_t pos = npos) const;

size_t find_first_of (const char* s, size_t pos = 0) const;  // 从给定位置,在母串中查找第一个位于子串的字符
size_t find_first_not_of (const char* s, size_t pos = 0) const;  // 从给定位置,在母串中查找第一个不在子串中的字符
size_t find_last_of(const char* s, size_t pos = npos) const;  // 从母串中查找最后一个位于子串的字符的位置
size_tfind_last_not_of (const char* s, size_t pos = npos) const;  // 从母串中查找最后一个没有位于子串中的字符的位置


// case1:第一次出现的位置
std::string s = "abctext123abc";
std::string substr = "text";
int pos = s.find(substr);  // 3

// case2:最后一次出现的位置(也可使用正则表达式进行复杂查找)
std::string s = "abctext123textabc";
std::string substr = "text";
int pos = s.rfind(substr);  // 10

2.2.2 替换

std::string s = "abctext123abc";
std::string substr = "text";
std::string substitute = "TEXT";
int substrPos = s.find(substr);
s.replace(pos, substr.length(), substitute);


// 字符串替换
a.replace(6, 10, "C++11");  		// "hello, world!!!" -> "hello, C++11!!!"
a.replace(0, 5, 3, 'a');  			// "hello, C++11" -> "aaaa, C++11"
a.replace(begin_it, end_it, "xxx")  // 将区间内的子串替换为"xxx"

2.2.3 获取

std::string s = "abctext123abc";
std::string substr = s.substr(3,4);  // substr = "text"

2.2.4 合并

// +
std::string s1 = "Hello";
std::string s2 = "World";
std::string s3 = s1 + ", " + s2;  // Hello, World

// append
std::string s1 = "Hello";
std::string s2 = "World";
s1.append(s2);  		// HelloWorld
str1.append(s2, 3, 3);  // Hellold

// stringstream
#include<sstream>
std::string s1 = "Hello";
std::string s2 = "World";
std::stringstream ss;
ss << s1 << s2;
std::string s3 = ss.str();  // HelloWorld

// sprintf
const char* str1 = "Hello";
const char* str2 = "World";
char result[100];
std::snprintf(result, sizeof(result), "%s%s", str1, str2);  // result = "HelloWorld"

以分隔符分割字符串
// 1. 使用istream流
char split = '.';
string token;
istringstream iss(str);
while( getline( iss, token, split ) ){
    cout << token << endl;
}

// 2.使用strtok,strtok_r()/strtok_s()
char s[] = "hello,world,this,is,a,test";
// strtok()方式,非线程安全
const char split[] = ";, ?"
char *token = NULL;
token = strtok(str, ",");
while (token != NULL) {
    printf("%s\n", token);
    token = strtok(NULL, ",");
}
// strtok_r()/strtok_s(),线程安全
char *ptr = NULL, *token = NULL;
token = strtok_r( s, split, &ptr );
while( token != NULL){
    cout << token << endl;
    token = strotok_r( NULL, split, &ptr );
}

// 3.find() + substr()
void splitStr(const string& rawStr, const char split, vector<string>& res){
    if (rawStr == "")
        return;
    string token;
    string tmpStr = rawStr + split;
    size_t pos = tmpStr.find(split);
    while ( pos != -1 ){
        token = tmpStr.substr(0, pos);
        res.push_back(token);
        tmpStr.replace( 0, pos + 1, "");
        pos = tmpStr.find(split);
    }
}
其他操作
// 遍历字符:下标法,迭代器(正向、反向)


// 插入单个字符
string s;
s.push_back('a');
s.insert( s.begin(), 'b' );

// 删除字符
a.erase(0, 7);  			// "hello, world!!!" -> "world"
a.erase(iter);  			// 删除迭代器iter指向的字符
a.erase(begin_ir, end_it);  // 删除去区间内的字符

// 大小写转换:tolower(), toupper()
for( size_t i = 0; i < a.size() ; ++i )
    a[i] = tolower(a[i]);  // toupper(a[i])

// 大小写转换:STL transform
#include <algorithm>
transform( a.begin(), a.end(), a.begin(), ::tolower )
    
// 排序
sort(a.begin(), a.end());

2.3 时间字符串

2.3.1 获取时间戳

// C++11以后:方法一:先转换时间按点对象为指定精度的时间点对象,再计算该单位下的时间戳
#include <chrono>
auto now = chrono::system_clock::now();  							// 获取当前时间点对象
auto now_ms = chrono::time_point_cast<chrono::milliseconds>(now);	// 将时间点对象转换为毫秒精度的时间点对象
auto duration = now_ms.time_since_epoch();							// 获取以毫秒计数的时间间隔对象(从基准时间开始计)
long long timestamp = duration.count();								// 获取毫秒级时间戳

// C++11以后:方法二,先得到时间间隔对象,再将时间间隔对象转换为指定时间单位,计算该单位下的时间戳
#include <chrono>
auto now = chrono::system_clock::now();  							// 获取当前时间点对象
auto d = now.time_since_epoch();									// 获取时间间隔对象
auto timestamp = chrono::duration_cast<chrono::seconds>(d).count(); // 获取秒级时间戳

// C风格
#include<ctime>
time_t timestamp = std::time(nullptr);  // time_t是long的别名,秒级

2.3.2 时间戳和时日期字符串相互转换

时间戳转时间日期字符串
#include <sstream>
#include <iomanip>
#include <ctime>
std::string timestampToDateString(long long timestamp) {
    // 将时间戳转换为 std::time_t 类型
	std::time_t time = static_cast<std::time_t>(timestamp);
    // 使用 std::localtime 将时间转换为本地时间结构
	std::tm* localTime = std::localtime(&time);

    // 使用 std::ostringstream 格式化时间
    std::ostringstream oss;
    oss << std::put_time(localTime, "%Y-%m-%d %H:%M:%S");  // from <iomanip>
    return oss.str();
}
时间日期字符串转时间戳
long long stringToTimestamp(const std::string& dateString) {
    std::tm tm = {};
	std::istringstream ss(dateString);
    // 按照指定格式解析输入的时间日期字符串
    ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
    if (ss.fail()) {
        std::cerr << "Failed to parse the date string." << std::endl;
        return -1;
    }
    // 将 tm 结构体转换为以秒为单位的时间戳
    return std::mktime(&tm);
}

// 调用stringToTimestamp
std::string dateString = "2024-10-01 12:00:00";
long long timestamp = stringToTimestamp(dateString);
if (timestamp != -1) {
    std::cout << "Timestamp (seconds): " << timestamp << std::endl;
}

3 文件操作

3.1 使用文件流对象写

3.1.1 基本用法

/*
文件打开模式
- ios::out 覆写模式,以此模式打开已存在文件,文件会被截顶(truncated),则输入数据将覆盖文件原有内容
- ios::app 追加模式,以此模式打开已存在文件则写入数据将追加到原有数据之后
*/
#include <fstream>
using namespace std;

int main() {
    // 创建一个输出文件流对象时打开文件
    ofstream outFile1("output.txt", ios::out);  // 如果没有改文件,则会创建一个

    // 先创建一个输入文件流对象,再打开文件
    ofstream outFile2;
    outFile2.open("output.txt", ios::app);

    string content1 = "Hello, World!";
    string content2 = "C++ Programming";

    outFile1 << content1 << endl;
    outFile2 << content2 << endl;
    
    outFile1.close();
    outFile2.close();

    return 0;
}

3.1.2 指定位置读取:seekg,即seek get

/* output.txt
Hello, World!
C++ Programming

*/

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    // 创建输入文件流对象时,打开文件
    string s;
    ifstream inFile1("output.txt", ios::in);
    inFile1.seekg(-5, ios::end);  // 将读指针从文件末尾往前移动5个字节。最后5个字符为"ming\n"
    inFile1 >> s;				  // 碰到第一个空字符("\n")终止
    cout << s << endl;			  // "ming"

    inFile1.seekg(5, ios::beg);  // 将读指针从文件起始位置往后移动5个字节
    inFile1 >> s;				 // 从","开始直到遇到第一个空字符(" ")
    cout << s << endl;			 // ","
    
    int curPos = inFile1.tellg();// 获取输入文件对象的当前指针位置
    cout << curPos << endl;		 // 6
    inFile1.seekg(1, ios::cur);  // 跳过","后的空字符" ",文件指针在第7个字节处(第7个字节尾,第8个字节首)
    inFile1 >> s;				 // 遇到的第一个空字符为("\n")
    cout << s << endl;			 // "World!"

    inFile1.close();
    return 0;
}

3.2 使用文件流对象读

3.2.1 基本用法

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    // 创建输入文件流对象时,打开文件
    ifstream inFile1("output.txt", ios::in);
    string s;
    inFile1 >> s;
    while(getline(inFile1, s)){
        cout << s << endl;
    }
    inFile1.close();
    return 0;
}

3.2.2 指定位置写入:seekp,即seek put。

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    // 创建输入文件流对象时,打开文件
    string s;
    ofstream outFile("output.txt", ios::out);
    outFile << "Hello, world!";

    outFile.seekp(7, ios::beg);
    outFile.put('W');
    outFile.seekp(-8, ios::end);
    outFile.put(';');
    outFile.seekp(1, ios::cur);  // "Hello; World!"
    outFile << "C++!";           // "Hello; C++!d"
    outFile.close();
    return 0;
}

3.3 顺序文件

指文件中的数据按照顺序依次存储,在访问时也只能按照顺序依次读取或写入,即从文件开头开始,逐个数据项地进行操作,不能直接跳转到文件中间的某个位置进行读写。

3.3.1 创建顺序文件

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

int main(){
    ofstream outClientFile( "clients.txt", ios::out );
    if ( !outClientFile ){
        cerr << "File could not be opened" << endl;
        // 将EXIT_SUCCESS传递给exit(),表明程序正常退出,将EXIT_FAILURE传递给exit(),表明程序异常退出。EXIT_SUCCESS和EXIT_FAILURE定义在<cstdlib>中
        exit( EXIT_FAILURE );
    }
    cout << "Enter the account, name, and balance." << endl
        << "Enter end-of-file to end input.\n? ";
    int account;
    string name;
    double balance;

    while ( cin >> account >> name >> balance ){
        outClientFile << account << ' ' << name << ' ' << balance << endl;
        cout << "? ";
    }
}

3.3.2 读取顺序文件

#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstdlib>
using namespace std;

void outputLine( int, const string&, double );

int main(){
    ifstream inClientFile( "clients.txt", ios::in );
    if( !inClientFile ){
        cerr << "File could not be opened" << endl;
        exit(EXIT_FAILURE);
    }
    int account;
    string name;
    double balance;

    cout << left << setw( 10 ) << "Account" << setw( 13 )
        << "Name" << "Balance" << endl << fixed << showpoint;
    
    while ( inClientFile >> account >> name >> balance )
        outputLine( account, name, balance );
}

void outputLine( int account, const string &name, double balance ){
    cout << left << setw( 10 ) << account << setw( 13 ) << name
        << setw( 7 ) << setprecision( 2 ) << right << balance << endl;
}

3.4 随机存取文件

允许程序直接访问文件中的任意位置,而不必按照数据的存储顺序依次访问。可以通过指定文件指针的位置,快速定位到文件中的特定位置进行读写操作。

3.4.1 创建随机存取文件

头文件:ClientData类的声明
#ifndef CLIENTDATA_H
#define CLIENTDATA_H

#include <string>

class ClientData{
public:
    ClientData( int = 0, const std::string & = "",
        const std::string& = "", double = 0.0 );

    void setAccountNumber( int );
    int getAccountNumber() const;

    void setLastName( const std::string & );
    std::string getLastName() const;

    void setFirstName( const std::string & );
    std::string getFirstName() const;

    void setBalance( double );
    double getBalance() const;
private:
    int accountNumber;
    char lastName[ 15 ];
    char firstName[ 10 ];
    double balance;
};

#endif

源文件:ClientData类的定义
#include <string>
#include "ClientData.h"
using namespace std;

ClientData::ClientData( int accountNumberValue, const string &lastNameValue,
    const string &firstNameValue, double balanceValue )
    : accountNumber( accountNumberValue ), balance( balanceValue )
{
    setLastName( lastNameValue );
    setFirstName( firstNameValue );
}

int ClientData::getAccountNumber() const{
    return accountNumber;
}

void ClientData::setAccountNumber( int accountNumberValue ){
    accountNumber = accountNumberValue;
} 

string ClientData::getFirstName() const {
    return firstName;
}

void ClientData::setFirstName( const string & firstNameString ) {
    int length = firstNameString.size();
    length = ( length < 10 ? length : 9 );
    firstNameString.copy( firstName, length );
    firstName[length] = '\0';
}

string ClientData::getLastName() const {
    return lastName;
}

void ClientData::setLastName( const string & lastNameString ) {
    int length = lastNameString.size();
    length = ( length < 10 ? length : 9 );
    lastNameString.copy( lastName, length );
    lastName[length] = '\0';
}

double ClientData::getBalance() const {
    return balance;
}

void ClientData::setBalance( double balanceValue ) {
    balance = balanceValue;
}
源文件:创建随机存取文件
#include <iostream>
#include <fstream>
#include <cstdlib>
#include "../MyClass/ClientData/ClientData.h"
using namespace std;

int main(){
    ofstream outCredit( "credit.dat", ios::out | ios::binary );
    if( !outCredit ){
        cerr << "File could not be opened." << endl;
        exit( EXIT_FAILURE );
    }
    ClientData blankClient;
    for( int i = 0;  i < 100; ++i ){
        outCredit.write( reinterpret_cast<const char * >( &blankClient ), sizeof(ClientData) );
    }
}

3.4.2 读取随机存取文件

#include <iostream>
#include <fstream>
#include <cstdlib>
#include "../MyClass/ClientData/ClientData.h"
using namespace std;

int main(){
    int accountNumber;
    string lastName;
    string firstName;
    double balance;

    fstream outCredit( "credit.dat", ios::out | ios::in | ios::binary );
    if( !outCredit ){
        cerr << "File could not be opened." << endl;
        exit( EXIT_FAILURE );
    }
    cout << "Enter acoount number (1 to 100, 0 to end input)\n?";
    ClientData client;
    cin >> accountNumber;
    while( accountNumber > 0 && accountNumber <= 100 )
    {
        cout << "Enter lastname, firstname, balance\n?";
        cin >> lastName;
        cin >> firstName;
        cin >> balance;
        client.setAccountNumber(accountNumber);
        client.setLastName(lastName);
        client.setFirstName(firstName);
        client.setBalance(balance);
        outCredit.seekp((client.getAccountNumber() - 1) * sizeof( ClientData ));
        outCredit.write(reinterpret_cast<const char *>(&client), sizeof(ClientData));
        cout << "Enter account number\n?";
        cin >> accountNumber;
    }
}

4. 参考

Deitel, H. M., & Deitel, P. J. (2020). C++ How to Program (11th ed.). Pearson.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值