C++语言程序设计(第二单元随堂笔记)
我们一起上清华(doge)
C++语言简单程序设计
导学
C++支持的基本运算
—算数运算
—逻辑运算
##c++中的数据输入/输出可以调用预定义的功能模块实现##
##程序的执行流程不总是顺序的因此程序要能够对
1.执行流程进行选择(选择,开关语句)
2.反复用同一算法依次处理大批量数据(循环语句)
c++字符集和构词法
c++字符集
1、大写的英文字母:AZ,az
2、数字字符:0~9
3、特殊字符
构词法
1、关键字 c++预定义的单词
2、标识符 程序员声明的单词,它命名程序正文中的一些实体
3、文字 在程序中直接使用符号表示的数据
4、分隔符 (){},:; 用于分隔各个词法记号或程序正文
5、运算符(操作符) 用于实现各种运算的符号
6、空白符 空格、制表符(TAB键)、垂直制表符、换行符、回车符和注释的总称
标识符的构成规则
1、以大写字母,小写字母或下划线(_)开始
2、可以由大写字母、小写字母、下划线(_)或数字0~9组成
3、大写字母和小写字母代表不同的标识符
4、不能是c++关键字或操作符
c++语言程序实例
//一个简单的c++程序
#include<iostream>
//是针对命名空间的指令(现在就是知道在#include<iostream>后面加入即可)
using namespace std;
int main() {
//cout是一个输出流对象,它是c++预定义的对象,包含了很多有用的输出功能 输出操作用<<表示,其作用是将<<后面的内容输出在屏幕中
//endl表示的是一个换行符
cout << "hello world" << endl;
cout << "welcome to c++" << endl;
return 0;
}
基本数据类型和表达式
c++能够处理的基本数据类型
1、整数类型
2、实数类型
3、字符类型
4、布尔类型
程序中的数据
常量:
1、在源程序中直接写明的数据
2、其值在整个程序运行期间不可改变
3、整数常量:
1、十进制 \d
2、八进制 \nnn
3、十六进制 \xnnn
浮点数常量:
转义字符常量:
c风格字符串常量:
1、一对双引号括起来的字符序列
2、在内存中按照串中字符的排列次序顺序存放,每一个字符占一个字节(在内存中存储形式是字符的ASCII码依次连续存放)
3、在末尾添加“\0”作为结束标记
#####添加前缀可以改变字符常量或者串常量的类型#####
如下表:
符号常量:
变量:
1、在程序中允许改变的数据
2、可以用地址进行操作
3、可以定义变量名
变量初始化:
int a=0;
int a(0);
int a={0}; //使用大括号的初始化称为列表初始化##(列表初始化的时候不允许信息的丢失。例如用double值初始int时,会造成数据丢失)
int a{0};
变量的储存形式:
register储存形式:存放在通用的寄存器中。
extern储存形式:在所有函数和程序段中都可以引用
static储存形式:在所有函数中都可以引用
thread_load储存类型:具有线程存储生存期。只能修饰命名空间以及块作用域中的变量或者已经被指定为static储存类型的变量。
mutable储存类型:只能用于类数据成员,并且不能于const或者static同时使用,也不能用来修饰引用变量。
常量表达式:
常量表达式是一类不能发送改变的表达式。一个对象或者表达式是否为常量表达式取决于他的类型和初始值
const int max_size = 100; //这个是表达式
const int c = max_size + 1; //这个是常量表达式
const int c = g(x); //这个不是常量表达式
int c = 0; //这个不是常量表达式
但是我们在正常编译过程中无法确定这个是不是常量表达式,于是需要constexpt关键字来判断
例子:
//一个简单的c++程序
#include<iostream>
using namespace std;
constexpr int fad(int x) {
return x;
}
int main() {
constexpr int size =fad(1);
//cout是一个输出流对象,它是c++预定义的对象,包含了很多有用的输出功能 输出操作用<<表示,其作用是将<<后面的内容输出在屏幕中
//endl表示的是一个换行符
cout << size << endl;
cout << "welcome to c++" << endl;
return 0;
}
执行结果:
指针和constexpr
必须明确一点,在constexpr声明中如果定义了一个指针,限定符conxtexpr仅对指针有效,与指针所指的对象无关。
const int*p = nullptr; //p是一个指向整形常量的指针
constexpr int* q = nullptr; //q是一个指向整数的常量指针
注意:constexpr 只能定义编译期常量,而 const 可以定义编译期常量,也可以定义运行期常量。
如下图(就会报错):
整数类型
1、基本的整数类型:int(根据每台机器的不同字节长度不同)
2、按符号分
符号的(signed)
有符号的(unsigned)
3、按照数据范围分
短整数(short)
长整数(long)
长长整数(long long )
字符类型(char)
1、容纳单个字符的编码
2、实质上储存的也是整数
3、每一个字符占一个字节(字符一般用的是ASCII码是七位二进制表示)(而一个字节是八位)
浮点类型
1、单精度(float)
2、双精度(double)
3、扩展精度(long double)
字符串类型
1、有字符串常量
2、基本类型中没有字符串变量
3、采用字符数组储存字符串(c风格的字符串)
4、字符串处理用标准c++雷库中的string类来存放字符串
布尔类型
1、只有两个值:true(真),false(假)
2、常用来表示关系比较、相等比较或逻辑运算的结果
###不同编译器范围不同###
算数运算符
下表显示了 C++ 支持的算术运算符。
假设变量 A 的值为 10,变量 B 的值为 20,则:
运算符 | 描述 | 实例 |
---|---|---|
+ | 把两个操作数相加 | A + B 将得到 30 |
- | 从第一个操作数中减去第二个操作数 | A - B 将得到 -10 |
* | 把两个操作数相乘 | A * B 将得到 200 |
/ | 分子除以分母 | B / A 将得到 2 |
% | 取模运算符,整除后的余数 | B % A 将得到 0 |
++ | 自增运算符,整数值增加 1 | A++ 将得到 11 |
– | 自减运算符,整数值减少 1 | A-- 将得到 9 |
这里举了一个例子:
a+=-=a*a 这个是从左往右进行运算的 a=a+-=a*a ==》a=a+(a=a-a*a)
逗号运算符和逗号表达式
#include<iostream>
using namespace std;
int main() {
int a = 2;
cout << a*a+5 << endl;
a = a*a, a=a + 5;
cout << a << endl;
}
运行结果:
逻辑运算和逻辑运算值
<,<=,>,>=,>,(优先级相同且较高)
==,!=(优先级相同且较低)
用关系运算符将两个表达式连接起来,就是关系表达式,其结果是bool类型,值为true或者false
逻辑表达式返回值也是bool类型,!(非),&&(与),||(或)
注意:&&与||有一种短路的性质:
就是a&&b,a的值为假的话不会判段b,而a||b的话,a的值为真,b不会继续判断直接返回true
条件运算符和条件表达式
表达式1?表达式2:表达式3
其中表达式1必须为bool类型,表达式2,3可以是任何值,也可以没有。
如果表达式1为真的话,则返回2反之为3
#include<iostream>
using namespace std;
int main() {
int a = 1, b = 2;
cout << (a < b) ? a:b;
}
sizeof运算符
sizeof运算符用来计算某种类型的对象在内存中所占的字节数。
sizeof(类型名)
size of 表达式
运算结果值为”类型值“所指的类型或”表达式“的结果类型所占的字节数,注意在这个过程中如果是这样的:
//一个简单的c++程序
#include<iostream>
using namespace std;
int f(int x) {
return 10;
}
int main() {
int a = 1, b = 2;
cout << sizeof f(1);
cout << sizeof(10);
}
输出结果:
位运算
3: 00000011 3: 3: ~ 3
5:(&) 00000101 5:(|) 5:(^)
——————————————————————————————————
3&5 00000001 3|5 00000111 3^5 00000110 ~3 11111100
使用按位与操作可以将操作数中的若干位置0(其他位不变);或者取操作数中的若干指定位。
位移:
char “a”;
a>>2
//一个简单的c++程序
#include<iostream>
using namespace std;
int f(int x) {
return 10;
}
int main() {
char a='a';
cout << a<<2;
//cout << sizeof(10);
}
输出结果:
就是:
11111000
运算后: a>>2;
为11111111000
打印出来就是a2
运算符优先级与结合性
类别 | 运算符 | 结合性 |
---|---|---|
后缀 | () [] -> . ++ - - | 从左到右 |
一元 | + - ! ~ ++ - - (type)* & sizeof | 从右到左 |
乘除 | * / % | 从左到右 |
加减 | + - | 从左到右 |
移位 | << >> | 从左到右 |
关系 | < <= > >= | 从左到右 |
相等 | == != | 从左到右 |
位与 AND | & | 从左到右 |
位异或 XOR | ^ | 从左到右 |
位或 OR | | | 从左到右 |
逻辑与 AND | && | 从左到右 |
逻辑或 OR | || | 从左到右 |
条件 | ?: | 从右到左 |
赋值 | = += -= *= /= %=>>= <<= &= ^= |= | 从右到左 |
逗号 | , | 从左到右 |
混合运算时数据类型的转换
#C++的类型转换分为两种,一种为隐式转换,另一种为显式转换。
#C++中应该尽量不要使用转换,尽量使用显式转换来代替隐式转换。
**定义:**隐式转换是系统跟据程序的需要而自动转换的。
1)C++类型(char,int,float,long,double等)的隐式转换:
算术表达式隐式转换顺序为:
1、char - int - long - double
2、float - double
char(unsigned)short(unsigned)int(unsigned)long(unsigned)long long float double
低————————————————————————————————————————》高
由低精度到高精度的转换是安全的,但是,高精度到低精度的转换是不安全的。
**定义:**显式转换也叫强制转换,是自己主动让这个类型转换成别的类型。
1)C++类型(char,int,float,long,double等)的显式转换:
类型说明符(表达式) //c++风格的显式转换符号
int m = 5;
char c = (char)m;//显式把m转为char类型
double d = 2.0;
int i = 1;
i += static_cast<int>(d);//显式把d转换为int类型
**2)C++类对象的显式转换:**当类构造函数只有一个参数或除了第一个参数外其余参数都有默认值时,则此类有隐含的类型转换操作符(隐式转换),但有时隐式转换并不是我们想要的,可在构造函数前加上关键字explicit,来指定显式调用。
void fun(CTest test);
class CTest
{
public:
explicit CTest(int m = 0);
}
fun(20);//error 隐式转换
fun(static_cast<CTest>(20)); //ok 显式转换
此外:c++还有四种类型转换操作符:
const_cast<类型说明符>(表达式)
dynamic_cast<类型说明符>(表达式)
reinterpret_cast<类型说明符>(表达式)
static_cast<类型说明符>(表达式)
这个后面会详解
数据的输入与输出
I/o流
简单来说就是input和output,cout为output,cin为输入,cout为输出就可以了
但是我们可以考虑一下流这个概念,数据的移动就像流,流在使用前要创建,在程序结束后就要被删除。
这里写一个实例代码:
//一个简单的c++程序
#include<iostream>
using namespace std;
int main() {
int a, b;
cin >> a>> b;
cout << "输出流为:"<< a<<" "<< b;
}
简单的I/O格式控制
##导入iomanip头文件##
常用的I/O流类库操作符
操纵符名 | 含义 |
---|---|
dec | 数值数据采用十进制表示 |
hex | 数值数据采用十六进制表示 |
oct | 数值数据采用八进制表示 |
ws | 提取空白符 |
endl | 插入换行符,并刷新流 |
ends | 插入空字符 |
setsprecision(int) | 设置浮点数的小数位数(包括小数点) |
setw(int) | 设置域宽 |
例子:
//一个简单的c++程序
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
cout << setw(1) << setprecision(5) << 3.1415 << endl;
cout << 3.14159 <<endl;
cout << 3.14159;
}
关于endl的作用:endl可以理解成:在每一次从流中取出数据,并且放在一个地方,这个地方可能能装满。endl就是刷新了这个 地方(缓冲区)(自己理解的如有错误望大佬指正orz)
算法的基本控制结构
if选择结构
输入年份判断是否为闰年:
//一个简单的c++程序
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
int year;
cout << "input year";
cin >> year;
cout << (!(year % 100) && !(year % 400) || (year % 100) && !(year % 4)?"is leap year":"is not leap year");
}
#运行结果:
多重选择结构:
//一个简单的c++程序
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
int x, y;
cout << "请输入x,y";
cin >> x >> y;
cout << (x > y ? "x为较大值" : (x == y ? "x与y相等" : "y为较大值"));
}
switch选择结构
//一个简单的c++程序
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
int day;
cout << "input day";
cin >> day;
switch (day)
{
case 0:
cout << "monday";
break;
case 1:
cout << "tuesday";
break;
case 2:
cout << "wednesday";
break;
case 3:
cout << "thursday";
break;
case 4:
cout << "friday";
break;
case 5:
cout << "saturday";
break;
case 6:
cout << "sunday";
break;
default:
cout << "input error";
break;
}
}
运行结果:
循环结构
例子:求1~10的和
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
int i = 0,sum=0;
while (i <= 10) {
i++;
sum += i;
}
cout<<"sum is " << sum << endl;
}
例子:输入一个整数,将各位数字反转后输出
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
int num,yue;
cout << "input num:";
cin >> num;
cout << "the number in reverse order is:" ;
do {
cout << (~num /10 ? num%10:0 );
num = num / 10;
} while (num/10);
cout << num;
}
代码结果:
for循环:
例子:
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
int sum = 0;
for(int i=0;i<10;i++,sum+=i){}
cout << sum;
}
关于for循环的深入理解:
for(变量初始化;for循环条件;操作){
循环操作;
}
范围for语句:
形式:
for(声明:表达式)
语句
其中表达式表示的必须是一个序列,比如是数组,vector,string等类型的对象。
vector<int> v = {1,2,3};
//一般遍历
for(auto i = v.cbegin(); i != v.cend(); i++)
{
cout << *i << " ";
}
//范围for语句
for(auto i : v)
{
cout << i << " "; //注意:没有*
}
string s = "string";
//一般打印字符串s的每个字母的方法
for(int i = 0; i < s.size(); i++)
{
cout << s[i] << " ";
}
//范围for语句
for(auto c : s)
{
cout << c << " ";
}
例子:输入一个整数求它所有的因子:
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
int i;
cin >> i;
for (int n = i; n != 0;n--) {
if (!(i%n)&&(n!=1&&n!=i)) {
cout <<i<<"的公因数"<< n << "\n";
}
}
}
循环结构与选择结构的嵌套
打印菱形
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
for (int i = 0; i < 7; i++) {
for (int j = 0; j<7; j++) {
cout << (j<6-i? " " : "*");
}
cout << "\n";
}
for (int i = 0; i < 7; i++) {
for (int j = 0; j<7; j++) {
cout << (j<6 - i ? "*" : " ");
}
cout << "\n";
}
}
运行结果:
例:选择1~200里面不能被3整除的数字,能被整除的输出数字,不能被整除的输出0
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
for (int i = 1; i <= 200; cout << ( i% 3 ? 0 : i), i++) { cout << "\n"; }
}
例:统计一系列整数,统计出正整数的个数i和负整数的个数j,读入0代表结束
#include<iostream>
#include<iomanip>
using namespace std;
int main() {
int num;
int i = 0, j = 0;
do {
cout << "请输入数字";
cin >> num;
if (num > 0) {
i++;
}
else {
j++;
}
} while (num);
cout << "正数的个数为" << i << "负数的个数为" << i;
}
运行结果:
其他控制语句
1、break语句
2、continue语句
3、goto语句
类型别名与类型推断
类型别名
一种方法是typeof方法:
typeof 已有类型名 新类型名表;
##新类型名表可以有多个标识符,他们之间用逗号分隔。
如:
typeof double Area,Volume;
typeof int Natural;
Natural A1,A2;
另外,还可以使用别名声明来定义一个类型别名。
using 新类型名=已有类型名;
如:
using my_int=int;
using my_int_i=my_int;
auto类型与decltype类型
auto类型用于定义一个不确定类型的数据:
例如:
#include<iostream>
#include<iomanip>
using namespace std;
int f() {
return 1;
}
int main() {
auto z = f();
decltype(z) j = 2;
}
在这段实例代码中:
z的类型会自动定义为int类型
而decltype的作用是:选择并返回