20220222

C++ Primer Plus - 第五、六章

  • 附录:
    • 1.ASCII码字符对照表
    • 2.C++ 运算符优先级
  • 第1-3章
  • 第4章 复合类型
  • 第5章 循环和关系表达式
    • 5.1 for循环
      • 5.1.1 for循环的组成部分---表达式和语句的区别、输出true和false
      • 5.1.2 回到for循环---const int SIZE = 10;为什么书上的程序敲出来会报错???
      • 5.1.6 副作用和顺序点
      • 5.1.7 前缀格式和后缀格式---i++ 和 ++i 的效率(内置类型和用户自定义类型)
      • 5.1.8 递增/递减运算符和指针---优先级:后缀 > 前缀 == 解引用 pt++、++* pt 、*++pt、(*pt)++
      • 5.1.10 复合语句(语句块)
      • 5.1.11 其他语法技巧---逗号运算符
      • 5.1.12 关系表达式---优先级:算术 > 关系运算符(>、<、=、>=、<=、!=、==)
      • 5.1.13 赋值、比较和可能犯的错误---判断是否相等的时候用==,而不是=
    • 5.2 while循环
      • 5.2.2 编写延时循环---#include< ctime>
    • 5.2.2 类型别名(为已有类型建立一个新名称)---typedef 优于 #define
    • 5.3 do-while循环
    • 5.4 基于范围的for循环(C++11)
    • 5.5 循环和文本输入
      • 5.5.1 5.5.2 5.5.3 --- 逐个字符`char ch;`输入
      • 5.5.4 5.5.5 ---判断是否到达文件尾EOF
    • 5.6 嵌套循环和二维数组
      • 区分 char数组/字符数组、字符串指针数组、string对象数组 ☆☆☆
    • 5.7 总结
    • 5.8 复习题
      • 第 1 题 入口循环条件 & 出口循环条件入口
      • 第 4 题 C++ 运算符优先级
      • 第 8 题 逗号运算符
      • 第 9 题 区分cin >> ch; 和 cin.get(ch); 和 ch = cin.get(); ☆☆☆
    • 5.9 编程练习
      • 第7、7'、8、9题的汇总☆☆☆
      • 第 7 题 用`字符数组`读入数字和字符串
      • 第 7' 题 用`string对象`读入数字和字符串
      • 第 8 题 用`字符数组`每次读入一个单词
      • 第 9 题 用`string对象`每次读入一个单词
      • 第 10 题 打印星星
  • 第6章 分支语句和逻辑运算符
    • 6.1 if语句
    • 6.2 逻辑表达式
      • 各种数据类型的取值范围---头文件#include< climits>
    • 6.3 字符函数库cctype --- 头文件#include< cctype>
      • cctype中的字符函数 --> 编程练习第1题
    • 6.4 三目运算符(? :)
    • 6.5 switch语句
    • 6.6 break和continue语句
      • 补充:空间std的使用规则☆☆☆ && 头文件中string与string.h的区别☆☆☆
        • ①名称空间std
        • ②string和string.h的区别
        • ③using声明 和 using编译指令 之间有何区别?
    • 6.7 读取数字的循环
    • 6.8 简单文件输入/输出
      • 6.8.1 文本I/O 和 文本文件
      • 6.8.2 写入到文本文件中---ofstream类
      • 6.8.3 读取文本文件
      • 补充:如何在Linux中创建一个文档
    • 6.9 总结
    • 6.10 复习题
      • 第1题:两个`if` 和 `if - else if`的区别
      • 第2题:字符变量`ch + 1`和`ch++`的区别
      • 第3题:
      • 第4题:判断字符变量ch是否是字母 `isalpha(ch)`
      • 第5题:!!x 和 x 等价吗
      • 第8题:把`字符char ch;`作为 (switch语句的菜单选项和case标签)的优点在哪里?---程序2
      • 第9题:while(ch = cin.get() != 'Q')语法有问题吗?
    • 6.11 编程练习
      • 第1题:大小写字母反转
      • 第2题:如何判断输入的数据是不是数字?
      • 第2'题:测试 char、int、double类型 在什么情况下会输入失败
      • 第7题:
      • 第8题:逐字符读取文件并统计字符个数,并解决字符个数总多一个的问题
      • 第9题:逐行读取文件内容(字符串和数字),数字和字符串的相互转换
  • 第七章 函数---C++的编程模块

附录:

1.ASCII码字符对照表

点这里

2.C++ 运算符优先级

点这里

第1-3章

点这里

第4章 复合类型

点这里

第5章 循环和关系表达式

5.1 for循环

5.1.1 for循环的组成部分—表达式和语句的区别、输出true和false

①输出true和false;
②表达式age = 100 和 语句age = 100; 的区别;

5.1.2 回到for循环—const int SIZE = 10;为什么书上的程序敲出来会报错???


const int SIZE = 10;

代码:

#include<iostream>
using namespace std;const int size = 10;int main() {//5.1.2int arr1[size];//size不明确for (int i = 0; i < size; i++) {//size不明确cout << i + 1 << " ";}system("pause");return 0;
}



5.1.6 副作用和顺序点


while(guests++ < 10)
cout << guests << endl;

程序执行的顺序是:
先是guests < 10
然后guests++
最后cout << guests


y = (4 + x++) + (6 + x++);
C++没有规定是在计算每个子表达式之后将x的值递增,还是在整个表达式计算完毕后才将x的值递增,所以应避免使用上面的写法。

5.1.7 前缀格式和后缀格式—i++ 和 ++i 的效率(内置类型和用户自定义类型)


for(int i = 0; i < 10; i++)//后缀格式

for(int i = 0; i < 10; ++i)//前缀格式

对于内置类型来说,上面两种格式没有差别;
但对于用户自定义的类型,如果有用户定义的递增和递减运算符,则前缀格式的效率更高,原因见下面:

这篇博客解释的很清楚:C++ 递增运算符:前置++和后置++的区别
首先说下结论:迭代器和其他模板对象应该使用前缀形式 (++i) 的自增,,自减运算符,因为前置自增 (++i) 通常要比后置自增 (i++) 效率更高

前置++和后置++,有4点不同:返回类型不同、形参不同、代码不同、效率不同:


int main()
{     Age a;     (a++)++;  //编译错误     ++(a++);  //编译错误     a++ = 1;   //编译错误     (++a)++;  //OK     ++(++a);  //OK     ++a = 1;   //OK
} 
  1. 返回类型不同
    前置++的返回类型是左值引用,后置++的返回类型const右值。而左值和右值,决定了前置++和后置++的用法。
    问:++a的返回类型为什么是引用呢?
    答:为了与内置类型的行为保持一致。前置++返回的总是被自增的对象本身。因此,++(++a)的效果就是a被自增两次。
  2. 形参的区别
    前置++没有形参,而后置++有一个int形参,但是该形参也没有被用到。很奇怪,难道有什么特殊的用意?
    其实也没有特殊的用意,只是为了绕过语法的限制
    前置++与后置++的操作符重载函数,函数原型必须不同,否则就违反了“重载函数必须拥有不同的函数原型”的语法规定。
    虽然前置++与后置++的返回类型不同,但是返回类型不属于函数原型。为了绕过语法限制,只好给后置++增加了一个int形参。
    原因就是这么简单,真的没其他特殊用意。其实,给前置++增加形参也可以;增加一个double形参只要不是int形参就可以。只是,当时就这么决定了。
  3. 代码实现的区别
    前置++的实现比较简单,自增之后,将*this返回即可。需要注意的是,一定要返回*this
    后置++的实现稍微麻烦一些。因为要返回自增之前的对象,所以先将对象拷贝一份,再进行自增,最后返回那个拷贝
  4. 效率的区别
    如果不需要返回自增之前的值,那么前置++和后置++的计算效果都一样。但是,我们仍然应该优先使用前置++,尤其是对于用户自定义类型的自增操作
    前置++的效率更高,理由是:后置++会生成临时对象

C++Primer中(P132)有这样简介的描述:
前置版本将对象本身作为左值返回,后置版本则将原始对象的副本作为右值返回,两种运算符必须作用于左值运算对象。后置版本需要拷贝副本,所以会影响程序的性能

在C++笔记10:运算符重载中有为自定义数据类型重载++运算符的内容 ,具体代码就是上面的第3点 代码实现的区别所说的:
用类成员函数实现的

//重载++运算符://前置++:MyInt& operator++() {//为什么要返回引用,是为了一直对一个数据(这里是自定义数据---类)进行递增操作num++;//先++return *this;//再返回对象本身this}//后置++:MyInt operator++(int) {//这里的int代表占位参数,可以用于区分前置和后置递增,//141和134两行属于重载,重载的条件是参数的个数、顺序、类型不同,//所以就加了个int,而且编译器只认int,其他的都不行,只有int可以区分开类++和++类MyInt temp = *this;//先记录对象本身thisnum++;//后++return temp;//最后将记录的返回,注意这里返回的是值,不是引用&}

5.1.8 递增/递减运算符和指针—优先级:后缀 > 前缀 == 解引用 pt++、++* pt 、*++pt、(*pt)++


//前缀递增、前缀递减、解引用运算符优先级相同;
//后缀递增、后缀递减优先级相同,且高于前缀和解引用运算符。

//5.1.8//前缀递增、前缀递减、解引用运算符优先级相同://后缀递增、后缀递减优先级相同,且高于前缀和解引用运算符。double arr[5] = { 11.1,22.2,33.3,44.4,55.5 };double* pt = arr;for (int i = 0; i < 5; i++) {cout << *(pt + i) << ", ";}cout << "\n" << endl;      //11.1, 22.2, 33.3, 44.4, 55.5cout << "*pt = " << *pt << "\n" << endl;//11.1//前缀递增 和 解引用运算符:cout << "*++pt = " << *++pt << endl;//22.2 相当于*(++pt)cout << "*pt = " << *pt << endl;//22.2cout << "++*pt = " << ++*pt << endl;//23.2 相当于++(*pt)cout << "*pt = " << *pt << endl;//23.2cout << endl;//后缀递增 和 解引用运算符:cout << "(*pt)++ = " << (*pt)++ << endl;//23.2 cout << "*pt = " << *pt << endl;//24.2cout << "*pt++ = " << *pt++ << endl;//24.2 相当于*(pt++)cout << "*pt = " << *pt << endl;//33.3cout << endl;//前缀递增、后缀递增、后缀递减、前缀递减:++pt;cout << "*pt = " << *pt << endl;//44.4pt++;cout << "*pt = " << *pt << endl;//55.5pt--;cout << "*pt = " << *pt << endl;//44.4--pt;cout << "*pt = " << *pt << endl;//33.3cout << endl;for (int i = 0; i < 5; i++) {cout << arr[i] << ", ";}cout << endl;                   //11.1, 24.2, 33.3, 44.4, 55.5

结果:

5.1.10 复合语句(语句块)

5.1.11 其他语法技巧—逗号运算符

5.1.12 关系表达式—优先级:算术 > 关系运算符(>、<、=、>=、<=、!=、==)

①关系运算符的优先级比算术运算符低;
②关系表达式对两个值进行比较,常被用作循环测试条件。

5.1.13 赋值、比较和可能犯的错误—判断是否相等的时候用==,而不是=


对于第二种情况,书中的解释:由于它将20赋给数组元素quizscores[i],因此表达式始终为非零,所以始终为true。

也可以看看5.1.1.的②:表达式 和 语句

5.2 while循环

5.2.2 编写延时循环—#include< ctime>

#include<iostream>
#include<ctime>
using namespace std;int main() {cout << "请输入您想要延迟的时长(单位:秒/s):";float sec;cin >> sec;clock_t delay = sec * CLOCKS_PER_SEC;//5*1000clock_t start = clock();while (clock() - start < delay) {//if ((clock() - start) > 0 && (clock() - start) % CLOCKS_PER_SEC == 0)//1000的整数倍:1000,2000,3000...//  cout << "第 " << (clock() - start) / CLOCKS_PER_SEC  << " 秒" << endl;}cout << "clock() = "<< clock()<<",共计时 " << (clock() - start) / CLOCKS_PER_SEC << " 秒。" << endl;system("pause");return 0;
}

5.2.2 类型别名(为已有类型建立一个新名称)—typedef 优于 #define

①#define(没分号
#define SIZE 100 //SIZE是100的别名
#define BYTE char //BYTE 是 char类型 的别名,预处理器将在编译程序时用char 替换所有的BYTE

注意:当需要声明一系列变量时,这种方法不适用:

②typedef (有分号
typedef char byte; //byte 是 char类型 的别名
typedef char* byte_pointer; //byte_pointer 是 char指针 的别名
typedef int word; //word 作为 int 的别名,那么cout将把word类型的值视为int类型

注意:
typedef不会创建新类型,而只是为已有的类型建立一个新名称。

5.3 do-while循环

do-while循环是出口条件(exit condition)循环:先执行循环体,然后再判定测试表达式,决定是否继续执行循环;
for循环和while循环是一种入口条件循环:如果测试条件为非零,则进入循环执行循环体;如果测试条件一开始就是false,则不会进入循环。

5.4 基于范围的for循环(C++11)

5.5 循环和文本输入

5.5.1 5.5.2 5.5.3 — 逐个字符char ch;输入

5.5.1 使用原始的cin进行输入

①直接用cin << ch;会忽略空格和换行符;
②为什么#后面还能输入字符?—见下图

5.5.2 使用cin.get(char)进行补救
①cin所属的istream类的一个成员函数cin.get(ch)可以读取输入的下一个字符(包括空格符),然后赋值给变量ch;
②#后面的内容依然会被缓冲,因此输入的字符个数仍可能比最终到达程序的要多。

思考:

//5.5.1 5.5.2char ch;int count = 0;//cin >> ch;//5.5.1cin.get(ch);//5.5.2while (ch != '#') {//#作为结束符cout << ch;count++;//cin >> ch;//5.5.1cin.get(ch);//5.5.2}cout << "共输入了 " << count << " 个字符。" << endl;

5.5.3 使用哪一个cin.get() — 函数重载

到目前见到了三种cin.get();

  1. cin.get();//没有参数
  2. cin.get(ch);//一个参数char类型
  3. cin.get(name,20);//两个参数:字符数组名,一次接收的字符数上限(③见第四章的 4.13 编程练习 的 第1题 )

这就是函数重载,函数重载允许创建多个同名函数,条件是他们的参数列表不同。

☆☆☆函数重载的应用:(1和2适合读单个字符,3适合读一整行字符串)

  1. char ch; ch = cin.get();//没有参数,返回值为输入中的下一个字符
  2. char ch; cin.get(ch);//一个参数char类型,参数是引用类型,直接将读到的字符赋给参数ch
  3. char name[20]; cin.get(name,20);//两个参数:字符数组名,一次接收的字符数上限(③见第四章的 4.13 编程练习 的 第1题 )

5.5.4 5.5.5 —判断是否到达文件尾EOF

5.5.4和5.5.5分别介绍了2种和1种方法,几种方法都可行,最终推荐5.5.4的程序2

5.5.4 cin.fail() == false 和 cin.eof() == false

二者都返回的是bool值:遇到EOF就返回true,否则范围false
cin.fail()cin.eof()多,因为前者可用于更多的实现中。


通过键盘模拟文件尾条件(EOF):Ctrl+ZEnter

示例:

程序1:

//5.5.4 5.5.5char ch;int count = 0;cin.get(ch);while (cin.fail() == false) {//判断是否到达文件尾 cin.eof() == false也可以cout << ch;count++;cin.get(ch);}cout << "共输入了 " << count << " 个字符。" << endl;

程序语句进一步精简:

具体的解释:

结论:
所以说,判断是否到达文件尾,可以直接用while(cin),这比cin.fail() == false)cin.eof() == false更通用,因为它可以检测到其他失败原因,如磁盘故障。

程序2:

//程序2:char ch;int count = 0;while (cin.get(ch)) {//判断是否到达文件尾 cout << ch;count++;}cout << "共输入了 " << count << " 个字符。" << endl;

5.5.5 (ch = cin.get()) != EOF


程序3:

//程序3:int ch;int count = 0;while ((ch = cin.get()) != EOF) {cout.put(char(ch));count++;}cout << "共输入了 " << count << " 个字符。" << endl;

程序3和程序1、2的区别在于:①ch是int类型;②循环条件;③输出的语句
为什么是要用int ch;来接收cin.get()的返回值?

分析一下循环条件(ch = cin.get()) != EOF

最后比较下5.5.4和5.5.5的差别:

5.6 嵌套循环和二维数组

C++没有提供二维数组类型,但用户可以创建每个元素本身就是数组的数组。

区分 char数组/字符数组、字符串指针数组、string对象数组 ☆☆☆

//5.6//字符串指针数组:const char* cities[5] = { "beijing","tianjin","xi'an","nanjing","xiamen" };//字符数组:char cities2[5][20]{ "beijing","tianjin","xi'an","nanjing","xiamen" };//string对象数组:const string cities3[5]={ "beijing","tianjin","xi'an","nanjing","xiamen" };

如果希望字符串是可修改的,则应该省略限定符const;
在希望字符串是可修改的情况下,string类自动调整大小的特性将使这种方法比使用二维数组更为方便。

5.7 总结

5.1.8 优先级:后缀 > 前缀 == 解引用* pt++、++* pt 、*++pt、(*pt)++

5.2.2 类型别名

5.6 区分 char数组/字符数组、字符串指针数组、string对象数组

5.5.4 5.5.5 —判断是否到达文件尾EOF

5.8 复习题

第 1 题 入口循环条件 & 出口循环条件入口

入口循环条件:先判断测试条件,如果测试条件为非零,则进入循环执行循环体;如果测试条件一开始就是false,则不会进入循环。for循环和while循环是一种入口条件循环。

出口循环条件:先执行循环体,然后再判定测试表达式,决定是否继续执行循环。do-while循环是一种出口条件循环。

第 4 题 C++ 运算符优先级

C++ 运算符优先级:点这里
优先级:后缀 > 前缀 == 解引用符(*)

优先级:算术 > 关系运算符(>、<、=、>=、<=、!=、==)

第 8 题 逗号运算符

5.1.11 其他语法技巧—逗号运算符

第 9 题 区分cin >> ch; 和 cin.get(ch); 和 ch = cin.get(); ☆☆☆

5.5.1、5.5.2和5.5.5的内容,这里再做个归纳总结:
C++语言要使用输入/输出流进行 单个字符 char ch; 的读取,通常使用3种方式,
分别是cin >> ch;cin.get(ch);ch = cin.get();
其中cin >> ch;将忽略所有空白字符(空格符、换行符、制表符);
cin.get(ch);ch = cin.get(); 将会读取所有ASCII字符并将其保存在ch变量中。

5.9 编程练习

第7、7’、8、9题的汇总☆☆☆

总结:

  1. 如果读取一个单词char name[20]; string str;或一个数字int num; 或一整行string name; char name[20]; —就看①
  2. 如果读取单个字符char ch; —就看③和②

具体内容:
①(看一下第四章-编程练习-第1题下面的综述)

实现方式 读取一个单词或数字 读入一整行
字符数组 char ch[20]; cin >> ch; cin.get();//消除结束符
int num; cin >> num; cin.get();//消除结束符
char name[20];
cin.getline(name,20);
string对象 string str; cin >> str; cin.get();//消除结束符
int num; cin >> num; cin.get();//消除结束符
string name;
getline(cin,name);

②函数cin.get()重载:(1和2适合读单个字符,3适合读一整行字符串)

  1. char ch; ch = cin.get();//没有参数,返回值为输入中的下一个字符
  2. char ch; cin.get(ch);//一个参数char类型,参数是引用类型,直接将读到的字符赋给参数ch
  3. char name[20]; cin.get(name,20);//两个参数:字符数组名,一次接收的字符数上限(③见第四章的 4.13 编程练习 的 第1题 )

③如果要读取单个字符char ch;通常使用3种方式
(推荐用后两种方式,也就是上面②的1和2),

char ch; ①cin >> ch;
cin.get();//消除结束符
②cin.get(ch);
cin.get();//消除结束符
③ch = cin.get();
cin.get();//消除结束符
特点 不会读入空白字符(空格符、换行符、制表符),所以不推荐 将会读取所有ASCII字符并将其保存在ch变量中,具体见上面②的1 将会读取所有ASCII字符并将其保存在ch变量中,具体见上面②的2

第 7 题 用字符数组读入数字和字符串

代码:


//第7题:
struct Cars {char manufacturer[20];//生产商int productiveYear;//生产年份
};int main() {//第7题:cout << "How many cars do you sish to catalog? ";int num_of_car;cin >> num_of_car;cin.get();//消除结束符Cars* car = new Cars[num_of_car];for (int i = 0; i < num_of_car; i++) {cout << "Car #" << i + 1 << ":" << endl;cout << "Please enter the make:";//cin >> car[i].manufacturer;//只能读一个单词cin.getline(car[i].manufacturer, 20);//用这个可以读一整行cout << "Please enter the year made:";cin >> car[i].productiveYear;cin.get();//消除结束符}cout << "Here is  your collection:" << endl;for (int i = 0; i < num_of_car; i++) {cout << car[i].productiveYear << " " << car[i].manufacturer << endl;}delete[] car;system("pause");return 0;
}

第 7’ 题 用string对象读入数字和字符串


代码:


//第7'题:
struct Cars {string manufacturer;//生产商int productiveYear;//生产年份
};int main() {//第7'题:cout << "How many cars do you sish to catalog? ";int num_of_car;cin >> num_of_car;cin.get();//消除结束符Cars* car = new Cars[num_of_car];for (int i = 0; i < num_of_car; i++) {cout << "Car #" << i + 1 << ":" << endl;cout << "Please enter the make:";//cin >> car[i].manufacturer;//只能读一个单词getline(cin,car[i].manufacturer);//用这个可以读一整行cout << "Please enter the year made:";cin >> car[i].productiveYear;cin.get();//消除结束符}cout << "Here is  your collection:" << endl;for (int i = 0; i < num_of_car; i++) {cout << car[i].productiveYear << " " << car[i].manufacturer << endl;}delete[] car;system("pause");return 0;
}

第 8 题 用字符数组每次读入一个单词


 //第8题:char words[20];//字符数组int num_of_words = 0;cout << "请输入单词(以done作为结束的单词):" << endl;while(strcmp("done",words)){num_of_words++;cin >> words;//读取一个单词cin.get();//消除结束符}cout << "一共有" << num_of_words - 1 << "个单词。" << endl;

第 9 题 用string对象每次读入一个单词



代码:

 //第9题:string str;int num_of_words = 0;cout << "请输入单词(以done作为结束的单词):" << endl;while(str != "done"){num_of_words++;cin >> str;//读取一个单词cin.get();//消除结束符}cout << "一共有" << num_of_words - 1 << "个单词。" << endl;

第 10 题 打印星星

第6章 分支语句和逻辑运算符

6.1 if语句

6.1.1

示例1:

#include<iostream>using namespace std;int main() {char ch;cin.get(ch);while (ch != '.') {if (ch == '\n')cout << ch;else//cout << ch + 1;//ch + 1输出的是int型,因为ch加1后就会强制转换成int型cout << ++ch;//++ch输出的是char型,即字符cin.get(ch);}system("pause");return 0;
}

效果:


6.1.2

6.1.3

6.2 逻辑表达式

优先级:算术运算符 > 关系运算符 > 逻辑运算符

用&&运算符和if else if else语句进行群治反胃测试的时候,应确保取值范围之间既没有缝隙,又没有重叠

各种数据类型的取值范围—头文件#include< climits>

如果给读取int值的程序输入一个过大的值,C++将会把其截短为合适的大小(int类型数据范围),却并不会通知用户丢失了数据。
以下的程序可以避免这样的问题:
它首先将可能的int值作为double值来读取,double类型的精度足以存储典型的int值,且取值范围更大。

示例代码:

#include<iostream>
#include<climits>using namespace std;
bool is_int(double num){if(num <= INT_MAX && num >= INT_MIN)return true;else return false;
}
int main(){//程序清单6.7.cppcout<<"请输入一个int类型的数据:";double num;cin >> num;while(!is_int(num)){//如果输入的数据不在int类型的范围内,就重新输入cout << "您输入的数据超出了int类型数据的范围,请重新输入:";cin >> num;}cout << "您输入的int类型数据为 " << (int)num << endl;return 0;
}

结果:

6.3 字符函数库cctype — 头文件#include< cctype>

判断一个字符是否是字母时,常用char ch; if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')),还有一种更简洁的方法:char ch; if(isalpha(ch))
C++从C语言继承了一个与字符相关的、非常方便的函数软件包,它可以简化诸如确定字符是否为大写字母、数字字符、标点符号等工作,这些函数的原型是在头文件#include<cctype >中定义的。

代码示例;

#include<iostream>
#include<cctype>
using namespace std;int main(){//程序清单6.8.cppchar ch;int num_chars = 0;//字母的个数int num_digits = 0;//数字字符的个数int num_whitespace = 0;//空白符的个数 换行符、空格、制表符int num_punct = 0;//标点符号的个数punctuationint num_others = 0;//其他字符类型的个数cout << "请输入一串字符,并以@作为结束符:" << endl;cin.get(ch);while(ch != '@'){if(isalpha(ch))num_chars++;else if(isdigit(ch))num_digits++;else if(isspace(ch))num_whitespace++;else if (ispunct(ch))num_punct++;elsenum_others++;cin.get(ch);}cout << "共有" << num_chars << "个字母," << num_digits << "个数字字符,"<< num_whitespace << "个空白符," << num_punct << "个标点符号," << num_others << "个其他字符。" << endl;return 0;
}

结果:

cctype中的字符函数 --> 编程练习第1题

下表的这些函数的参数和返回值都是int类型
所以如果要将大写字母转成小写字母,输出的时候要记得加个强制类型转换

if(isupper(ch))//如果是大写字母cout << (char)tolower(ch);//加char强制类型转换

6.4 三目运算符(? :)

比较三个数的大小,并输入最大值和最小值:

#include <iostream>using namespace std;int main()
{float a,b,c;float max,min;cout << "请分别输入a、b、c三个数的值:" << endl;cout << "请输入a的值:";cin >> a;cout << "请输入b的值:";cin >> b;cout << "请输入c的值:";cin >> c;max = ((a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c));min = ((a > b) ? ((b > c) ? c : b) : ((a > c) ? c : a));cout << "max = " << max << "\nmin = " << min << endl;}

6.5 switch语句

6.6 break和continue语句

break语句和continue语句都能使程序跳过部分代码

  1. break语句可用在switch语句或循环中,使程序跳到switch或循环后面的语句处执行;
  2. continue语句用于循环中,让程序跳过循环体中余下的代码,并开始新一轮循环。


示例代码:

#include <iostream>
#include<string.h>
using namespace std;
const int size = 80;
int main()
{char line[size] = "abc";int num_space = 0;cout << "请输入一个字符串:" << endl;cin.get(line,80);cout << "完整的字符串是:\n" << line << "\n字符串长度为:" << strlen(line) << endl;cout << "字符串的第一句是:\n";for(int i = 0;i < strlen(line);i++){//line[i] != '\0'cout << line[i];if(line[i] == '.')break;if(line[i] == ' '){num_space++;continue;}    }cout << "\n第一句中共有" << num_space << "个空格。" << endl;return 0;
}

结果:

注意:
使用strlen()必须要包含头文件#include<string.h>#include<cstring>
而头文件#include<string>是string类的头文件:

补充:空间std的使用规则☆☆☆ && 头文件中string与string.h的区别☆☆☆

参考链接:点这里(建议全文背诵,内容我都搬到下面的,有些地方做了些修改,内容的意思没变)

头文件 C语言的标准 C++的标准 备注
iostream #include<iostream.h> #include< iostream>
using namespace std;
两种用法是一样的
math #include<math.h> #include< cmath>
using namespace std;
两种用法是一样的
string(比较特殊) #include<string.h> #include< cstring>
using namespace std;
//string str1;
两种用法是一样的,但这个头文件中没有类的概念,所以不能写string str1;
#include< string>
using namespace std;
string str1;
这个头文件中包含了string类,所以string str1;是合理的

标准的C++头文件没有.h扩展名,将以前的C的头文件转化为C++的头文件后,有时会加上c的前缀表示来自于c,例如#include<cmath>就是由#include<math.h>变来的。

①名称空间std

//using编译指令:
using namespace std; //可以使用std定义的所有类及对象
//using声明:
using std::cout;//只使用cout  这里没有namespace

std::是个名称空间标识符,C++标准库中的函数或者对象都是在名称空间std中定义的,所以要使用标准库中的函数或者对象都要用std来限定

一般来说,std都是在要调用C++标准库时使用。比如;
#include<iostream.h>里面定义的所有类以及对象都是在全局空间里,所以可以直接用cout ;—见程序1
但在#include<iostream>里面,它所定义的东西都在名字空间std里面,所以必须加上 using namespace std;才能使用cout。—见程序2

//程序1:
#include<iostream.h>//此处加上.h
void main()
{ cout << "hello,world." << endl;
} //程序2:
#include<iostream>//此处没有.h
using namespace std; //就需要写上std
void main()
{ cout << "hello,world." << endl;
}

对于大型项目来说,用using namespace std;是一个潜在的问题,所以更好的方法是,只使所需的名称可用,这样既省了内存,又不需要在每次要用的时候都必须加std::前缀。

#include<iostream>
//相当于声明cout、cin、endl,然后就可以使用了,而不需要在每次要用的时候都加std::前缀
using std::cout;
using std::cin;
using std::endl;int main(){cout << "123" << endl;int num;cin >> num;return 0;
}

②string和string.h的区别

一般来说,C语言中一个带“.h”扩展名的库文件,比如iostream.h,在C++的标准库中都有一个不带“.h”扩展名的相对应,区别除了后者改进很多之外,还有一点就是后者很多东西都定义在“std”名字空间中

string比较特殊:当C++要兼容C的标准库时,C的标准库里碰巧也已经有一个名字叫做“string.h”的头文件(包含一些常用的C字符串处理函数,比如strcmp),这个头文件跟C++的string类半点关系也没有,所以并非<string.h>的“升级版本”,它们是毫无关系的两个头文件

#include <string.h>
#include <string>
usingnamespace std; 或者
#include <cstring>
#include <string>
//其中<cstring>是与C标准库的<string.h>相对应,但含有std名字空间的版本

<string.h>是C标准库的头文件,对应的是基于char*的字符串处理函数(包含一些常用的C字符串处理函数,比如strcmp);
< cstring>与C标准库的<string.h>相对应,但含有std名字空间的版本;
< string>是包装了std 的C++头文件,对应的是新的string类

< string>是c++ 的头文件,其内包含了一个string类,string str1;就是建立一个string类的对象str1;
<string.h>是c语言的头文件,C语言中并没有类的概念,所以不能string str1;

③using声明 和 using编译指令 之间有何区别?

using声明使得名称空间中的单个名称可用,其作用域与using所在的声明区域相同;
using编译指令使名称空间中的所有名称可用。使用using编译指令时,就像一个包含using声明和名称空间本身的最小声明区域中声明了这些名称一样。

6.7 读取数字的循环

如果要输入数字,但用户却输入了字符串,怎么办?
用到了cin.clear();

6.8 简单文件输入/输出

C++笔记12:C++中.txt和.csv文件的写入和读取

6.8.1 文本I/O 和 文本文件

6.8.2 写入到文本文件中—ofstream类

iostream类包含istream类和ostream类:

  1. cin是istream类的一个对象,这是有由统预先定义好的;
  2. cout是ostream类的一个对象,也是由系统预先定义好的;
  3. 通过cout可以将信息显示到屏幕上(或者说是输出到屏幕中去),通过cin可以使得用户通过屏幕来把信息读取到系统中(或者说是输入到系统中来)。

同理,fstream类包含ofstream类和ifstream类,是针对文件的输入和输出的类
其中ofstream类是把信息输出到文件中去(或者说是写到文件中去),而ifstream类是把文件中的内容读取到系统中(或者说是输入到系统中来)。

cout头文件iostream预先定义好的一个ostream类对象
同理也创建两个ofstream类的对象outFilefout,然后通过.open()方法把ofstream类对象和文件联系到一起,即打开文件

将内容写入文件:

总之,使用文件输出的主要步骤如下:

  1. 包含头文件fstream; #include< fstream>
  2. 创建一个ofstream对象;ofstream ofs;
  3. 将该ofstream对象同一个文件关联起来;ofs.open("carInfo.txt");
  4. 像使用cout那样使用该ofstream对象,把内容写到文件中;ofs << "我叫丁乐乐";
  5. 用.close()方法将文件关闭。 ofs.close();

示例:
代码:

#include <iostream>
#include<fstream>using namespace std;int main()
{//把内容输出到文件:char automobile[50] = "Flitz Perky";int year = 2009;double a_price = 13500;double b_price = 0.913 * a_price;ofstream ofs;ofs.open("carInfo_6.8.txt");ofs << "车名:" << automobile << endl;ofs << "生产年份:" << year << endl;ofs << "原来的价格:" << a_price << "美元" << endl;ofs << "现在的价格:" << b_price << "美元" << endl;ofs.close();return 0;
}

结果:(在该程序的可执行文件所在的目录下,可以看到一个名为carInfo_6.8.txt的新文件)

ofs.open("123.txt");打开名为123.txt的文件:
如果没有此文件,就创建此文件;
如果有,open()函数默认将原文件中的内容清空,然后写入新的内容。
ofs.close();关闭文件。如果忘记关闭文件,程序正常终止时将自动关闭它。

添加以下代码:

    ofs << fixed;ofs.precision(2);ofs.setf(ios_base::showpoint);

结果:

6.8.3 读取文本文件

  1. 读取文件时,先要断文件是否成功打开,用.is_open()来判断;
  2. 成功打开文件后,在读取文件的过程中,判断是否出现问题,用.good()来判断;
    另外还可以用其他方法判断读取文件的循环中止的具体原因:
    ①用.eof()判断是否到达文件尾;
    ②用.fail()判断是否是读取的内容不匹配。
    .eof(0和.fail()5.5.4 5.5.5 —判断是否到达文件尾EOF出现过)

模板是:

//1.是否成功打开文件?ifstream ifs;ifs.open(filePath);if(ifs.is_open() == false){cout << "文件打开错误!" << endl;return -1;}//2.读取文件内容的大循环是否终止,具体又是因为什么原因终止?ifs >> value;while(ifs.good()){//读取文件内容的大循环//loop body goes here 循环体的内容ifs >> value;}//后面紧跟<判断导致(读取文件的)循环终止de具体原因>的代码:if(ifs.eof())cout << "到达文件尾了!" << endl;else if(ifs.fail())cout << "读取的内容不匹配!!" << endl;elsecout << "读取内容时文件受损或硬件故障!!!" << endl;

这里放一个案例,是读取.txt文件的案例,不同的文件内容,读取的方法也不一样,可以参考C++笔记12:C++中.txt和.csv文件的写入和读取。

案例代码:

#include <iostream>
#include<fstream>using namespace std;const int SIZE = 80;
int main()
{//6.8.3 读取文件的内容:char filePath[SIZE];cout << "请输入文件名:";cin.getline(filePath,80);ifstream ifs;ifs.open(filePath);if(ifs.is_open() == false){cout << "文件打开错误!" << endl;return -1;}double value;double sum = 0.0;int count = 0;ifs >> value;while(ifs.good()){count++;sum += value;ifs >> value;}if(ifs.eof())cout << "到达文件尾了!" << endl;else if(ifs.fail())cout << "读取的内容不匹配!!" << endl;elsecout << "读取内容时文件受损或硬件故障!!!" << endl;cout << "一共有 " << count << "个数,总和sum = " << sum << ";平均数ave = " << sum / count << "." << endl;return 0;
}

结果:
1.文件存在,并且正确地完整地读取了文件的全部内容:

2.文件读取失败,因为文件不存在:

3.文件读取成功,但读到的文件内容不匹配:

补充:如何在Linux中创建一个文档

参考链接:点这里

//三种方法创建文档:cat > scores.txt  //使用Cat命令创建文本文件touch sample.txt  //使用触摸命令创建文本文件> scores.txt       //使用标准重定向符号(>)创建文本文件//创建完成后:ls                //查看是否创建成功nano scores.txt   //编辑文档的内容cat scores.txt     //查看文档的内容

6.9 总结

字符函数库cctype — 头文件#include< cctype>

6.10 复习题

第1题:两个ifif - else if的区别

//第1题:char ch;int space,newline;//版本1:while(cin.get(ch)){if(ch == ' ')space++;if(ch == '\n')newline++;}//版本2:while(cin.get(ch)){if(ch == ' ')space++;else if(ch == '\n')newline++;}

两种分支语句都能够正确统计空格符和换行符的个数。差异在于:
版本1针对所有输入的字符变量ch,都要进行两次判断;
版本2针对所有输入的字符变量ch,都首先判断是否是空格符,然后针对所有非空格符ch再次判断是否是换行符。
从原理上来说,版本2的效率会略高于版本1

第2题:字符变量ch + 1ch++的区别

//第2题:char ch;ch = cin.get();while ((ch != '.')){if(ch == '\n')cout << ch;elsecout << ++ch;//cout << (ch + 1);ch = cin.get();}cout << "___bye!" << endl;

结果:
ch++之后还是字符:

但ch+1之后就成了int型数据:

第3题:

代码:

#include<iostream>using namespace std;int main(){//第3题;char ch;int ct1,ct2;ct1 = ct2 = 0;while((ch = cin.get()) != '$'){cout << ch;ct1++;if(ch = '$')ct2++;cout << ch;}cout << "ct1 = " << ct1 << ",ct2 = " << ct2 << endl;return 0;
}

结果:

第4题:判断字符变量ch是否是字母 isalpha(ch)

6.3 字符函数库cctype

第5题:!!x 和 x 等价吗

xbool变量时,!!x的运算结果等于x
x是其他类型时,x!!x在类型上并不相同,运算符会将x转换成合适的布尔类型之后,再进行逻辑运算;
因此并不能简单认为两次取反(!!)就等于原值。

//第5题:bool x1 = true;int x2 = 0;int x3 = 3;int x4 = -3;cout << "x1 = " << x1 << ", !!x1 = " << !!x1 << endl;cout << "x2 = " << x2 << ", !!x2 = " << !!x2 << endl;cout << "x3 = " << x3 << ", !!x3 = " << !!x3 << endl;cout << "x4 = " << x4 << ", !!x4 = " << !!x4 << endl;

结果:

第8题:把字符char ch;作为 (switch语句的菜单选项和case标签)的优点在哪里?—程序2

程序1:(对字母a和A做同样的处理

//第8题:char str[50] = "aAbBBCCCddddeghijk";int a_num,b_num,c_num,d_num,e_num;a_num = b_num = c_num = d_num = e_num = 0;for(int i = 0;i < strlen(str);i++){switch ((str[i])){case 'a':case 'A':a_num++;break;case 'b':case 'B':b_num++;break;case 'c':case 'C':c_num++;break;case 'd':case 'D':d_num++;break;default:e_num++;break;}}cout << "a_num = " << a_num << "; b_num = " << b_num << ";c_num = " << c_num << "; d_num = " << d_num << ";e_num = " << e_num << endl;

结果:

程序2:

    char ch;   //int ch;//输入整型数据可以正常判断,输入字母或者其他标点符号,程序会崩溃cin >> ch;//空白符会被忽略//ch = cin.get();//空白符也会读入while(ch  != 'q'){switch ((ch)){case 3:cout << "数字3" << endl;break;case '3':cout << "字符3" << endl;break;default:cout << "其他" << endl;break;}cin >> ch;//ch = cin.get();}

结果:
ch = cin.get();作为输入的方式:

cin >> ch;作为输入的方式:

当ch是整型变量时:

解释:
如果ch是int类型,只有当用户输入整型数据(阿拉伯数字0-9组成的整数)的时候,程序可以正常运行;但当用户输入字符(英文字母或者其他字符如标点符号)时,cin >> ch;将会产生读取异常,最终导致程序无法处理switch分支语句而崩溃
如果ch是char类型,所有的键盘输入都会以ASCII字符的形式正确读取,switch分支语句就能正常运行,程序也不会崩溃。

结论:
最好使用字符类型char作为switch语句的菜单选项和case标签,这在一定程度上可以提高程序的健壮性

另外,这里用到的cin >> ch;ch = cin.get();都是每次读取单个字符,区别在于前者会忽略空白符(空格、回车符),后者不会。
(读取单个字符的几种方式第五章的第7、7’、8、9题的汇总)

第9题:while(ch = cin.get() != ‘Q’)语法有问题吗?

//第9题:int line = 0;char ch;
//①// while(cin.get(ch)){//     if(ch == 'Q')//         break;//     if(ch != '\n')//         continue;//     line++;// }
//②// while((cin.get(ch) && ch != 'Q')){//     if(ch == '\n')//         line++;// }
//③    while((ch = cin.get()) != 'Q'){if(ch == '\n')line++;}cout << "line = " << line << endl;

结果:




6.11 编程练习

第1题:大小写字母反转


分析:
cctype的函数的参数和返回值都是int类型,所以要记得加个强制类型转换。

代码:

#include<iostream>
#include<string>
#include<string.h>
#include<fstream>
#include<array>using namespace std;int main(){//第1题:char ch;while((ch = cin.get()) != '@'){if(isupper(ch))//如果是大写字母cout << (char)tolower(ch);else if(islower(ch))cout << (char)toupper(ch);else if (!isdigit(ch))//如果不是数字,就正常输出cout << ch;}return 0;
}

第2题:如何判断输入的数据是不是数字?


原理:直接用(cin >> temp)的返回值来判断是否遇到非数字输入
即如果输入的是数字,就说明读取成功,则返回true;
如果输入的不是数字,就说明读取失败,则返回false,就用break跳出循环,停止输入。

另外,不能用isdigit(temp)来判断是否遇到非数字输入,因为它只能判断是不是数字0-9,是就返回true,不是就返回false。

double temp;
if(!(cin >> temp))//如果输入的数据不是double数字,就会返回falsebreak;

(0303更新)也可以这样写:(源自7.3.3 更多数组函数示例 - 1.填充数组的程序6.7 读取数字的循环 - 程序清单6.14

double temp;
cin >> temp;//读取double型数据的输入
if(!cin)    //这里的cin就包含着(上面的读取是否成功)的结果break;

代码:

#include<iostream>
#include<array>using namespace std;int main(){//第2题:array<double,10> arr;//double arr[10];double temp;int count = 0;//统计用户已共输入多少个数double sum,ave;sum = ave = 0;cout << "请输入10个以内的donation值:" << endl;for(int i = 0;i < 10;i++){cout << "第" << i+1 << "个数:" ;//cin >> temp;if(!(cin >> temp))//如果输入的内容不是数字,即读取失败,就退出循环 //!isdigit(temp)只能判断是不是数字0-9,是就返回true,不是就返回falsebreak;arr[i] = temp;sum += arr[i];count++;}ave = sum / count;cout << "您共输入了 " << count << "个数据,它们的总和sum = " << sum << ";平均值ave = " << ave << "." << endl;int num = 0;//统计有多少个数大于平均值for(int i = 0;i < count;i++){if(arr[i] > ave)num++;}cout << "其中有" << num << "个数字大于平均值。" << endl;return 0;
}

第2’题:测试 char、int、double类型 在什么情况下会输入失败

代码:

//第2'题:    const int size = 10;char type[20] = "int";//   "char"   "double"//char ch[size];//int ch[size] = {0};double ch[size] = {0.0};int count = 0;cout << "请输入" << size << "个以内的" << type << "类型的数据" << endl;for(int i = 0;i < size;i++){cout << "请输入第 " << i+1 << " 个数据:";count++;if(!(cin >> ch[i]))//如果输入失败,就跳出循环break;//count++;}cout << "您一共输入了 " << count << " 个数据,分别是 " <<endl;for(int i = 0;i < count;i++){cout << ch[i] << ",";}cout << endl;

结果:
当ch是char类型时,输够10个字符才会退出循环,因为所有键盘上能输入的都属于char类型;
当ch是int类型时,只能输入由0-9组成的整数才可以,遇到小数点或者字母或者其他字符时就会退出循环;
当ch是double类型时,浮点数都OK,但遇到小数点或者字母或者其他字符时也会退出循环。


第7题:


判断是否单独输入一个字母q:

if(strcmp(words,"q")){//words不是q
}
else{//words是q
}

strcmp(str1,str2)的结果相等则返回0,不相等则返回非0,所以
如果结果为0,就表示words是q;
如果结果为非0,就表示words不是q。

代码:

//第7题:char words[20];int num_vowels,num_consonants,num_others;//以元音字母打头的单词数,以辅音字母打头的单词数,其他num_vowels = num_consonants = num_others = 0;cout << "请输入words,以'q'结束:" << endl;cin >> words;cin.get();while(strcmp(words,"q"))  {if(isalpha(words[0])){if(words[0] == 'a' || words[0] == 'e' || words[0] == 'i' || words[0] == 'o' || words[0] == 'u')num_vowels++;elsenum_consonants++;}elsenum_others++;cin >> words;cin.get();}cout << "以元音字母打头的单词数:" << num_vowels << "\n以辅音字母打头的单词数:" << num_consonants << "\n其他:" << num_others << endl;

第8题:逐字符读取文件并统计字符个数,并解决字符个数总多一个的问题


刚开始写的程序:先创建一个文件并写入内容,然后再读取。

//第8题:char filePath[80] = "no.8_test";//carInfo_6.8.txt scores.txtofstream ofs;ofs.open(filePath);//ofs << 'a' << endl;ofs << "1 2 3";//<< endl;//ofs << "a b c d e" << endl;ofs.close();ifstream ifs;ifs.open(filePath);if(!ifs.is_open()){cout << "文件打开错误!" << endl;return -1;}char ch;int num_ch = 0;while(!ifs.eof()){//未到文件尾就一直循环读取文件的内容ifs.get(ch);//把空白符也读进来了//ifs >> ch;//会忽略空白符cout << ch << '_';//++num_ch;}ifs.close();cout << "\n文件中的字符个数为: " << num_ch << endl;

结果:
如果用ifs.get(ch);读取,会把文件中的空白符也读进来,但会发现最后一个字符会被统计两次,所以总的字符个数多一个;


如果用ifs >> ch;来读取,就会忽略掉文件中的空白符,但统计到的字符数还是多一个,依然是最后一个字符被统计了两次:

改进:
参考链接:解决c++读入文件时多读一个字符
其实 EOF(end of file) 这个文件结束标志是在文件的最后一个字符之后的,当读入最后一个字符的时候其实文件并没有读到 EOF 标志,只有下一次读的时候才会读到 EOF,所以会把 EOF 的值看做一个字符输出,导致多统计了一个字符。
解决办法:

  1. 使用 peek() 函数,该函数获取下个字符的值但不移动文件指针,故可在最后一个字符的时候知道下个字符为 EOF:
  while (in.peek() != EOF){char c = in.get();cout << c;}
  1. 也可以在输出前再判断一步:
while (!in.eof())
{char c = in.get();if (!in.eof())cout << c;
}

因此第8题的最终程序如下:

//第8题:char filePath[80] = "no.8_test";//carInfo_6.8.txt scores.txtofstream ofs;ofs.open(filePath);ofs << 'a' << endl;ofs << "1 2 3" << endl;ofs << "a b c d e" << endl;ofs.close();ifstream ifs;ifs.open(filePath);if(!ifs.is_open()){cout << "文件打开错误!" << endl;return -1;}char ch;int num_ch = 0;while(!ifs.eof()){//未到文件尾就一直循环读取文件的内容ifs.get(ch);//把空白符也读进来了//ifs >> ch;//会忽略空白符if(!ifs.eof()){cout << ch << '_';//++num_ch;}}ifs.close();cout << "\n文件中的字符个数为: " << num_ch << endl;

结果:

第9题:逐行读取文件内容(字符串和数字),数字和字符串的相互转换


分析;
1.new完一定要记得写delete;
2.结构体中的姓名,第6题用的string类,第9题用的char字符串,在读取整行的时候代码分别是getline(cin,str);cin.getline(str,20);
3.读取整行之后,把字符串转换成数字:

//string-->int:
string str;
int num;
num = stoi(str);//string转int
//int-->string:
string str;
str = to_string(num); //已测试,可行√//char字符串-->int:
char str[20];
int num;
num = atoi(str_temp);//char字符串转int
//int-->char字符串:
//char str[80]; str = itoa(n,str2,10); //第一个参数为整数,第二个为字符串(char*),第三个为进制
//这个测试失败,慎用!!!还是用string类的to_string()

这里参考链接:C++ 数字与字符串之间相互转换(多种方法)
4.对于char字符串来说,把一个字符串的内容赋给另一个字符串,需要用strcpy(str2,str1);//char字符串要通过strcpy()来完成字符串复制;
而对于string,就可以直接用str2 = str1;

代码:

#include<iostream>
#include<string>
#include<string.h>
#include<fstream>using namespace std;//第6题+第9题:
struct donationInfo{//string name;//第6题用的string类char name[20];//第9题用的char字符串double money;
};int main(){//第6题:// int num;//捐款者人数// cout << "请输入捐款者人数: ";// cin >> num;// cin.get();//消除结束符// donationInfo* donators = new donationInfo[num];// for(int i = 0;i < num;i++){//     cout << "请输入第 " << i+1 << " 个捐款者的信息:" << endl;//     cout << "姓名: "; //     getline(cin,donators[i].name);//     cout << "捐款额: ";//     cin >> donators[i].money;//     cin.get();//消除结束符// }// cout << "捐款者信息输入完毕!\n" << endl;// int num_temp = 0;// cout << "其中,重要捐款人信息如下:" << endl;// for(int i = 0;i < num;i++){//     if(donators[i].money > 10000){//         num_temp++;//         cout << "姓名:" << donators[i].name << "\t捐款额:" << donators[i].money << endl;//     }// }// if(num_temp == 0)//     cout << "none!" <<endl;// num_temp = 0;// cout << "其他捐款人信息如下:" << endl;// for(int i = 0;i < num;i++){//     if(donators[i].money <= 10000){//         num_temp++;//         cout << "姓名:" << donators[i].name << "\t捐款额:" << donators[i].money << endl;//     }// }// if(num_temp == 0)//     cout << "none!" <<endl;// delete[] donators;//第9题;char filePath[80] = "no.9_test.txt";ifstream ifs;ifs.open(filePath);if(!ifs.is_open()){cout << "文件读取失败!" << endl;return -1;}int num;//string-->int:// string str_temp;// getline(ifs,str_temp);// num = stoi(str_temp);//string转int  //int转string:string str; str = to_string(num); cout << "str = " << str << endl; //已测试,可行√//char字符串-->int:char str_temp[20];ifs.getline(str_temp,20);//读取一整行,不保留结束符。num = atoi(str_temp);//char字符串转int //int转char字符串;char str[80]; str = itoa(n,str2,10); //第一个参数为整数,第二个为字符串(char*),第三个为进制 //测试失败,慎用!还是用string类的to_string()cout << "捐款总人数:" << num << endl;donationInfo* donators = new donationInfo[num];//记得最后要delete[]!!!for(int i = 0;i < num;i++){//读一行姓名:char str_name[20];ifs.getline(str_name,20);strcpy(donators[i].name,str_name);//char字符串要通过strcpy()来完成字符串复制//读一行数字:char str_num[20];ifs.getline(str_num,20);double temp;temp = atoi(str_num);//char字符串转doubledonators[i].money = temp;}//先查看下是否读取成功:// for(int i = 0;i < num;i++){//     cout << "姓名:" << donators[i].name << "捐款额:" << donators[i].money << endl;// }// cout << endl;int num_temp = 0;cout << "其中,重要捐款人信息如下:" << endl;for(int i = 0;i < num;i++){if(donators[i].money > 10000){num_temp++;cout << "姓名:" << donators[i].name << "\t捐款额:" << donators[i].money << endl;}}if(num_temp == 0)cout << "none!" <<endl;num_temp = 0;cout << "其他捐款人信息如下:" << endl;for(int i = 0;i < num;i++){if(donators[i].money <= 10000){num_temp++;cout << "姓名:" << donators[i].name << "\t捐款额:" << donators[i].money << endl;}}if(num_temp == 0)cout << "none!" <<endl;delete[] donators;return 0;
}

结果:

(第六章完)

第七章 函数—C++的编程模块

点这里

C++ Primer Plus(嵌入式公开课)---第5,6章 循环和关系表达式 分支语句和逻辑运算符相关推荐

  1. 【C++ Primer Plus】第5章 循环和关系表达式

    [for循环] for语法: for (initialization; test-expression; update-expression){} 可以在for循环的初始化部分中声明和初始化变量. 在 ...

  2. 【C++ Primer】第五章学习笔记(循环和关系表达式)

    一,for循环       1,在C++中每一个表达式都有值:                int  a=0//声明表达式                23+17   //数学表达式       ...

  3. C++ Primer Plus学习(六)——分支语句和逻辑运算符

    分支语句和逻辑运算符 if语句 逻辑表达式 字符函数库cctype ?: 运算符 switch语句 break和continue语句 读取数字的循环 文件输入\输出 写入到文本文件中 读取文本文件 i ...

  4. 【C++ Primer Plus】第6章 分支语句和逻辑运算符

    6.1 if 语句 if 语法: if (test-condition) statement if 测试条件将被强制转换为bool值,因此0将被转换为false,非零为true. 6.2 if els ...

  5. Coursera公开课笔记: 斯坦福大学机器学习第一课“引言(Introduction)”

    Coursera公开课笔记: 斯坦福大学机器学习第一课"引言(Introduction)" 注:这是我在"我爱公开课"上做的学习笔记,会在52opencours ...

  6. PostgreSQL 免费公开课(第14期)(CUUG)(2020年)

    十四.PostgreSQL 12.2企业级应用系列公开课:调优系列公开课(一) 1.如何获得慢查询的SQL语句 2.常见参数设置因子与应用案例 2.1.shared_buffers 2.2.wal_b ...

  7. 聊天机器人落地及进阶实战 | 公开课速记

    嘉宾 | 邵浩 编辑 | suiling 来源 | AI科技大本营在线公开课 近年来,聊天机器人技术及产品得到了快速的发展.聊天机器人作为人工智能技术的杀手级应用,发展得如火如荼,各种智能硬件层出不穷 ...

  8. 英伟达公开课 | 手把手教你部署一辆高速目标检测Jetbot智能小车

    主讲人 | 何琨 英伟达 量子位编辑 | 公众号 QbitAI 3月26日,英伟达图像处理系列公开课第三期线上开播,来自NVIDIA开发者社区的何琨老师,与数百位开发者共同探讨了: 利用NVIDIA迁 ...

  9. SLAM的前世今生 终于有人说清楚了 | 硬创公开课

    SLAM的前世今生 终于有人说清楚了 | 硬创公开课 今年8月,雷锋网(搜索"雷锋网"公众号关注)将在深圳举办"全球人工智能与机器人创新大会"(GAIR),在本 ...

最新文章

  1. 前端每日实战:100# 视频演示如何用纯 CSS 创作闪闪发光的霓虹灯文字
  2. 又一轮电邮中间人攻击来袭 企业如何自保?
  3. 上传到docker hub_docker 创建image上传到 docker hub并下载
  4. SAP CRM Distribution Chain数据模型
  5. mysql scrapy 重复数据_MySQL大数据量表中删除重复记录
  6. nginx 实现Web应用程序的负载均衡
  7. sql依据单个字段去重_小白学习笔记,测试工程师必备SQL语句整理
  8. 新技术给数据中心带来新风险
  9. Android* 操作系统上的应用程序远程调试
  10. 【机器学习】鸢尾花数据探索
  11. 有限差分法热传导matlab,热传导方程有限差分法的MATLAB实现
  12. VMWareCentOS7硬盘扩容
  13. 如何把wav转换为mp3?
  14. 筑巢引凤 - 男人25后是蓝筹股
  15. nextjs 基于 isomorphic-unfetch 封装自己的请求库
  16. Universal DEP/ASLR bypass with msvcr71.dll and mona.py
  17. TCP的三次握手和四次挥手
  18. 爬取西瓜视频影视分类
  19. 【转载】配置文件 .yml 写法小结
  20. Navicat Premium 使用技巧

热门文章

  1. 分享回合制策略游戏AI算法设计方法
  2. 大根堆、小根堆(数组模拟操作)
  3. Java语言编写计算器
  4. U盘用来安装系统后无法打开
  5. java整型_java中长整型定义
  6. 晨兴刘芹谈创业者这种动物:生来孤独、天道不一定酬勤
  7. ssm毕设项目学生宿舍管理系统15pjb(java+VUE+Mybatis+Maven+Mysql+sprnig)
  8. html之行间样式和外部样式以及内部样式
  9. 正版求生之路联机服务器已满,求生之路2正版怎么联机 正版的联机方法
  10. 【LeetCode】345. Reverse Vowels of a String 解题报告