- 1 计数器控制的循环的要素
- 2 for循环语句
- 应用:计算复利
- 在金融计算中使用double或float类型的特别提醒
- 利用流 *** 纵符格式化数值的输出
- 3 do...while循环语句
- 4 switch多路选择语句
- 读入输入的字符
- 输入EOF指示符
- 在输入中忽略换行符、制表符和空格
- 有关数据类型的说明
- C++11的类内初始化器
- 5 break和continue语句
- break语句
- continue语句
- 6 逻辑运算符
- 逻辑与(&&)运算符
- 逻辑或(||)运算符
- 逻辑非(!)运算符
- 7 运算符优先级总表
- 8 ==运算符和=运算符的混淆问题
- 左值和右值
计数器控制的循环需要:
- 命名一个控制变量(或者循环计数器)
- 设置控制变量(controler)的初值
- 定义一个循环继续条件,用于对控制变量终止的测试(例如,循环是否应该继续)
- 增值(或减值),即在每次循环过程中修改控制变量的值
#include
using namespace std;
int main()
{
unsigned int counter = 1;
while (counter <= 10)
{
cout << counter << " ";
++counter;
}
cout << endl;
}
也可以用下面的写法让代码更简练
#include
using namespace std;
int main()
{
unsigned int counter = 0;
while (++counter <= 10)
cout << counter << " ";
cout << endl;
}
2 for循环语句TIPS:
应使用整数值控制计数器的循环。
自增运算符和自减运算符分别只能和整形 *** 作数一起使用。
通常,for语句用来描述计数器控制的循环,而while语句用于表达标记控制的循环。
如果for语句头部的“初始化”表达式中声明了控制变量,那么该控制变量仅能在for语句的循环体中使用,在此for语句之外它是未知的。
对控制变量名的使用进行的限制称为变量的作用域(scope)。
for循环头部如果要定义多变量,只能定义同种数据类型的变量,否则只能在for循环外定义多于变量,若认为浪费变量名,可以加{}
限制作用域。
正确定义如下:
for (int i=0 , j = 1; i < 9 && j < 10; i++ , j++)
{
//blabla...
}
或
for (int i=0 , j = 1; i < 9 || j < 10; i++ , j++)
{
//blabla...
}
for循环头部的三个表达式可选,但两个分号必需。
将分号直接放置在for语句头部的右括号的右边,这是一个逻辑错误。
控制变量的值可以在for语句循环体内进行改变,但容易导致难以察觉的逻辑错误。
若循环控制变量增值或减值的步长超过1,应尽量避免在循环条件中使用相等运算符(!=
或 ==
)。
#include
#include
#include
using namespace std;
int main()
{
double amount;
double principal = 1000.0;
double rate = .05;
cout << "Year" << setw(21) << "Amount on deposit" << endl;
cout << fixed << setprecision(2);
for (unsigned int year = 1; year <= 10; ++year)
{
amount = principal * pow(1.0 + rate, year);
cout << setw(4) << year << setw(21) << amount << endl;
}
}
函数pow(x,y)
计算x的y次幂的值,它需要接受两个类型为double
的实参,并返回一个double
类型的值。
如果这个程序没有头文件
,那么将无法通过编译。
例子中的变量year
是个整数,这个头文件包含信息,告诉编译器在这个函数调用时,把year的值转换成一个临时的double
值。
这些信息含在pow
函数的函数原型中。
如果忘记包含头文件
,将会产生一个编译错误。
例如,计算机中保存到两笔金额分别为14.234(打印出来是14.23)和18.673(打印出来是18.67),当他们相加时,内部求和的结果是32.907(打印出来是32.91),但是我们自己将打印的数字相加得到的是32.90。
应当注意这个隐患。
在例子中,流 *** 纵符setw(4)
规定了下一个输出值应占用的域宽为4。
也就是说,cout
打印一个值,它至少占用4个字符位置。
如果输出的值小于4个字符位置的宽度,那么在默认情况下,该值的输出在域宽范围内向右对齐;如果输出的值大于4个字符位置的宽度,那么域宽将向右侧扩展到整个值的实际宽度。
为了指出值要向左对齐输出,只需要简单地输出无参数的流 *** 纵符left
(在头文件
中可以找到)即可。
当然向右对齐也可以恢复,只是再输出无参数的流 *** 纵符right
而已。
我们在例子中应用了流 *** 纵符fixed
和setprecision
,这些格式的设置如果不被更改则会一直起作用。
正因如此,称这样的设置为黏性设置(sticky setting)。
可是,指定域宽的setw
只对接下来要输出的值有用。
do…while语句是循环体执行之后再进行循环继续条件的测试,因此循环体总是至少执行一次。
#include
#include
#include
using namespace std;
int main()
{
unsigned int counter = 1;
do
{
cout << counter << " ";
++counter;
} while (counter <= 10);
cout << endl;
}
注意while语句的括号右侧有分号。
使用switch语句优化GradeBook类:
#include
class GradeBook
{
public:
explicit GradeBook(std::string );
void setCourseName(std::string );
std::string getCourseName() const;
void displayMessage() const;
void inputGrades();
void displayGradeReport() const;
private:
std::string courseName;
unsigned int aCount;
unsigned int bCount;
unsigned int cCount;
unsigned int dCount;
unsigned int fCount;
};
#include
#include "GradeBook.h"
using namespace std;
GradeBook::GradeBook(std::string)
: aCount(0), bCount(0), cCount(0), dCount(0), fCount(0);
{
setCourseName(name);
}
// SETTERS
void GradeBook::setCourseName(std::string)
{
if (name.length() <= 25)
courseName = name;
else
{
courseName = name.substr(0, 25);
cerr << "Name \"" << name << "\" exceeds maximum length (25).\n"
<< "Limiting courseName to first 25 characters.\n"
<< endl;
}
}
// GETTERS
string GradeBook::getCourseName() const
{
return courseName;
}
void GradeBook::displayMessage() const {
std::cout << "Welcome to the grade book for\n"
<< getCourseName() << "!\n"
<< std::endl;
}
void GradeBook::inputGrades() {
int grade;
cout << "Enter the letter grades.\n"
<< endl
<< "Enter the EOF character to end input." << endl;
while ((grade = cin.get()) != EOF)
{
switch (grade)
{
case 'A':
case 'a':
++aCount;
break;
case 'B':
case 'b':
++bCount;
break;
case 'C':
case 'c':
++cCount;
break;
case 'D':
case 'd':
++dCount;
break;
case 'F':
case 'f':
++fCount;
break;
case '\n':
case '\t':
case ' ':
break;
default:
cout << "Incorrect letter grade entered. Enter a new grade."
<< endl;
break;
}
}
}
void GradeBook::displayGradeReport() const {
cout << "\n\nNumber of students who received each letter grade:"
<< "\nA: " << aCount << "\nB: " << bCount << "\nC: " << cCount
<< "\nD: " << dCount << "\nF: " << fCount << endl;
}
#include "GradeBook.hpp"
int main()
{
GradeBook myGradeBook("CS101 C++ Programming");
myGradeBook.displayMessage();
myGradeBook.inputGrades();
myGradeBook.displayGradeReport();
}
读入输入的字符
函数cin.get()
从键盘读入一个字符并保存到整型变量grade
中,一般字符存储在char
类型的变量中,它们也可以存储在任何整数数据类型中,因为类型short
、int
、long
和long long
都可以保证不比char
类型小。
所以根据具体用途,即可以把字符当作整数来处理,也可按照字符来对待。
如:
cout << "The character (" << 'a' << ") has the value " << static_cast<int>('a') << endl;
打印字符a和它的整数值,结果如下:
The character (a) has the value 97
一般而言,整个赋值表达式的值正是赋给赋值运算符左边变量。
因此赋值表达式grade=cin.get()
的值等于由cin.get()
返回并赋给变量grade
的值。
a = b = c = 0;
这行代码首先计算赋值表达式c = 0
的值(=
运算符是从右到左结合的)。
然后,赋值表达式c = 0
的值(是0)赋给变量b,接着,赋值表达式b = (c = 0)
的值(也是0)赋值给变量a。
EOF代表“end-of-file”,是用于标记“文件结束”的一个符号。
在程序中我们常使用EOF(一般取值为-1)做标记值,但不可以直接输入-1或者EOF这三个字符作为这个标记值。
准确地说,只能输入一个由具体系统决定的代表“文件结束”的组合键,指示不再有数据需要输入了。
EOF是一个符号整数常量,它通过头文件
包含到程序中。
EOF具有的数据类型是int
。
在OS X/UNIX/Linux系统和很多其他系统中,“文件结束”的输入通过在一行上输入如下的组合键实现:
在Microsoft Windows之类的其他系统下,“文件结束”的输入通过在一行上输入如下的组合键实现:
某些情况下,必须在按了前述组合键后,再按一次回车键。
字符^Z
有时出现在屏幕上,表示文件结束。
在switch
语句中,若在单词case
与被测试的整数值之间遗漏了空格,例如将case 3:
写成了case3:
,那么会引起一个逻辑错误。
case '\n':
case '\t':
case ' ':
break;
为了使程序读入字符,必须通过按回车键,这样会在希望处理的字符之后在输入中多加一个换行符。
上述语句避免了每次输入换行符、制表符和空格时,都有default
子句打印一条错误信息。
每个case
情况只可用于测试整型常量表达式——字符常量和整数常量的任意组合,其计算结果是一个常整数值。
同样,每个case
标签只能指定一个整型常量表达式。
有关数据类型的说明TIPS:
在
switch
语句的case
标签中指定非常量的整型表达式是一个语法错误。
在
switch
语句中,如果提供同样的case
标签,则产生一个编译错误。
C++具有灵活的数据类型长度,每种类型的整数取值的范围由具体平台所决定。
除了int
和char
之外,C++还提供了类型short
、long
和long long
。
对于short
整数而言,它的最小取值范围是-32768 ~ 32767。
对于绝大多数的整数运算来说,long
整数就足够了。
long
整数的最小取值范围是-2147483648 ~ 2147483647。
在大多数计算机中,int
类型要么与short
类型等价,要么与long
类型等价。
各个int
类型的取值范围至少与short
类型相同,最多与long
类型一样。
数据类型char
既可以用来表示计算机字符集中的任何字符,也可以用于表示小整数。
C++11允许程序员在类声明中声明数据成员时,为它们提供默认值。
如:
unsigned int aCount = 0;
unsigned int bCount = 0;
unsigned int cCount = 0;
unsigned int dCount = 0;
unsigned int fCount = 0;
这与之前例子中在类的构造函数中对数据成员初始化不同。
break
语句在while
、for
、do...while
或者switch
语句中执行,立刻使程序退出这些语句。
break
语句的常见用法是要么提前离开循环,要么用于跳过switch
语句的剩余部分。
continue
语句在while
、for
、do...while
或者switch
语句中执行时,是程序跳过循环体内剩下语句,继续进行循环体下一次迭代。
在while
和do...while
语句中,循环继续条件的测试在continue
语句执行之后马上进行。
在for
语句中,则执行增值表达式,然后对循环继续条件进行测试。
在for
循环语句中,当continue
语句执行后,程序控制转到for
头部的控制变量增值部分继续执行。
如果while
语句的增值表达式跟随在continue
语句之后时,该增值表达式在程序测试循环继续条件之前不会执行,很可能导致死循环。
若我们希望在保证两个条件都为true的前提下才能选择某个执行路径,则可以使用&&
运算符。
一个逻辑与表达式的右侧只有在其左侧为true的情况下才会被计算。
逻辑或(||)运算符TIPS:
在数学中的 3
3 < x && x < 7 。
&&
运算符的优先级比||
稍高些。
两个运算符都是从左到右结合的。
与&&
一样,含||
的表达式,其计算在一旦能够确定整个表达式的真假时,就会立即结束。
一元的逻辑非运算符只用一个条件作为 *** 作数,且放在要“逆转”的条件前面。
如:
if(!(grade == sentineValue))
大多数情况下,对于用逻辑非运算符表达的条件,程序员同样可以通过合适的关系运算符或者相等运算符来表达。
例如,上面语句可以写成:
if(grade != sentineValue)
7 运算符优先级总表
在上一章的总表中加入逻辑和逗号运算符。
运算符 | 结合律 | 类型 |
---|---|---|
:: () | 从左向右 | 最高 |
++ -- static_cast<类型>() | 从左向右 | 后缀 |
++ -- + - ! | 从右向左 | 一元(前缀) |
* / % | 从左向右 | 乘 |
+ - | 从左向右 | 加 |
<< >> | 从左向右 | 插入/提取 |
< <= > >= | 从左向右 | 关系 |
== != | 从左向右 | 相等 |
&& | 从左向右 | 逻辑与 |
|| | 从左向右 | 逻辑或 |
?: | 从右向左 | 条件 |
= += -= *= /= %= | 从右向左 | 赋值 |
, | 从左向右 | 逗号 |
在赋值时用==
运算符,在比较时用=
运算符,都属于逻辑错误,这种互换具有破坏性,因为通常不产生语法错误。
左值和右值TIPS:
在书写
x==7
之类的条件时,通常将变量名放左边,常量放右边。
但写成
7==x
这种形式会好些,即将常量放左边,变量名放右边,因为当不小心用=
代替了==
,编译器将起到保护作用。
编译器会认为
7=x
是个编译错误,因为常量值是不可更改的。
变量名称为左值(lvalue),因为可以在赋值运算符左边使用;常量称为右值(rvalue),因为只能在赋值运算符右边使用。
左值可以作右值,但右值绝不能作左值。
如果想用一下一条简单语句为一个变量赋值:
x = 1;
却写成:
x == 1;
这里不是一个语法错误。
编译器只是简单判断这个条件表达式。
表达式的值为true或false,不管怎样,这里没赋值运算符,所以这个值自然丢失了,同时x的值保持不变。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)