【for循环】
for语法:
for (initialization; test-expression; update-expression){}
- 可以在for循环的初始化部分中声明和初始化变量。
- 在for循环中声明的 initialization 变量和for内部变量只存在于for循环过程。
- 可通过修改 **update-expression **修改步长(可以用”,“将两个表达式合并为一个,同时改变两个量)。
- initialization 和 **update-expression **可以省略。但两个分号”;“是必须的。
- C++常用的方式是,在for和括号之间加上一个空格,而省略函数名与括号之间的空格。(if 和 while 也是)
for循环步骤:
- 设置初始值 initialization。
- 每轮循环开始前,执行测试 test-expression(bool类型),决定循环体是否被执行。(for循环是入口条件(entry-condition)循环)
- 执行循环操作。
- 每轮循环结束时,更新用于测试的值 update-expression。
// 使用 for 循环反转字符串
#include <iostream>
#include <cstring>
int main(void)
{
using namespace std;
cout << "Enter a word:";
string word;
cin >> word;
char temp;
int i, j; //代码在循环之前声明i和j,因为不能用逗号运算符将两个声明组合起来。这是因为声明已经将逗号用于其他用途—分隔列表中的变量。
for (j=0, i=word.size()-1; j<i; --i, ++j) // , 列表分隔符
{
temp = word[i]; // temp 循环结束后被丢弃
word[i] = word[j];
word[j] = temp;
}
cout << word << "\nDone\n";
return 0;
}
【基于范围的for循环】
int prices[5] = {
1, 2, 3, 4, 5};
for (int x : prices) // x 最初表示数组的第一个元素
cout << x << endl; // 循环显示数组中的每个值
【C++中的一些基础知识】
i++和++i的区别:
- i++ 返回原来的值,++i 返回加1后的值。
- i++ 不能作为左值,而++i可以。
- i++前者是先赋值,然后再自增;++i后者是先自增,后赋值。
- int i=0; a = i++; //a=0,i=1
bool类型:false and true
- cout在显示bool值之前将它们转换为int:0 and 1
cout.setf(ios::boolalpha);
该标记函数命令cout显示true和false,而不是1和0。- <<运算符的优先级比表达式中使用的运算符高, 因此代码使用括号来获得正确的运算顺序。
bool类型的输出:
//bool类型的输出
#include <iostream>
int main(void)
{
using namespace std;
int x;
// <<运算符的优先级比表达式中使用的运算符高, 因此代码使用括号来获得正确的运算顺序。
cout << " (x=100)=" << (x=100) << endl; //判定赋值表达式会带来副作用, 即修改被赋值者的值。
cout << " (x<3)=" << (x<3) << endl; //cout在显示bool值之前将它们转换为int
cout << " (x>3)=" << (x>3) << endl;
for (int i=0; i<2; i++) //可以在for循环的初始化部分中声明和初始化变量。i只是在for循环中存在
{
int a = 10; //在for循环中声明一个其他的变量,只是在for循环中存在
cout << "i = " << i << endl;
cout.setf(ios_base::boolalpha); //该标记命令cout显示true和false,而不是1和0。
cout << " (x<3)=" << (x<3) << endl;
cout << " (x>3)=" << (x>3) << endl;
}
//cout << "i = " << i << endl; // i 消失,只是在for循环中存在
//cout << "a = " << a << endl; // a 消失,只是在for循环中存在
cout << " (x<3)=" << (x<3) << endl; //false,不知道怎么让cout再显示回int
cout << " (x>3)=" << (x>3) << endl;
return 0;
}
(x=100)=100
(x<3)=0
(x>3)=1
i = 0
(x<3)=false
(x>3)=true
i = 1
(x<3)=false
(x>3)=true
(x<3)=false
(x>3)=true
使用 cout 的三种方法:
- 方法1:
using namespae std;
//using编译指令 - 方法2:
using std::cout;
//using声明 - 方法3:
std::cout << "Enter a number:" << std::endl;
用for循环和数组计算阶乘:
//
// 用for循环和数组计算阶乘: n!=1×2×3×...×(n-1)×n, 0!=1
//
#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;
return 0;
}
//下面是我自己写的,哈哈哈太low了,而且很多地方没有考虑到位
//#include <iostream>
//
//int main(void)
//{
// using namespace std;
//
// int jiecheng=1; //阶乘增加很快,int数值范围太小
// int n;
//
// cout << "Enter a number:";
// cin >> n;
//
// if (n!=0)
// for(int i=1; i<(n+1); i++)
// {
// jiecheng = i * jiecheng;
// }
// cout << n << "!=" << jiecheng << endl;
//
// return 0;
//}
完整表达式:
何为完整表达式呢?它是这样一个表达式: 不是另一个更大表达式的子表达式。
完整表达式的例子: 表达式语句中的表达式部分 以及 用作while循环中检测条件的表达式。
int guests = 9;
while (guests++ < 10)
cout << guests << endl; //output 10,while循环中检测条件是一个完整表达式,所以和10比较之后自加一存储
非完整表达式的例子:y = (4 + x++) + (6 + x++);
中4 + x++
不是一个完整的表达式不保证x的值在计算子表达式4 + x++后立刻增加1。
前缀后缀:
- C++允许您针对类定义这些运算符
- 前缀函数
++i
: 将值加1, 然后返回结果; - 后缀
i++
:首先复制一个副本, 将其加1, 然后将复制的副本返回。 - 因此, 对于类而言, 前缀版本的效率比后缀版本高。
递增递减运算符和指针:
将递增/递减运算符用于指针时, 将把指针的值增加/减少其指向的数据类型占用的字节数.
//
// Created by chaikeya on 2022/8/21.
//递增递减运算符和指针, 前缀和后缀
//
#include <iostream>
int main(void)
{
using namespace std;
double arr[5] = {
21.1, 32.8, 23.4, 45.2, 37.4};
double *pt = arr; // 该语句执行完: pt = &arr[0], *pt = arr[0] = 21.1
++pt; // 该语句执行完: pt = &arr[1], *pt = arr[1] = 32.8
double x = *++pt; // 该语句执行完: pt = &arr[2], *pt = arr[2] = 23.4, x = arr[2] = 23.4
++*pt; // 该语句执行完: pt = &arr[2], *pt = arr[2] = 23.4 + 1 = 24.4
(*pt)++; // 该语句执行完: pt = &arr[2], *pt = arr[2] = 24.4 + 1 = 25.4
x = *pt++; // 该语句执行完: pt = &arr[3], *pt = arr[3] = 25.4, x = arr[2] = 25.4
//后缀运算符意味着将对原来的地址(&arr[2]) 而不是递增后的新地址解除引用, 因此*pt++的值为arr[2],即25.4.
return 0;
}
复合语句(语句块):
- 代码块由一对花括号和它们包含的语句组成, 被视为一条语句.
- 如果在语句块中定义一个新的变量,则仅当程序执行该语句块中的语句时,该变量才存在。执行完该语句块后,变量将被释放。这表明此变量仅在该语句块中才是可用的.
- 如果在一个语句块中声明一个变量,而外部语句块中也有一个这种名称的变量,情况将如何呢?在声明位置到内部语句块结束的范围之内,新变量将隐藏旧变量;然后就变量再次可见.
//
// Created by chaikeya on 2022/8/21.
// 复合语句(语句块)
//
#include <iostream>
int main(void)
{
using namespace std;
int x = 20; // original x
{
// block starts
cout << x << endl; // use original x
int y; // y 只存在于语句块中
y = x++; // 后缀运算符,y = 20, x = 21
int x = 100; // new x = 100
x += 1; // 组合赋值运算符,左=左+右
cout << x << endl; // use new x = 101
} // block ends
cout << x << endl; // use original x = 20
//cout << y << endl; // y 不存在
return 0;
}
运算符:
组合赋值运算符:
+=运算符将两个操作数相加,并将结果赋给左边的操作数。这意味着左边的操作数必须能够被赋值,如变量、数组元素、结构成员或通过对指针解除引用来标识的数据。
逗号运算符:
int cats = 17, 240;
// cats=17, 240不起作用int cats = (17, 240);
// cats=240, 逗号表达式的值是第二部分的值.
关系运算符:>, <, >=, <=, !=, ==,
比较结果为 bool 值,int x = (3>5);
此时x=0,将bool值提升为int。
算术运算符:+, -, *, /,
优先级:(由高到低执行)算术运算符 > 关系运算符 > 逗号运算符
x + 3 > y -2
等价于(x + 3) > (y -2)
C-风格字符串的比较 strcmp():
- strcmp()该函数接受两个字符串地址作为参数(数组名是一个地址,字符串也是一个地址)
- strcmp()如果两个字符串相同,该函数将返回零
- strcmp()如果第一个字符串按字母顺序排在第二个字符串之前(后)返回一个负(正)数
// C-风格字符串的比较 strcmp()
// 该程序显示一个单词,修改其首字母,然后再次显示这个单词,这样循环往复,直到strcmp( )确定该单词与字符串“mate”相同为止。
// strcmp()该函数接受两个字符串地址作为参数(数组名是一个地址,字符串也是一个地址)
// strcmp()如果两个字符串相同,该函数将返回零
// strcmp()如果第一个字符串按字母顺序排在第二个字符串之前(后)返回一个负(正)数
#include <iostream>
#include <cstring> // strcmp()函数的头文件
int main(void)
{
using namespace std;
char word[5] = "?ate"; // strcmp()该函数接受两个字符串地址作为参数(数组名是一个地址,字符串也是一个地址)
for (char ch = 'a'; strcmp(word, "mate"); ch++) // strcmp()如果字符串不相等,则它的值为非零(true);
// strcmp()如果字符串相等,则它的值为零(false)。
{
cout << word << endl;
word[0] = ch;
}
cout << "After loop ends, word is " << word << endl;
cout << strcmp("abc", "ABC") << endl; // return 1 (正数),ASCII表中A在a前
return 0;
}
string 类字符串的比较:关系运算符
// string 类字符串的比较
// 类设计让您能够使用关系运算符进行比较
#include <iostream>
#include <string> // string class
int main(void)
{
using namespace std;
string word = "?ate";
for (char ch = 'a'; word != "mate"; ch++) // 可以将关系运算符用于string对象
{
cout << word << endl;
word[0] = ch;
}
cout << "After loop ends, word is " << word << endl;
return 0;
}
类型别名:
- 预处理器:
#define A B
用 A 替代 B - 关键字typedef:
typedef A B;
用 B 替代 A
【while循环】
while循环是没有初始化和更新部分的for循环,它只有测试条件和循环体:(入口条件(entry-condition)循环)
头文件ctime:
- 首先,定义了一个符号常量—CLOCKS_PER_SEC,该常量等于每秒钟包含的系统时间单位数.
- 因此,将系统时间除以这个值,可以得到秒数。或者将秒数乘以CLOCK_PER_SEC,可以得到以系统时间单位为单位的时间.
- 其次, ctime将clock_t作为clock( )返回类型的别名, 这意味着可以将变量声明为clock_t类型,编译器将把它转换为long、unsigned int或适合系统的其他类型。
用 while 和 clock 编写一个延迟循环:
// 如何使用clock()和头文件ctime来创建延迟循环。
#include <iostream>
#include <ctime> // clock_t 的头文件
int main(void)
{
using namespace std;
cout << "Enter the delay time, in seconds:";
float secs;
cin >> secs;
clock_t delay = secs * CLOCKS_PER_SEC; // 以系统时间单位为单位(而不是以秒为单位) 计算延迟时间
cout << "starting\a\n";
clock_t start = clock();
while (clock() - start < delay); // while 循环体为空语句
cout << "done!\a\n";
return 0;
}
【do while 循环】
- 出口条件(exit condition)循环。
- 首先执行循环体, 然后再判定测试表达式, 决定是否应继续执行循环。
- 如果条件为false, 则循环终止; 否则, 进入新一轮的执行和测试。
- 这样的循环通常至少执行一次,因为其程序流必须经过循环 体后才能到达测试条件。
用法:请求用户输入时, 程序必须先获得输入, 然后对它进行测试 。
【循环和文本输入】
cin对象支持3种不同模式的单字符输入
- cin
cin.get(char);
C语言:要修改变量的值, 必须将变量的地址传递给函数。C++:头文件iostream将cin.get(ch)的参数声明为引用类型, 因此该函数可以修改其参数的值。
函数重载允许创建多个同名函数, 条件是它们的参数列表不同。
数组名是其第一个元素的地址, 因此字符数组名的类型为char*
检测文件尾(EOF)
while (cin.fail() == false){...}
通过键盘来模拟文件尾条件。
在Unix中, 可以在行首按下Ctrl+D来实现; 在Windows命令提示符模式下, 可以在任意位置按Ctrl+Z和Enter。- cin.get()
while (cin.get(ch));
三条指导原则(确定结束条件、 对条件进行初始化以及更新条件) 全部被放在循环测试条件中。
- cin.get(ch) 为判断循环测试条件, 程序必须首先调用cin.get(ch)。如果成功,则将值放入ch中。
- 然后,程序获得函数调用的返回值,即cin。
- 接下来,程序对cin进行bool转换, 如果输入成功, 则结果为true, 否则为false。
while ((ch = cin.get()) != EOF)
- 程序必须首先调用cin.get( )函数, 然后将该函数的返回值赋给ch。
- 由于赋值语句的值为左操作数的值, 因此整个子表达式变为ch的值。
- 如果这个值是EOF, 则循环将结束, 否则继续。
- 该测试条件中所有的括号都是必不可少的。 (因为!=运算符的优先级高于=)
输入/输出
// 方法一:
int ch; // for compatibility with EOF value
ch = cin.get();
while (ch != EOF)
{
cout.put(ch); // cout.put(char(ch)) for some implementations
ch = cin.get();
}
// 方法二:
char ch;
cin.get(ch); // cin.get(ch)返回一个对象, 而不是读取的字符
while (cin.fail() == false) // test for EOF
{
cout << ch;
cin.get(ch);
}
【嵌套循环和二维数组 】
二维数组:int maxtemps[4][5];
假设要打印数组所有的内容, 可以用一个for循环来改变行, 用另一个被嵌套的for循环来改变列:
for (int row = 0; row < 4; row++)
{
for (int col = 0; col < 5; ++col)
cout << maxtemps[row][col] << "\t";
cout << endl;
}
将一个指针数组初始化为一组字符串常量:
也就是说,将cities声明为一个char指针数组。这使得每个元素(如cities[0])都是一个char指针,可被初始化为一个字符串的地址。程序将cities [0]初始化为字符串“Gribble City”的地址.
指针数组 = char数组的数组 = string对象数组
- 指针数组:char * cities[5]
- char数组的数组:char cities[5][25]
- string对象数组:char string cities[5]
// 初始化了一个二维数组, 并使用了一个嵌套循环
// 将一个指针数组初始化为一组字符串常量。
// 也就是说,将cities声明为一个char指针数组。这使得每个元素(如cities[0])都是一个char指针,可被初始化为一个字符串的地址。
// 程序将cities [0]初始化为字符串“Gribble City”的地址
#include <iostream>
const int Cities = 5;
const int Years = 4;
int main()
{
using namespace std;
// 可以试用使用char数组的数组 char cities[Cities][25]
// 还可以使用string对象数组 string cities[Cities]
const char * cities[Cities] = // 将cities声明为一个char指针数组
{
// to 5 strings
"Gribble City", // cities[0]初始化为字符串“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;
}
【总结】
- C++提供了3种循环: for循环、 while循环和do while循环。 如果循环测试条件为true或非零, 则循环将重复执行一组指令; 如果测试条件为false或0, 则结束循环。 for循环和while循环都是入口条件循环, 这意味着程序将在执行循环体中的语句之前检查测试条件。 do while循环是出口条件循环, 这意味着其将在执行循环体中的语句之后检查条件。
- 每种循环的句法都要求循环体由一条语句组成。 然而, 这条语句可以是复合语句, 也可以是语句块(由花括号括起的多条语句) 。
- 关系表达式对两个值进行比较, 常被用作循环测试条件。 关系表达式是通过使用6种关系运算符之一构成的: <、 <=、 = =、 >=、 >或! =。关系表达式的结果为bool类型, 值为true或false。
- 许多程序都逐字节地读取文本输入或文本文件, istream类提供了多种可完成这种工作的方法。
- 如果ch是一个char变量, 则下面的语句将输入中的下一个字符读入到ch中:
cin >> ch;
它将忽略空格、 换行符和制表符。 - 下面的成员函数调用读取输入中的下一个字符(而不管该字符是什么) 并将其存储到ch中:
cin.get(ch);
成员函数调用cin.get( )
返回下一个输入字符—包括空格、 换行符和制表符, 因此, 可以这样使用它:ch = cin.get();
cin.get(char)
成员函数调用通过返回转换为false的bool值来指出已到达EOF, 而cin.get( )
成员函数调用则通过返回EOF值来指出已到达EOF, EOF是在文件iostream中定义的。- 嵌套循环是循环中的循环, 适合用于处理二维数组。
【编程练习】
// 5.9.2
// 使用array对象(而不是数组)和long double(而不是long long)重新编写程序清单5.4,并计算100!的值。
#include <iostream>
#include <array>
using namespace std;
const int ArSize = 100; // example of external declaration
int main()
{
array<long double, ArSize> factorials;
factorials[1] = factorials[0] = 1LL; //连续赋值,从右到左
for (int i = 2; i < ArSize; i++)
factorials[i] = i * factorials[i-1];
cout << ArSize << "! = " << factorials[99] << endl;
return 0;
}
// 5.9.4
// Daphne 利息 = 0.10×原始存款
// Cleo 利息 = 0.05×当前存款
// 计算多少年后, Cleo的投资价值才能超过Daphne的投资价值, 并显示此时两个人的投资价值。
#include <iostream>
int main(void)
{
using namespace std;
double Daphne_account=100;
double Cleo_account=100;
int years=0;
while (Daphne_account >= Cleo_account)
{
years++;
Daphne_account+=10;
Cleo_account=Cleo_account*1.05;
}
cout << "After " << years << " years " << "Cleo is richer than Daphne " << endl;
cout << "Cleo_account = " << Cleo_account << endl;
cout << "Daphne_account = " << Daphne_account << endl;
return 0;
}
// 5.9.7
// 设计一个名为car的结构, 用它存储下述有关汽车的信息: 生产商(存储在字符数组或string对象中的字符串) 、 生产年份(整数) 。
// 编写一个程序,向用户询问有多少辆汽车。随后,程序使用new来创建一个由相应数量的car结构组成的动态数组。
// 接下来, 程序提示用户输入每辆车的生产商(可能由多个单词组成) 和年份信息。
// 请注意, 这需要特别小心, 因为它将交替读取数值和字符串(参见第4章) 。
// 最后,程序将显示每个结构的内容。
#include <iostream>
#include <cstring>
using namespace std;
struct car
{
std::string make;
int year;
};
int main(void)
{
int n;
cout << "How many:";
cin >> n;
car *pt = new car[n];
for (int i=0; i < n; ++i)
{
cout << "Car #" << i+1 << ":" << endl;
cout << "Place enter the make:";
cin >> pt[i].make;
cout <<"please enter the year make: ";
cin>>pt[i].year;
}
cout<<" Here is your collection: "<<endl;
for (int i = 0; i < n; i++)
{
cout << pt[i].make<<" "<<pt[i].year<<endl;
}
delete [] pt;
}
// 5.9.8
// 编写一个程序, 它使用一个char数组和循环来每次读取一个单词,直到用户输入done为止。
// 随后,该程序指出用户输入了多少个单词(不包括done在内) 。
// 用string类的方法实现
#include <iostream>
#include <cstring>
int main(void)
{
using namespace std;
int num_word=0;
char letter[128]; //string letter;
cout<<"Enter words (type done to stop)"<<endl;
while (cin >> letter)
{
if (!(strcmp(letter, "done"))) //if (letter == "done")
{
break;
}
num_word++;
}
cout<<"You enter a total of "<<num_word<<" words."<<endl;
return 0;
}