03-循环和关系表达式



循环和关系表达式

5.1、for循环

例子

// forloop.cpp -- introducing the for loop
#include <iostream>
int main()
{
    using namespace std;
    int i;  // create a counter
//   initialize; test ; update
    for (i = 0; i < 5; i++)
        cout << "C++ knows loops.\n";
    cout << "C++ knows when to stop.\n";
    // cin.get();
    return 0;
}

提示:

​ C++常用的方式是,在for和括号之间加上一个空格,而省略函数名与括号之间的空格。

关于一些运算符的

// express.cpp -- values of expressions
#include <iostream>
int main()
{
    using namespace std;
    int x;

    cout << "The expression x = 100 has the value ";
    cout << (x = 100) << endl;
    cout << "Now x = " << x << endl;
    cout << "The expression x < 3 has the value ";
    cout << (x < 3) << endl;
    cout << "The expression x > 3 has the value ";
    cout << (x > 3) << endl;
    cout.setf(ios_base::boolalpha);   //a newer C++ feature
    cout << "The expression x < 3 has the value ";
    cout << (x < 3) << endl;
    cout << "The expression x > 3 has the value ";
    cout << (x > 3) << endl;
    /// cin.get();
    return 0; 
}
/*
The expression x = 100 has the value 100
Now x = 100
The expression x < 3 has the value 0
The expression x > 3 has the value 1
The expression x < 3 has the value false
The expression x > 3 has the value true
*/

​ 通常,cout显示bool值之前将它们转换为int,但cout.setf(ios_base:boolalpha)函数调用设置了一个标记,该标记命令cout显示true和false,而不是1和0。

​ C++表达式是值或值与运算符的组合,每个C++表达式都有值。

age=100			//表达式
age=100;		//一条语句
  • 例子1
// formore.cpp -- more looping with for
#include <iostream>
const int ArSize = 16;      // example of external declaration

int main() {
	long long factorials[ArSize];
	factorials[1] = factorials[0] = 1LL;
	for (int i = 2; i < ArSize; i++)
		factorials[i] = i * factorials[i - 1];
	for (int i = 0; i < ArSize; i++)
		std::cout << i << "! = " << factorials[i] << std::endl;
	// std::cin.get();
	return 0;
}
  • 例子2

改步长;使用了using的声明,而不是using编译指令

// bigstep.cpp -- count as directed
#include <iostream>
int main()
{
	using std::cout;    // a using declaration
    using std::cin;
    using std::endl;;
    cout << "Enter an integer: ";
    int by;
    cin >> by;
    cout << "Counting by " << by << "s:\n";
    for (int i = 0; i < 100; i = i + by)
        cout << i << endl;
    // cin.get();
    // cin.get();
    return 0;
}
  • 例子3

依次访问字符串中每个字符的方式

// forstr1.cpp -- using for with a string
#include <iostream>
#include <string>

int main() {
	using namespace std;
	cout << "Enter a word: ";
	string word;
	cin >> word;

	// display letters in reverse order
	for (int i = word.size() - 1; i >= 0; i--)
		cout << word[i];
	cout << "\nBye.\n";
	// cin.get();
	// cin.get();
	return 0;
}
/*
Enter a word: animal
lamina
Bye.
*/
  • 递增/减运算符和指针
double arr[5]={21.1, 32.8, 23.4, 45.2, 37.4};
double *pt=arr;		//pt point arr[0]
++pt;				//pt point arr[1]

double x=*++pt;		//increment pointer,take the value,arr[2]---23.4
++*pt;				//先取值,后将这个值加1.---23.4+1=24.4
(*pt)++;			//先取值,后将这个值加1.---24.4+1=25.4

x=*pt++;			//++运算级高于解除引用运算符,以为着将运算符用于pt,而不是*pt
//*pt++的值为arr[2],为25.4;执行完该语句后,pt的值将为arr[3]的地址

注意:不要在在同一条语句对同一个值递增或递减多次。

注意

​ 指针递增和递减循环指针算术规则。因此,如果pt指向某个数组的第一个元素,++pt将修改pt,使之指向第二个元素。

  • 组合运算符

组合的运算符,如下图所示
在这里插入图片描述

  • 组合语句(语句块)
// block.cpp -- use a block statement
#include <iostream>

int main() {
	using namespace std;
	cout << "The Amazing Accounto will sum and average ";
	cout << "five numbers for you.\n";
	cout << "Please enter five values:\n";
	double number;
	double sum = 0.0;
	for (int i = 1; i <= 5; i++) {
		// block starts here
		cout << "Value " << i << ": ";
		cin >> number;
		sum += number;
	}                                   // block ends here
	cout << "Five exquisite choices indeed! ";
	cout << "They sum to " << sum << endl;
	cout << "and average to " << sum / 5 << ".\n";
	cout << "The Amazing Accounto bids you adieu!\n";
	// cin.get();
	// cin.get();
	return 0;
}

/*
The Amazing Accounto will sum and average five numbers for you.
Please enter five values:
Value 1: 1942
Value 2: 1948
Value 3: 1957
Value 4: 1974
Value 5: 1980
Five exquisite choices indeed! They sum to 9801
and average to 1960.2.
The Amazing Accounto bids you adieu!
*/

如果在语句块中定义新变量,那么新变量的作用范围仅在于语句块内。

运算符

  • 逗号运算符

语句块允许把两条或更多的语句放到一个地方。

逗号运算符对表达式完成同样的任务,允许将两个表达式放到C++语法只允许放一个表达式的地方。

// forstr2.cpp -- reversing an array
#include <iostream>
#include <string>

int main() {
	using namespace std;
	cout << "Enter a word: ";
	string word;
	cin >> word;

	// physically modify string object
	char temp;
	int i, j;
	for (j = 0, i = word.size() - 1; j < i; --i, ++j) {
		// start block
		temp = word[i];
		word[i] = word[j];
		word[j] = temp;
	}                       // end block
	cout << word << "\nDone\n";
	// cin.get();
	// cin.get();
	return 0;
}

/*
Enter a word: qwertyuio
oiuytrewq
Done
*/

逗号运算符的2个特性

首先,它确保先计算第一个表达式,然后计算第二个表达式

i=20,j=2*i;			//i set to 20,then j set to 40

其次,逗号运算符的优先级是最低的

cats=17,240;		//(cats=17),240  cats will set to 17

cats=(17,240);		//cats set to 240, 逗号右侧的表达式值
  • 关系表达式

​ 由于字符用其ASCII码表示,因此也可以将这些运算符用于字符。不能将它们用于C风格字符串,但可用于string类对象。对于所有的关系表达式,如果比较结果为真,则其值为true,否则为false,因此可将其用作循环测试表达式。

在这里插入图片描述

由于关系运算符的优先级比算术运算符

x+3>y-2;
(x+3)>(y-2);		//两者等价
  • 赋值、比较
musican==4;			//比较
musican=4;			//赋值

比较字符串

  • C风格字符串的比较

​ C++将C风格字符串视为地址,因此如果使用关系运算符来比较它们,将无法得到满意的结果。

​ 在C风格字符串是通过结尾的空值字符定义的,而不是由其所在数组的长度定义的。这意味着两个字符串即使被存储在长度不同的数组中,也可能是相同的。

char big[80]="Daffy";
char little[6]="Daffy";

​ 虽然不能用关系运算符来比较字符串,但可以用它们来比较字符,因为字符实际上是整型的。

// compstr1.cpp -- comparing strings using arrays
#include <iostream>
#include <cstring>     // prototype for strcmp()

int main() {
	using namespace std;
	char word[5] = "?ate";

	for (char ch = 'a'; strcmp(word, "mate"); ch++) {
		cout << word << endl;
		word[0] = ch;
	}
	cout << "After loop ends, word is " << word << endl;
	// cin.get();
	return 0;
}
/*
?ate
aate
bate
cate
date
eate
fate
gate
hate
iate
jate
kate
late
After loop ends, word is mate
*/

strcmp(word, “mate”)。如果字符串不相等,则它的值为非零(true);如果字符串相等,则它的值为零(false)。

检测相等或排序

如果str1和str2相等,则下面的表达式为true:

strcmp(str1,str2)==0

如果str1和str2不相等,则下面表达式为true:

strcmp(str1,str2)!=0
strcmp(str1,str2)

如果str1在str2前面,则下面的表达式为true:

strcmp(str1,str2)<0

如果str1在str2后面,则下面的表达式为true:

strcmp(str1,str2)>0
  • 比较string类字符串

int main() {
	using namespace std;
	string word = "?ate";

	for (char ch = 'a'; word != "mate"; ch++) {
		cout << word << endl;
		word[0] = ch;
	}
	cout << "After loop ends, word is " << word << endl;
	// cin.get();
	return 0;
}
/*
?ate
aate
bate
cate
date
eate
fate
gate
hate
iate
jate
kate
late
After loop ends, word is mate
*/

测试条件中用了一个关系运算符,运算符左边是一个string对象,右边是一个C风格字符串

word!="mate";

string类重载运算符!=可以在下述条件下使用:至少有一个操作数为string对象,另一个操作数可以为string对象,也可以是C风格字符串

5.2、while循环

while的示意图

例子

// while.cpp -- introducing the while loop
#include <iostream>
const int ArSize = 20;

int main() {
	using namespace std;
	char name[ArSize];

	cout << "Your first name, please: ";
	cin >> name;
	cout << "Here is your name, verticalized and ASCIIized:\n";
	int i = 0;                  // start at beginning of string
	while (name[i] != '\0') {   // process to end of string   while(name[i])
		cout << name[i] << ": " << int(name[i]) << endl;
		i++;                    // don't forget this step
	}
	// cin.get();
	// cin.get();
	return 0;
}
/*
Your first name, please: Butty
Here is your name, verticalized and ASCIIized:
B: 66
u: 117
t: 116
t: 116
y: 121
*/

for与while

for循环和while循环几乎等效。它们之间存在3个差别

  • 在for循环中省略测试条件,将认为条件为true
  • 在for循环中,可在初始化语句声明一个局部变量,但是while循环中不能这样做
  • 如果循环体中包括continue语句,情况稍微不同

一般来说,使用for循环来计数。在无法知道循环将要执行的次数时,使用while循环

延时

头文件ctime中,定义了一个符号常量——CLOCKS_PER_SEC,该常量等于每秒种包含的系统时间单位数。

ctime将clock_t作为clock()返回类型的别名。

// waiting.cpp -- using clock() in a time-delay loop
#include <iostream>
#include <ctime> // describes clock() function, clock_t type

int main() {
	using namespace std;
	cout << "Enter the delay time, in seconds: ";
	float secs;
	cin >> secs;
	clock_t delay = secs * CLOCKS_PER_SEC;  // convert to clock ticks
	cout << "starting\a\n";
	clock_t start = clock();
	while (clock() - start < delay )        // wait until time elapses
		;                                   // note the semicolon
	cout << "done \a\n";
	// cin.get();
	// cin.get();
	return 0;
}
/*
Enter the delay time, in seconds: 10
starting
done
*/

类型别名

方法1:使用预处理器

#define BYTE char		//编译时用char替换所有的BYTE,从而使BYTE称为char的别名

方法2:使用关键字typedef来创建别名

typedef char byte;	//将byte作为char的别名

//通用格式
typedef typeName aliasName;

typedef char* byte_pointer;		//将byte_pointer声明为char指针

define在声明一系列变量时,不使用

#define FLOAT_POINTER float*
FLOAT_POINTER *pa,pb;		//pa为float型指针,pb just a float

5.3、do while循环

程序流程

例子

// dowhile.cpp -- exit-condition loop
#include <iostream>
int main()
{
    using namespace std;
    int n;

    cout << "Enter numbers in the range 1-10 to find ";
    cout << "my favorite number\n";
    do
    {
        cin >> n;       // execute body
    } while (n != 7);   // then test
    cout << "Yes, 7 is my favorite.\n" ;
    // cin.get();
    // cin.get();
    return 0; 
}

几个循环的对比

int I=0;
for(; ;)
{
	I++;
	//do something
	if(I>=30) break;
	
}
//可以等价于下面的
int I=0;
do{
	I++;
	//do something
}while(I<30);

下面的

int I=0;
for(; ;I++)
{
	if(I>=30) break;
	//do something
}

while(I<30)
{
	//do something
	I++;
}

5.4、基于范围的for循环

类似于迭代器

循环显示

double prices[5]={4.99, 4.32, 1.23, 12.23, 8.49};
for(double x:prices)
	cout<<x<<std::endl;

还可以修改数组的元素

for(double &x:prices)
    x=x*0.80;

还可以使用基于范围的for循环和初始化列表

for(int x:{3,5,2,8,6})
	cout<<x<<" ";
cout<<'\n';

5.5、循环和文本输入

cin对象支持3种不同模式的单字符输入。

例子1

// textin1.cpp -- reading chars with a while loop
#include <iostream>

int main() {
	using namespace std;
	char ch;
	int count = 0;      // use basic input
	cout << "Enter characters; enter # to quit:\n";
	cin >> ch;          // get a character
	while (ch != '#') { // test the character
		cout << ch;     // echo the character
		++count;        // count the character
		cin >> ch;      // get the next character
	}
	cout << endl << count << " characters read\n";
// get rid of rest of line
	// while (cin.get() != '\n')
	// ;
//cin.get();
	return 0;
}

/*
Enter characters; enter # to quit:
seekenrun#
seekenrun
9 characters read
*/

上面的例子。由于cin忽略空格和换行符,因此在输入中的空格没有被回显。

发送给cin的输入被缓冲。意味着只有在用户按下回车健后,他输入的内容才会被发送给程序。按下回车键后,整个字符序列将被发送给程序,但程序在遇到#字符后将结束对输入的处理。

例子2

使用cin.get(ch)

// textin1.cpp -- reading chars with a while loop
#include <iostream>
/*
int main() {
	using namespace std;
	char ch;
	int count = 0;      // use basic input
	cout << "Enter characters; enter # to quit:\n";
	cin >> ch;          // get a character
	while (ch != '#') { // test the character
		cout << ch;     // echo the character
		++count;        // count the character
		cin >> ch;      // get the next character
	}
	cout << endl << count << " characters read\n";
// get rid of rest of line
	// while (cin.get() != '\n')
	// ;
//cin.get();
	return 0;
}
*/

// textin2.cpp -- using cin.get(char)
#include <iostream>

int main() {
	using namespace std;
	char ch;
	int count = 0;

	cout << "Enter characters; enter # to quit:\n";
	cin.get(ch);        // use the cin.get(ch) function
	while (ch != '#') {
		cout << ch;
		++count;
		cin.get(ch);    // use it again
	}
	cout << endl << count << " characters read\n";
// get rid of rest of line
	// while (cin.get() != '\n')
	//    ;
	//cin.get();
	return 0;
}

/*
Enter characters; enter # to quit:
Did you use a#2 pencil
Did you use a
13 characters read
*/

​ 在C语言中,要修改变量的值,必须将变量的地址传递给函数。但程序中调用cin.get()时,传递的是ch,而不是&ch。在C语言中,这样的代码是无效的。

​ 在C++中,iostream将cin.get(ch)的参数声明为引用类型,因此该函数可以修改其参数的值。

cin.get()

char name[Size];
....
cout<<"Enter your name:\n";
cin.get(name,Size).get();

//最后一行相当于两个连续的函数调用
cin.get(name,Size);
cin.get();

cin.get()的一个版本接受两个参数:数组名(字符串(char*类型)的地址)和Size(int类型的整数)

注:数组名是第一个元素的地址,因此字符数组名的类型为char*。

char ch;
cin.get();

这里cin.get接受一个char参数。

在C++中,因为该语言支持函数重载的OOP特性。函数重载允许创建多个同名函数,条件是它们的参数列表不同。

文件尾条件

Windows中有一个名为gofish.exe的可执行程序和一个名为fishtable的文本文件

gofish<fishtable

键盘的模拟EOF

//EOF
<CTRL>+<z>+<ENTER>		[可能有ENTER]

code

#include <iostream>

int main() {
	using namespace std;
	char ch;
	int count = 0;
	cin.get(ch);        // attempt to read a char
	while (cin.fail() == false) { // test for EOF
		cout << ch;     // echo character
		++count;
		cin.get(ch);    // attempt to read another char
	}
	cout << endl << count << " characters read\n";
	return 0;
}
/*
THe green ertyui
THe green ertyui
Yes,but the crow
Yes,but the crow
^Z^Z

34 characters read
*/

cin.clear():清楚EOF标记

CTRL+Z实际上将结束输入和输出,而cin.clear()将无法恢复输入和输出。

常见的字符输入的做法

每次读取一个字符,知道遇到EOF的输入循环

cin.get(ch);        // attempt to read a char
while (cin.fail() == false) { // test for EOF  也可以while(!cin.fail())
		cout << ch;     // echo character
		++count;
		cin.get(ch);    // attempt to read another char
}

get()&put()

iostream

ch=cin.get();

cout.put();

一般情况

char ch;
int count = 0;
cin.get(ch);        // attempt to read a char
while (cin.fail() == false) { // test for EOF
    cout << ch;     // echo character
    ++count;
    cin.get(ch);    // attempt to read another char
}

可以使用int ch,并用cin.get()代替cin.get(char),用cout.put()代替cout,用EOF测试代替cin.fail()测试

int ch;
int count = 0;
ch=cin.get();        
while (ch!=EOF) { // test for EOF
    cout.put(ch);     // echo character
    ++count;
    ch=cin.get();      // attempt to read another char
}

code

// textin4.cpp -- reading chars with cin.get()
#include <iostream>
int main(void)
{
    using namespace std;
    int ch;                         // should be int, not char
    int count = 0;

    while ((ch = cin.get()) != EOF) // test for end-of-file
    {
        cout.put(char(ch));
        ++count;
    }
    cout << endl << count << " characters read\n";
	return 0; 
}

两个函数的对比

image-20230814210007628
//价格输入中的下一个字符读入到ch1中,并将下一个字符符入到ch2
cin.get(ch1).get(ch2);

头文件iostream代替stdio.h

5.6、循环嵌套和二维数组

int maxtemps[4][5]
image-20230815100714642

例子

// nested.cpp -- nested loops and 2-D array
#include <iostream>
const int Cities = 5;
const int Years = 4;

int main() {
	using namespace std;
	const char *cities[Cities] = {  // array of pointers
		// to 5 strings
		"Gribble City",
		"Gribbletown",
		"New Gribble",
		"San Gribble",
		"Gribble Vista"
	};

	int maxtemps[Years][Cities] = { // 2-D array
		{96, 100, 87, 101, 105},   // values for maxtemps[0]
		{96, 98, 91, 107, 104},   // values for maxtemps[1]
		{97, 101, 93, 108, 107}, // values for maxtemps[2]
		{98, 103, 95, 109, 108}   // values for maxtemps[3]
	};

	cout << "Maximum temperatures for 2008 - 2011\n\n";
	for (int city = 0; city < Cities; ++city) {
		cout << cities[city] << ":\t";
		for (int year = 0; year < Years; ++year)
			cout << maxtemps[year][city] << "\t";
		cout << endl;
	}
	// cin.get();
	return 0;
}
/*
Maximum temperatures for 2008 - 2011

Gribble City:   96      96      97      98
Gribbletown:    100     98      101     103
New Gribble:    87      91      93      95
San Gribble:    101     107     108     109
Gribble Vista:  105     104     107     108
*/

几种不同的方法的对比

//方法1:char指针数组
const char *cities[Cities] = {....};

//方法2:char数组的数组
char cities[cities][25]={.....};

//方法3:string对象数组
char string cities[cities]={....};

5.7、总结

如果ch是一个char变量,则下面的语句将输入中的下一个字符读入到ch中

cin>>ch;

然而,它将忽略空格、换行符和指标符。下面的成员函数调用读取输入中的下一个字符。(而不用管该字符是什么),并将其存储到ch中

cin.get(ch);

成员函数调用cin.get()返回下一个输入字符——包括空格、换行符和制表符。

ch=cin.get();

cin.get(char)成员函数调用通过返回转换为false的bool值来指出已达到EOF

而cin.get( )成员函数调用通过返回EOF值来指出已到达EOF

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值