C++ Primer Plus(嵌入式公开课)---第5,6章 循环和关系表达式 分支语句和逻辑运算符
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
}
- 返回类型不同
前置++的返回类型是左值引用,后置++的返回类型const右值。而左值和右值,决定了前置++和后置++的用法。
问:++a的返回类型为什么是引用呢?
答:为了与内置类型的行为保持一致。前置++返回的总是被自增的对象本身。因此,++(++a)的效果就是a被自增两次。 - 形参的区别
前置++没有形参,而后置++有一个int
形参,但是该形参也没有被用到。很奇怪,难道有什么特殊的用意?
其实也没有特殊的用意,只是为了绕过语法的限制。
前置++与后置++的操作符重载函数,函数原型必须不同,否则就违反了“重载函数必须拥有不同的函数原型”的语法规定。
虽然前置++与后置++的返回类型不同,但是返回类型不属于函数原型。为了绕过语法限制,只好给后置++增加了一个int
形参。
原因就是这么简单,真的没其他特殊用意。其实,给前置++增加形参也可以;增加一个double
形参只要不是int
形参就可以。只是,当时就这么决定了。 - 代码实现的区别
前置++的实现比较简单,自增之后,将*this
返回即可。需要注意的是,一定要返回*this
。
后置++的实现稍微麻烦一些。因为要返回自增之前的对象,所以先将对象拷贝一份,再进行自增,最后返回那个拷贝。 - 效率的区别
如果不需要返回自增之前的值,那么前置++和后置++的计算效果都一样。但是,我们仍然应该优先使用前置++,尤其是对于用户自定义类型的自增操作。
前置++的效率更高,理由是:后置++会生成临时对象。
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();
:
- cin.get();//没有参数
- cin.get(ch);//一个参数char类型
- cin.get(name,20);//两个参数:字符数组名,一次接收的字符数上限(③见第四章的 4.13 编程练习 的 第1题 )
这就是函数重载,函数重载允许创建多个同名函数,条件是他们的参数列表不同。
☆☆☆函数重载的应用:(1和2适合读单个字符,3适合读一整行字符串)
char ch; ch = cin.get();
//没有参数,返回值为输入中的下一个字符char ch; cin.get(ch);
//一个参数char类型,参数是引用类型,直接将读到的字符赋给参数chchar 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+Z
和 Enter
。
示例:
程序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题的汇总☆☆☆
总结:
- 如果读取一个单词
char name[20];
string str;
或一个数字int num;
或一整行string name;
char name[20];
—就看① - 如果读取单个字符
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适合读一整行字符串)
char ch; ch = cin.get();
//没有参数,返回值为输入中的下一个字符char ch; cin.get(ch);
//一个参数char类型,参数是引用类型,直接将读到的字符赋给参数chchar 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语句都能使程序跳过部分代码:
- break语句可用在switch语句或循环中,使程序跳到switch或循环后面的语句处执行;
- 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类:
- cin是istream类的一个对象,这是有由统预先定义好的;
- cout是ostream类的一个对象,也是由系统预先定义好的;
- 通过cout可以将信息显示到屏幕上(或者说是输出到屏幕中去),通过cin可以使得用户通过屏幕来把信息读取到系统中(或者说是输入到系统中来)。
同理,fstream类
包含ofstream类和ifstream类,是针对文件的输入和输出的类,
其中ofstream类是把信息输出到文件中去(或者说是写到文件中去),而ifstream类是把文件中的内容读取到系统中(或者说是输入到系统中来)。
cout
是头文件iostream
预先定义好的一个ostream类
的对象
,
同理也创建两个ofstream类
的对象outFile
和fout
,然后通过.open()
方法把ofstream类对象和文件联系到一起,即打开文件:
将内容写入文件:
总之,使用文件输出的主要步骤如下:
- 包含头文件fstream; #include< fstream>
- 创建一个ofstream对象;
ofstream ofs;
- 将该ofstream对象同一个文件关联起来;
ofs.open("carInfo.txt");
- 像使用cout那样使用该ofstream对象,把内容写到文件中;
ofs << "我叫丁乐乐";
- 用.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 读取文本文件
- 读取文件时,先要断文件是否成功打开,用
.is_open()
来判断; - 成功打开文件后,在读取文件的过程中,判断是否出现问题,用
.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题:两个if
和 if - 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 + 1
和ch++
的区别
//第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 等价吗
当x
是bool
变量时,!!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 的值看做一个字符输出,导致多统计了一个字符。
解决办法:
- 使用
peek()
函数,该函数获取下个字符的值但不移动文件指针,故可在最后一个字符的时候知道下个字符为 EOF:
while (in.peek() != EOF){char c = in.get();cout << c;}
- 也可以在输出前再判断一步:
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章 循环和关系表达式 分支语句和逻辑运算符相关推荐
- 【C++ Primer Plus】第5章 循环和关系表达式
[for循环] for语法: for (initialization; test-expression; update-expression){} 可以在for循环的初始化部分中声明和初始化变量. 在 ...
- 【C++ Primer】第五章学习笔记(循环和关系表达式)
一,for循环 1,在C++中每一个表达式都有值: int a=0//声明表达式 23+17 //数学表达式 ...
- C++ Primer Plus学习(六)——分支语句和逻辑运算符
分支语句和逻辑运算符 if语句 逻辑表达式 字符函数库cctype ?: 运算符 switch语句 break和continue语句 读取数字的循环 文件输入\输出 写入到文本文件中 读取文本文件 i ...
- 【C++ Primer Plus】第6章 分支语句和逻辑运算符
6.1 if 语句 if 语法: if (test-condition) statement if 测试条件将被强制转换为bool值,因此0将被转换为false,非零为true. 6.2 if els ...
- Coursera公开课笔记: 斯坦福大学机器学习第一课“引言(Introduction)”
Coursera公开课笔记: 斯坦福大学机器学习第一课"引言(Introduction)" 注:这是我在"我爱公开课"上做的学习笔记,会在52opencours ...
- PostgreSQL 免费公开课(第14期)(CUUG)(2020年)
十四.PostgreSQL 12.2企业级应用系列公开课:调优系列公开课(一) 1.如何获得慢查询的SQL语句 2.常见参数设置因子与应用案例 2.1.shared_buffers 2.2.wal_b ...
- 聊天机器人落地及进阶实战 | 公开课速记
嘉宾 | 邵浩 编辑 | suiling 来源 | AI科技大本营在线公开课 近年来,聊天机器人技术及产品得到了快速的发展.聊天机器人作为人工智能技术的杀手级应用,发展得如火如荼,各种智能硬件层出不穷 ...
- 英伟达公开课 | 手把手教你部署一辆高速目标检测Jetbot智能小车
主讲人 | 何琨 英伟达 量子位编辑 | 公众号 QbitAI 3月26日,英伟达图像处理系列公开课第三期线上开播,来自NVIDIA开发者社区的何琨老师,与数百位开发者共同探讨了: 利用NVIDIA迁 ...
- SLAM的前世今生 终于有人说清楚了 | 硬创公开课
SLAM的前世今生 终于有人说清楚了 | 硬创公开课 今年8月,雷锋网(搜索"雷锋网"公众号关注)将在深圳举办"全球人工智能与机器人创新大会"(GAIR),在本 ...
最新文章
- 前端每日实战:100# 视频演示如何用纯 CSS 创作闪闪发光的霓虹灯文字
- 又一轮电邮中间人攻击来袭 企业如何自保?
- 上传到docker hub_docker 创建image上传到 docker hub并下载
- SAP CRM Distribution Chain数据模型
- mysql scrapy 重复数据_MySQL大数据量表中删除重复记录
- nginx 实现Web应用程序的负载均衡
- sql依据单个字段去重_小白学习笔记,测试工程师必备SQL语句整理
- 新技术给数据中心带来新风险
- Android* 操作系统上的应用程序远程调试
- 【机器学习】鸢尾花数据探索
- 有限差分法热传导matlab,热传导方程有限差分法的MATLAB实现
- VMWareCentOS7硬盘扩容
- 如何把wav转换为mp3?
- 筑巢引凤 - 男人25后是蓝筹股
- nextjs 基于 isomorphic-unfetch 封装自己的请求库
- Universal DEP/ASLR bypass with msvcr71.dll and mona.py
- TCP的三次握手和四次挥手
- 爬取西瓜视频影视分类
- 【转载】配置文件 .yml 写法小结
- Navicat Premium 使用技巧
热门文章
- 分享回合制策略游戏AI算法设计方法
- 大根堆、小根堆(数组模拟操作)
- Java语言编写计算器
- U盘用来安装系统后无法打开
- java整型_java中长整型定义
- 晨兴刘芹谈创业者这种动物:生来孤独、天道不一定酬勤
- ssm毕设项目学生宿舍管理系统15pjb(java+VUE+Mybatis+Maven+Mysql+sprnig)
- html之行间样式和外部样式以及内部样式
- 正版求生之路联机服务器已满,求生之路2正版怎么联机 正版的联机方法
- 【LeetCode】345. Reverse Vowels of a String 解题报告