1.for循环——执行特定的次数
①介绍——满足测试条件,执行循环,不满足,跳出循环
#include<iostream>
int main()
{
using namespace std;
for (int i = 5; i ; i--)
cout << "C++ knows loops.\n";
cout << "C++ knows when to stop.\n";
return 0;
}
1.循环执行一次初始化,通常使用表达式将变量设置为起始值;
2.测试表达式可以使用任意表达式,C++将结果强制转换为Bool类型。for循环是入口条件测试,这意味着在每次循环前,都将计算测试表达式的值,当表达式的值为false时,将不会执行循环体。
3.更新表达式:可以是任何有效c++表达式,还可以是其他控制表达式。
注:for语句看上去有些像函数调用,因为他后边跟了一对括号,常用方法是,在for和括号之间加一个括号,而省略函数名与括号之间的空格。
②表达式,语句和非表达式
1.表达式:
任何值或者任何有效的值和运算符的组合都是表达式。例如 10 是 值为10的表达式,28*20是值为560的表达式。 x = 20 是值为20的表达式(C++将赋值表达式的值定义为左侧成员的值);<<运算符的优先级比表达式中使用的运算符高,因此代码要使用括号来获得正确的运算顺序。
#include<iostream>
int main()
{
using namespace std;
int x;
cout << "The expression x=100 has the value "
<< (x = 100) << endl
<< "Now x = 100"<<endl;
x = 100;
cout << "The expression x<3 has the value "
<< (x < 3) << endl
<< "The expression x>3 has the value "
<< (x > 3) << endl;
cout.setf(ios_base::boolalpha); //设置标记,该标记命令cout显示true和false,而不是0和1
cout << "The expression x<3 has the value "
<< (x < 3) << endl
<< "The expression x>3 has the value "
<< (x > 3) << endl;
return 0;
}
2.副作用:
为判定表达式 x =100;C++必须将100赋给x.当判定表达式的值的这种操作改变了内存中的数据时,我们说表达式有副作用。有可能把赋值看做预期效果,有时判定表达式看作预期效果,但从这里来看,判定表达式是主要作用。并不是所有的表达式都有副作用,x+15将计算出新值,但x的值不会改变,++x + 15就有副作用,x加1.
3.语句
任何表达式后加上分号,就是语句,但语句删除分号,不一定是表达式(返回语句声明语句和for语句都不满足删除分号后是个表达式)
C++小规则——可以在for循环的初始化部分中声明变量,循环结束,变量不存在(C现在也可以了)。
③for语句中的常用符号介绍
1.回到for循环
#include<iostream>
int main()
{
const int Size = 16;
long long arr[Size];
arr[0] = 1;
long long res = 1;
for (int i = 1; i < 16; i++)
{
res *= i;
arr[i] = res;
}
for (int i = 0; i < 16; i++)
{
std::cout << i << "! =" << arr[i] << std::endl;
}
return 0;
}
实例提醒,可以使用std::而不是编译指令using来让选定的标准名称可用。
2.修改步长
#include<iostream>
int main()
{
using namespace std;
cout << "Enter an integer:" << endl;
int num = 0;
cin >> num;
cout << "Counting by " << num << "s\n";
for (int i = 0; i < 100; i = i + num)
{
cout << i << endl;
}
return 0;
}
3.使用for循环访问字符串
#include<iostream>
#include<string>
int main()
{
using namespace std;
string str;
getline(cin, str);
for (int i = str.size() - 1; i >= 0; i--) //str.size计算字符串长度
cout << str[i];
cout << "\nBye!";
return 0;
}
4.递增运算符和递减运算符
这两种运算符是处理将值加1和减1在操作的简约、方便的方法。运算符有两种格式,前缀和后缀。
前缀 —— 表达式的值先使用,变量再+1;
后缀 ——? 变量先+1,后使用表达式的值;
如果表达式的值未使用,则这两种从逻辑上来说没有任何区别,但是从执行速度来说,对于C++内置类型,没有区别,对于用户定义的类,前缀将值+1,返回结果,后缀先复制一个副本,将其+1,将复制的副本返回,对于类而言,前缀版本效率更高。
注:对同一条语句中不能对一个值多次进行递增或者递减操作,操作会变得模糊不清。
5.副作用和顺序点
副作用——计算表达式对某些东西(变量的值)进行了修改;
顺序点——程序过程中的一个执行点,再进行下一步之前确保对所有的副作用都进行了评估,分号就是一个顺序点,任何完整的表达式末尾都是一个顺序点。
在C++11中,不再使用术语“顺序点”,使用了术语“顺序”。
6.递增运算符和指针
可以将递增运算符用于指针和基本变量,解引用,递增递减顺序如何,取决于优先级。
后缀递增递减优先级相同,但高于前缀运算符,结合方式从右往左;
前缀递增递减 解引用 优先级相同,从右往左的结合方式。
#include<iostream>
#include<string>
int main()
{
using namespace std;
int arr[5] = { 0,3,5,7,9 };
int* pt = arr;
pt++; //pt指向3
int x = *++pt; //解引用使用前,++pt指向5,解引用x=5;
cout << "x = " << x << endl;
int y = ++*pt; //pt指向5,前缀 y = 6;
cout << "y = " << y << endl;
return 0;
}
7.组合赋值运算符
+=? ? -+? ? *=? ? /=? ? ?%=;
8.复合语句
两个花括号构造一条复合语句(代码块),代码块被认为成一条语句,如果在语块中定义一个新的变量,仅当程序执行该语块中的语句时,该变量才存在,执行完该语句块后,变量被释放,如果语句外和语句内有相同的变量,在语句中,新变量将隐藏旧变量;执行结束后,旧变量再次可见。
9.逗号运算符
语句块允许把两条或更多的语句仿造C++句法中只能放一条语句的地方,逗号运算符对表达式也能完成同样的任务;
for(j= 0,i=word.size()-1;j<i;--i,++j)
逗号不总是运算符,int i,j;逗号将变量列表中相邻的名称分开;
其他说明: 到目前为止,逗号运算符最常见的用途是将两个或更多的表达式放到一个for循环表达式中,这确保了先计算第一个表达式,然后计算第二个(逗号是顺序点);其次,C++中规定,逗号表达式的值是第二部分的值,并且逗号运算符的优先级是最低的。
cast = 17,32; // cast = 17;
cast=(17,32); // cast = 32;
10.关系表达式
<? ? ? ? ? ?<=? ? ? ? ? ? ? ?==(判断相等有两个等号)? ? ? ? ? ? ? ? ? ? ?>? ? ? ? ? ? ? ? ?>=? ? ? ? ? ?!=
④C-风格字符串比较
由于C++将C-风格字符串视为地址,因此如果使用关系运算符来比较它们,将无法得到满意的结果。应使用C-风格字符串库中的strcmp()函数来比较。该函数接受两个字符串地址作为参数,如果两个字符串地址相同返回0,第一个字符串按字母顺序排在第二个字符串之前,返回正数(大小在小写前),排在后边返回负数。
⑤比较string类字符串
类设计可以使用关系符来直接比较。
⑥基于范围的for循环(C++11)
C++11新增了一种循环:基于范围的for循环。这简化了一种常见的循环任务,对数组或(容器类)的每个元素执行相同的操作,如下实例:
#include<iostream>
#include<string>
int main()
{
using namespace std;
double prices[5] = { 4.22,3.56,7.89,8.99,6.56 };
for (double x : prices)
cout << x << endl;
return 0;
}

?
在后边章节详细讨论。?
2.while循环——判断是否达到某个条件(循环)
①介绍
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstring>
int main()
{
using namespace std;
cout << "Your first name,please:";
char name[20];
cin.getline(name, 20);
cout << "Here is your name,verticalized and ASCIIized:\n";
int i = 0;
while (name[i]) //while(name[i]!='\0')
{
cout << name[i] << ": " << (int)name[i] << endl;
i++;
}
return 0;
}
while语句:入口循环条件,首先计算圆括号内的测试条件表达式,如果为true,执行循环体,执行完成后重新返回测试条件,对它进行重新评估,直到测试条件为false,如果测试条件一开始变为false,则程序不会执行循环体。
逐字符遍历字符串直到遇到空值字符的技术时C++处理C-风格字符串的标准方法,由于字符串包含了结尾标记,因此程序通常不需要直到字符串的长度。string对象不使用空字符来标记字符串末尾,16章讨论用于标识string对象中最后一个字符的技术。
②for与while比较
for和while在本质上几乎是等效的,究竟使用哪一个只是风格上的问题。存在三个差别:
1.for循环中省略了测试条件时,将认为条件为true;
2.for循环中,可使用初始化语句声明一个局部变量,while不可以;
3.循环体包含continue语句,情况不同,在第六章介绍。
③编写延时程序
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<ctime>
int main()
{
using namespace std;
cout << "Enter the delay time,in seconds:";
float seconds;
cin>>seconds;
clock_t delay = seconds * CLOCKS_PER_SEC; //头文件ctime提供了统一返回时间和返回类型
cout << "starting\a\n";
clock_t start = clock(); //记录初始值
while (clock() - start < delay)
;
cout << "Done!" << endl;
return 0;
}
程序介绍:
头文件ctime定义了一个符号常量——CLOCKS_PER_SEC,该常量等于每秒钟包含的系统时间单位数,将系统时间除以这个值,就可以得到秒数,或者将秒数乘这个值,就可以得到对应的系统时间。其次,头文件将clock_t作为clock()返回类型的别名,这意味着可以将变量声明为clock_t类型,编译器将会把它转换为long、unsigned int或适合系统的其他类型。
④类型别名
C++为类型建立别名的方式有两种:
1.预处理器??
#define BYTE char //BYTE成为char的别名
2.typedef来创建别名
typedef char BYTE //BYTE为char别名
当声明一系列变量时,预处理器效果没有typedef好:typedef就不会有这样的问题。
#define FLOAT_POINTER float*
FLOAT_POINTER pa,pb; // float* pa,pb, pb错误
3.do while循环——条件为false,循环终止
介绍:出口条件循环,这意味着循环首先执行循环体,然后在判定测试表达式,决定是否应该继续执行循环。通常,入口条件循环比出口条件循环好,因为入口条件循环再循环开始之前对条件进行检查,但有时候do while测试更合理,例如,请求用户输入时,程序必须先获得输入,才能对其进行测试。
#include<iostream>
#include<string>
int main()
{
using namespace std;
int num = 0;
cout << "Enter numbers in the range 1-10 to find my favourite number:\n";
do
{
cin >> num;
} while (num != 7);
cout << "Yes,7 is my favourite .\n";
return 0;
}
4.循环和文本输入
cin对象支持3种不同模式的单字符输入,其用户接口各不相同,下面介绍。
①使用原始的cin进行输入
使用循环读取来自键盘输入,则必须有办法直到何时停止,一种方法是选择某个特殊字符——有时被称为哨兵字符,将其作为停止标记。
#include<iostream>
#include<string>
int main()
{
using namespace std;
int count = 0;
cout << "Enter characters;enter # tp quit:\n";
char ch;
cin >> ch;
while (ch != '#')
{
cout << ch;
count++;
cin >> ch;
}
cout << "\n" << count << " characters read." << endl;
return 0;
}

程序说明:①该程序在循环之前读取第一个字符,这样循环可以测试第一个字符,因为第一个字符可能是#,因为程序采用入口条件循环,因此在这种条件下,能够正确地跳过整个循环。
②程序在输出过程中省略了空格,这是因为cin在读取char值时,与读取其他基本类型一样,cin将忽略空格和换行符。
③只有在用户按下回车键后,他输入的内容才会被发送给程序,这就是在运行该程序时,可以在#后面输入字符的原因。?
②使用cin.get(char)进行补救
1.改进
通常,逐个字符读取输入的程序需要检查每个字符,包括空格、制表符和换行符。
#include<iostream>
#include<string>
int main()
{
using namespace std;
int count = 0;
cout << "Enter characters;enter # tp quit:\n";
char ch;
cin.get(ch);
while (ch != '#')
{
cout << ch;
count++;
cin.get(ch);
}
cout << "\n" << count << " characters read." << endl;
return 0;
}

现在,该程序回显了每一个字符,并将全部字符计算在内,在C语言中,要修改变量的值,必须把变量的地址传递给函数,但是cin.get(ch)并没有传递ch的地址,为什么ch改变了,因为在C++中,只要函数将参数声明为引用即可。在第八章详细介绍。
?2.三个cin.get()函数:
cin.get(字符串地址(名字),要接受的字符个数(整数))
cin.get(ch),第一部分中的函数;
cin.get(),前边章节用于跳过换行键输入。
在C++中,这称为函数重载的oop特性,函数重载允许创建多个同名函数,条件是他们的参数列表不同,第八章讨论。
3.怀旧版cin.get()
C语言中有函数getchar()和putchar(),它们在C++中依然适用,只要像C语言中那样包含头文件cstdio,也可以使用istream和ostream类中类似功能的成员函数。
不接受任何参数的cin.get()成员函数返回输入中的下一个字符,可以这样使用ch = cin.get();
该函数的工作方式与C语言中的getchar()相似,将字符编码作为int值返回;而cin.get(ch)返回一个对象,而不是读取的字符,同样的,可以使用cout.put()函数来显示字符。cout.put(ch).该函数的工作方式类似C语言中的putchar(),只不过其参数类型为char,而不是int.
为了成功使用cin.get(),需要知道其如何处理EOF条件。cin.get测试条件有:
char ch;
ch = cin.get();
while (ch != EOF)
{
cout.put(ch);
ch = cin.get();
}
char ch;
cin.get(ch);
while (cin.fail() == false)
{
cout << ch;
cin.get(ch);
}
注:EOF表示的不是有效字符编码,因此可能不与char类型兼容。例如,在有些系统中,char类型是没有符号的,因此char变量不可能为EOF值(-1).由于这种原因,如果使用cin.get()没有参数并测试EOF,则必须将返回值赋给int变量,而不是char变量。另外,如果将ch类型声明为int,而不是char,则必须在显示ch时将其强制转为char类型。
cin.get(ch)和cin.get()
| 属性 | cin.get(ch) | ch = cin.get() | | 传递输入字符的方式 | 赋值给参数ch | 将函数返回值赋给ch | | 用于字符输入时函数的返回值 | istream对象 | int类型字符编码 | | 到达EOF时函数返回值 | istream对象 | EOF |
③文件尾条件
程序检测到文件结尾后,cin将两位(eofbit failbit)都设置为1.可以通过成员函数eof()来查看eofbit是否被设置,如果检测到EOF后,cin.eof()将返回Bool值true,否则返回false,同样,如果eofbit或failbit被设置为1,则fail()函数返回true,否则返回false.大多数情况选择fail函数来验证,因为可用于更多的实现。
EOF结束输入:对于键盘输入来说,有可能使用模拟EOF来结束循环(ctrl + z +enter),但稍后要读取其他输入,cin.clear()方法可以清除EOF标记,使输入继续进行,在17章纤细介绍。
5.嵌套循环和二维数组
#include<iostream>
#include<string>
int main()
{
using namespace std;
const int city = 5;
const int year = 4;
const char* cities[city] =
{
"Gribble City","Gribbletown","New Gribble","San Gribble","Gribble Vista"
};
int maxtemps[year][city] =
{
{96,100,87,101,105},{96,98,91,107,104},
{97,101,93,108,107},{98,103,95,109,108}
}; //二维数组的初始化
cout << "Maximum temperatures for 2008 - 2011\n";
for (int i = 0; i < city; i++)
{
cout << cities[i]<<":\t"; //\t使用使得程序输出更美观
for (int j = 0; j < year; j++)
cout << " " << maxtemps[j][i] << " ";
cout << endl;
}
return 0;
}
|