I/O
cout保留有效数字问题
C++中cout默认保留六位有效数字,并且进行四舍五入
修改保留数的方法
cout.precision(2); //用这个来改变默认保留几位小数
cout<<"保留两位有效:"<<endl;
cout中可以不写endl,endl属于换行符。
cout字符串输出
对于字符中间可以不使用<< 换行也没有影响 而变量由于变量名不能合并所以要用<<,相当于多个cout叠加
解释 cout<<“hello\nworld”; 或者cout<<“hello\n”“world”;
两种I/O方式
cin>>a; cout<<a;
scanf(“%d%d%d”,&a,&b,&c); printf(“%d”,b);
scanf printf相对于cin cout速度更快,处理数据范围更大,并且更多样化
输出整数
输出时要求为整数,可以使用int输出整形,也可以用double后用%.0lf %.x就是保留小数点后x位
小数
小数要用double(最好不用float)。输入时对于double变量使用lf。输出时float与double都使用f
整形/整形==整形
t=ceil(s/v)+10;//此处如果s与v采用int,则结果为整数
如果t,s改为整数型,则s/t实际上进行的是整除 如 17/8=2;单让s为double也可以,即 17.0/8;
直接输出判断01
printf("%d",(year%4==0&&year%100!=0)||year%400==0);//直接输出判断0,1时不能用cout
输入输出控制符
%x 以16进制读入或输出整形变量
%nd 以n宽度输出整数,不足用空格填充
%0nd 以以n宽度输出整数,不足用0填充
%.nf 输出浮点数,保留小数
%e 以科学计数法形式输出 可以使用%.0e让double类型以整数形式输出科学计数法
%g(%G) 浮点数不显无意义的零"0"
%s 字符串
格式字符串(格式)
〔标志〕〔输出最少宽度〕〔.精度〕〔长度〕类型
“%-md” : 左对齐,若m比实际少时,按实际输出。
“%m.ns” : 输出m位,取字符串(左起)n位,左补空格,当n>m or m省略时m=n
“%m.nf” : 输出浮点数,m为宽度,n为小数点右边数位
“%3.1f” : 输入3852.99 输出3853.0
char
输入字符时,不会跳过空格。可以通过在scanf中添加非控制字符解决
函数使用
自定义函数
某一函数需要调用A函数,则A函数应该写在这个函数前面
如果A调B,B调A,哪个写在前面?:运用声明语句,即不写函数体内容
char
char用来定义字符变量,其关联的还有getchar等
getchar读取缓冲区方法
**在控制台中通过键盘输入数据时,以回车键作为结束标志。当输入结束后,键盘输入的数据连同回车键一起被输入到输入缓冲区中。**在程序中第一次调用getchar()函数从输入缓冲区中读取一个字节的数据。需要注意的是,如果此时在程序中第二次调用getchar()函数,因为此时输入缓冲区中还有回车键的数据没有被读出,第二个getchar()函数读出的是回车符。(/n)
例:输入a然后回车结束,用两次getchar( ),第一次是a,第二次是回车符
cin.get可以获得输入的所有字符,包括空格回车。返回值是int型
int c;
while((c = cin.get())!=EOF){//在while中输入执行语句
cout<<(char) c;
}
//也可以用scanf("%c",%c);
解决方法1
可以使用rewind()函数来清理输入缓冲区中的数据
void rewind( FILE* stream );
//参数stream表示指向FILE结构的指针,即为指定的流。该函数的作用是将文件指针移动到文件的起始位置处。
//getchar是从标准的输入stdin中读取字符,所以用stdin
//学长说一般rewind都是配合stdin使用的,另外几个配合fflush
假设输入是a,回车,b,回车。代码采用getchar,rewind,getchar,rewind可以使读入的两个字符为a,b。
解释:输入a回车,a与回车符会进入缓冲区,getchar读取a后清空缓存区,接着上b回车,读的就是b
其他解决方法
getchar()使用不方便,解决方法:
- 使用下面的语句清除回车: while(getchar()!=‘\n’);
- 用getche()或getch()代替getchar(),其作用是从键盘读入一个字符(不用按回车),注意要包含头文件<conio.h>
getch getche getchar
getchar()
函数名:getchar()
头文件:stdio.h
功 能:从I/O流中读字符
原 型:int getchar(void);
getchar()函数是输入流读入一个字符, 并带回显。它与后面两个函数的区别在于: getchar()函数等待输入直到按回车才结束, 回车前的所有输入字符都会逐个显示在屏幕上。但只有第一个字符作为函数的返回值。getchar不忽略空白符。
getch( )
函数名: getch()
头文件:conio.h
功 能:从控制台读取一个字符,但不显示在屏幕上
原 型:int getch(void)
返回值:读取的字符
getche()
函数名:getche()
头文件:conio.h
功 能:从控制台取字符(带回显)
用 法:int getche(void);
输入带空格的字符串
- cin:当遇到空白字符(空格或者回车键)即停止,并且会把空白字符留在缓冲区,容易造成数据的输入错误。
- cin.get():接收缓冲区的第一个字符,通常用来接收由cin产生的空白字符(比如空格)
- getline(cin,str (string变量名) ):可以输入一行,能接收空格,用string来接收。遇到回车结束输入。
- scanf:%s输入的字符串不能有[空格]或[换行],否则直接结束输入
unsigned long long这个比longlong范围还要大
排序函数sort
sort用于数列排序
sort(a,a+4); 默认升序
次方
pow(a,b);
a的b次方,a为double类型,b为int类型
数组
数组要在main方法外定义,不然可能会出现问题
数组越界
- 可能会引起意外修改其他变量的值,导致程序运算结果不正确
- 可能试图访问不该访问的内存区域,导致程序崩溃
- 数组越界的程序,某些编译器可能会正常运行,有的不能
求数组长度
字符串数组
strlen( )
数字数组
sizeof()函数可以返回数组所占的内存,而sizeof(a[0])返回的是数组第一个元素所占的内存 比如int类型的单个所占内存是4
也就是写成sizeof( ) / sizeof(a[0])
位运算
用于对整数类型(int,char,long等)变量中的某一位(bit),或者若干为进行操作
六种位运算符
& //按位与(双目)
| //按位或(双目)
^ //按位异或(双目)
~ //按位非(取反)(单目)
<< //左移(双目)
>> //右移(双目)
指针
也称为指针变量,大小为4或8个字节,其内容代表一个内存地址
指针的定义 : 类型名 * 指针变量名
理解
int*p = (int *) 40000;//把40000写入p所在的内存空间里面
*p=5000;//往地址40000处起始的若干个字节的内存空间中写入5000
int n = *p;//将地址40000处起始的若干个字节的内容赋值给n
p代表一个数据;而*p则是指向地址p所在的内存空间;
*p赋值给n,相当于是把p所指向的地址的内容赋给n
T*p
p的类型是T*
*p的类型是T
通过*p,可以读写从地址p开始的sizeof( T )
*p等价于存放在地址p处的一个T类型的变量
*是间接引用运算符
sizeof( T* )是4字节(64位计算机上可能是8个字节)
实际用法
让指针指向某一变量的地址:
char ch1 ='A';
char*pc=&ch1;//使pc指向变量ch1
&:取地址运算符
指针的运算
指针的比大小比的是地址,而不是地址里的内容
p1 - p2=(地址p1 - 地址p2) / sizeof(T)代表p1,p2之间能存放多少个T类型的数据
p+n = 地址p + n*sizeof(T) 最后还是一个地址,减法同理
p[ n ]等价于 *(p + n)
空指针
可以用NULL对于任意类型的指针赋值
空指针指向地址0
指针可以作为条件表达式使用,if§等价于if(p!=NULL)
指针与数组
数组的名字是一个指针常量,指向数组的起始位置。可以用名字给相同类型的指针赋值
作为函数形参时,T*p和T P[ ]等价
有意思的事情
各种长度求法统计
字符串长度
str.length( )
str.size( )
字符数组长度
strlen( a )获取实际长度
sizeof( a )获取申明的数组所占的字节
数组长度
sizeof(a)/sizeof(a[0]) 先得出所占字节,再除该类型数组每一单位所占字节
if中进行赋值
a = b = 3;
printf("a = %d, b = %d.\n",a,b);
if (a=4)
printf("a is equal to 4.");
else
printf("a is not equal to 4.");
//(a=4)对于编译器而言,是完全正确的表达。这个表达式除了将4赋值给变量a之外,还会返回整数4作为表达式的值。对于if条件语句,非零即真,因此,(a=4)被视为逻辑真
a++与++a
int x=7,y=8;
int z1=y-(x++);//在x被使用后使其自加1,z1计算出来后x=8
int z2=y-(++x);//在x被使用前使其自加1,z2计算前x先变成9(上一次运算已经使x=8)
++a,在表达式中返回的值是加1后的
a++,在表达式中返回的值是加1前的,即原来的a
cin与scanf不混用,输出也是
溢出
printf("%d",(2147483646+6)/2)//结果溢出,结果错误
printf("%d",2147483646/2+6/2)//结果正常
逻辑表达式是短路计算
如果逻辑符前面已经可以判断出整体的对错,那么后面的表达式就不再进行计算
大小写转换
根据ASCII表 小写字母=大写字母+32,则大写字母=小写字母-32
for括号内不写东西
for括号中三种内容都可以不写,但是;;必须保留
for( ; ; )是死循环,可以用break跳出
scanf有返回值
scanf()返回值为int,表示成功读入的变量个数
EOF
EOF是直接可以用的符号常量,值为-1
常用来做对错判断
无限输入
通过ctrl+z回车解决
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
cout<<n+m;
}
//可以无线输入,回车也不会结束进程。按下ctrl+Z后再按回车才会暂停
通过回车解决
int s[10001];
int i = 0;
while(cin >> s[i]){
i++;
if(cin.get() == '\n'){
break;
}
}
freopen
在主函数开头输入freopen(“c:\\temp\\test.test”,“r”,stdin);
可以程序读取c:\temp\test.test中的数据,不用用键盘敲了(代码中地址要写双斜杠)
定义常量
#define NUM 100(C的用法)
const int MAX_VAL = 23;(C++的用法)
不让double四舍五入
double a=6.6666;
a=(int)(a*100)/100.0;//将6.6666乘100变为666.66然后通过强转int改为666,最后再用100.0转回double
printf("%.2lf",a);
//如果保留三位小数,就把100改为1000
头文件
iostream
iostream(iostream.h)用于输入输出,老版C++需要输入扩展名.h
namespace
using namespace std为名称空间,可以使用多个版本的同一函数
cmath
用于数学计算
int abs(int x) //求整形数绝对值
double cos(double x) //求余弦
double fabs(double x) //求浮点数绝对值
int ceil(double x) //求不小于x的最小值
double sin(doubel x) //求正弦
double sqrt(double x) //求平方根
ctype
用于字符处理
输入参数为int或者char(int和char是兼容的,可以通过ascii码相互转换)
isalnum() // 判断是否为字母或者数字
iscntrl() // 判断是否为控制字符
isgraph() // 判断是否为除空格外的打印字符
islower() // 判断是否为小写字符
isprint() // 判断是否为打印字符
ispunct() // 判断是否为标点符号
isspace() // 判断是否为空格
isupper() // 判断是否为大写字母
isdigit() // 判断是否为数字字符
isxdigit() // 如果参数是十六进制数字,0~9、a~f、A~F,返回true
tolower() // 如果参数是大写字符,返回其小写
toupper() // 如果参数是小写字符,返回其大写
面向对象
引用
类型名 & 引用名 = 某变量名
int n = 4;
int & r = n;//r引用了n,r的类型是int &
某个变量的引用等价于这个变量,相当于这个变量的一个别名
引用只能引用变量,不能引用变量和表达式。一旦初始化后,不能改变引用对象
用法
可以作为函数的输入值void swap(int & a){ }
可以作为函数的返回值int & SetValue( ) { return n; } 返回值是一个int的引用,引用名为n
常引用
const 类型名 & 引用名 = 某变量名
常引用不能被赋值,相当于只能使用被引用变量的值而不能改变它
const T &和T&是不同的类型
T&类型的引用或者T类型的变量可以用来初始化const T &l类型的引用。反之则需要强制转换
const
可以定义常量
可以定义常量指针
不可以通过常量指针修改其指向的内容,常量指针的指向可以改变
不可以把常量指针赋值给非常量指针(除非使用强转,把常量指针转为非常量指针后再赋值),反之可以
函数参数为常量指针时,可避免函数内部不小心修改了参数指针所指地方的内容(防止自己打代码是犯错误)
可以定义常引用
动态内存分配
分配一个变量或分配一个数组
P = new T
T是任意类型名,P是类型为T*的指针
动态分配出一片大小为sizeof (T) 字节的内存空间,并且该内存空间的其实地址赋值给P
释放动态内存
用delete来释放动态分配的内存,删除动态分配的数组,要在delete后面加上[ ]
内联函数
可以减少函数调用的开销,针对于只有几条语句的函数,他们执行的很快,执行很多次。编译器处理内联函数时将整个函数的代码插入到调用语句处,而不会产生调用函数的语句
在函数定义前面加inline就可以定义内联函数
函数重载
跟java一样
类
写法
class CRectangle{
public:
int n;
void Init(int n_){
n = n_;//初始化,类似于this.name=name
}
.....
//属性和函数
};//最后必须有分号
//使用时
CRectangle r;//r是对象
//用法1
r.Init(n);//调用函数
//用法2 指针
CRectangle * p = & r;
p -> Init(5);
//用法3 引用
CRectangle &rr = r;
rr.w=5;
sizeof(CRectangle)的大小就是所有成员变量的大小之和
声明
现在类里声明而不写具体内容
在外面写声明的函数
int CRectangle::Area( ){
......
}
//这样可以表明Area函数是属于CRectangle类的,不是全局函数
类成员可访问范围
private public protected
如果没有写改成员的关键词,缺省的认为他是私有成员
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DFc1zG5A-1666539685467)(C:\Users\zhenghaokun\AppData\Roaming\Typora\typora-user-images\image-20221023203645397.png)]
类中也可以重载
int x;
void value(int val=0){x=val0}//
int value() {return x;}
注意防止二义性
void value(int val=0){x=val;}
int value(){ return x; }
//调用A.value()无法判断是哪一个,因为第一个是缺省参数,不输入也可以