头文件简介
头文件是一种包含功能函数、数据接口声明的载体文件,主要用于保存程序的声明,而定义文件用于保存程序的实现。头文件的使用允许程序员在多个源文件中共享函数和数据类型的声明,从而提高了代码的可重用性和模块化。这种分离使得代码更易于维护和理解,同时也便于管理大型项目中的复杂依赖关系。
我们引用某一个头文件,往往是为了调用其抽象出来的基础方法,比如下面这样一段程序,如果不引用“iostream”(注释掉这一行),此时“cout”命令无法被调用,编译的时候会收到一个错误提示:std::cout' is defined in header <iostream>; did you forget to '#include <iostream>
。简单来说,想使用哪个功能,就预先引入哪个头文件(如果有对应功能的头文件的话)。
#include <iostream>
using namespace std;
int main(){
cout << "Hello World!" << endl;
}
万能头文件
C++的万能头文件是,它是一个包含了每一个标准库的头文件:
include <bits/stdc++.h>
优点:在算法竞赛中节约时间;减少了编写所有必要头文件的工作量。
缺点:不是GNU C++库的标准头文件,在部分情况下会编译失败;包含了很多不必要的东西,会大大增加编译时间。
常用的头文件
iostream
C++ 标准库中用于输入输出操作的头文件,有时候我们也会在程序中看到<cstdio>
这个头文件,该文件用于C语言风格的输入输出,既然是面向 C++ 的竞赛,可以优先选择使用<iostream>
。
sstream
sstream 是 C++ 标准库中的一个组件,它提供了一种方便的方式来处理字符串流(可以像处理流一样处理字符串)。<sstream>
允许你将字符串当作输入/输出流来使用,这使得从字符串中读取数据或将数据写入字符串变得非常简单,其中:
istringstream:用于从字符串中读取数据。
/*从字符串读数据*/
#include<iostream>
#include<sstream>
using namespace std;
int main(){
string data="10 20.5";
istringstream iss(data);
int i;
float d;
iss >> i >> d;
cout << i << d;
}
ostringstream:用于将数据写入字符串。
/*向字符串写入数据*/
#include<iostream>
#include<sstream>
using namespace std;
int main(){
ostringstream oss;
int i=100;
float d=200.5;
oss << i << " " << d;
string result=oss.str();
cout << result;
}
stringstream:是istringstream和ostringstream的组合,可以同时进行读取和写入操作。
#include<iostream>
#include<sstream> //字符流
using namespace std;
int main(){
int a;
char b,c;
string result1,result2;
stringstream ss; //定义流
ss << 1 ; //输入流
ss << 2 << 3; // 输入流
ss << 'a' ; //支持字符
ss << "hello" ; //也支持字符串
ss >> a >> b >> c; //按变量属性赋值
cout << "int: " << a << endl;
cout << "char: " << b << endl;
cout << "char: " << c << endl;
ss >> result1; //数据提取时有断点,每提取一次断点后延
ss >> result2; //断点已达末尾无数据
cout << "r1: " << result1 << endl;
cout << "r2: " << result2 << endl; //result2此时为空
result1 = ss.str(); //虽然断点已到达数据末尾,但流中数据仍然存在
result2 = ss.str(); //并可整体重复提取
cout << "r1: " << result1 << endl;
cout << "r2: " << result2 << endl;
cout<< "-----------------------" << endl;
ss.str(""); //清空流数据
ss.clear(); //清理断点,否则无法正确输入输出
ss << 6543 << "string";
ss >> a;
cout << a << " ";
result1=ss.str();
cout << result1;
}
iomanip
是 C++ 标准库中的一个头文件,它提供了对输入/输出流的格式化操作。iomanip 库中的函数允许开发者控制输出格式,如设置小数点后的位数、设置宽度、对齐方式等。iomanip 是 Input/Output Manipulators 的缩写,它提供了一组操作符,用于控制 C++ 标准库中的输入/输出流的格式,该库常与<iostream>配合使用。
cstdio
cstdio是将stdio.h的内容用C++头文件的形式表示出来。stdio.h是C标准函数库中的头文件,即:standard buffered input&output。提供基本的文字的输入输出流操作(包括屏幕和文件等)。由于C语言并没有提供专用于文字输入输出的关键字,所以该库是最普遍的C语言程序加载库。在c++环境中,一般会优先选择使用cstdio(cstdio与stdio.h两者之间选择的话)。
string
关于查找字符串,查找字符串a是否包含子串b,不是用 strA.find(strB) > 0
而是 strA.find(strB) != string:npos
这是为什么呢?(初学者比较容易犯的一个错误)
int idx = str.find("abc");
if (idx == string::npos);
上述代码中,idx的类型被定义为int,这是错误的,即使定义为 unsigned int 也是错的,它必须定义为 string::size_type。npos 是这样定义的: static const size_type npos = -1; 因为 string::size_type (由字符串配置器 allocator 定义) 描述的是 size,故需为无符号整数型别。因为缺省配置器以型别 size_t 作为 size_type,于是 -1 被转换为无符号整数型别,npos 也就成了该型别的最大无符号值。不过实际数值还是取决于型别 size_type 的实际定义。不幸的是这些最大值都不相同。事实上,(unsigned long)-1 和 (unsigned short)-1 不同(前提是两者型别大小不同)。因此,比较式 idx == string::npos 中,如果 idx 的值为-1,由于 idx 和字符串string::npos 型别不同,比较结果可能得到 false。因此要想判断 find()等查找函数的结果是否为npos,最好的办法是直接比较。
常用查找指令:
size_type find( const basic_string &str, size_type index );
//返回str在字符串中第一次出现的位置(从index开始查找),如果没找到则返回string::npos
size_type find( const char *str, size_type index );
//返回str在字符串中第一次出现的位置(从index开始查找),如果没找到则返回string::npos
size_type find( const char *str, size_type index, size_type length );
//返回str在字符串中第一次出现的位置(从index开始查找,长度为length),如果没找到就返回string::npos
size_type find( char ch, size_type index );
// 返回字符ch在字符串中第一次出现的位置(从index开始查找),如果没找到就返回string::npos
string常用函数:
string &insert(int p,const string &s);
//在p位置插入字符串s
string &replace(int p, int n,const char *s);
//删除从p开始的n个字符,然后在p处插入串s
string &erase(int p, int n);
//删除p开始的n个字符,返回修改后的字符串
string substr(int pos = 0,int n = npos) const;
//返回pos开始的n个字符组成的字符串
void swap(string &s2);
//交换当前字符串与s2的值
string &append(const char *s);
//把字符串s连接到当前字符串结尾
void push_back(char c)
//当前字符串尾部加一个字符c
const char *data()const;
//返回一个非null终止的c字符数组,data():与c_str()类似,用于string转const char*其中它返回的数组是不以空字符终止,
const char *c_str()const;
//返回一个以null终止的c字符串,即c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同,用于string转const char*
string类测试代码:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1 = "abc123defg";
string str2 = "swap!";
cout<<str1<<endl;
cout<<str1.erase(3,3)<<endl; //从索引3开始的3个字符,即删除掉了"123"
cout<<str1.insert(0,"123")<<endl; //在头部插入
cout<<str1.append("123")<<endl; //append()方法可以添加字符串
str1.push_back('A'); //push_back()方法只能添加一个字符
cout<<str1<<endl;
cout<<str1.replace(0,3,"hello")<<endl; //即将索引0开始的3个字符替换成"hello"
cout<<str1.substr(5,7)<<endl; //从索引5开始7个字节
str1.swap(str2);
cout<<str1<<endl;
const char* p = str.c_str();
printf("%s\n",p);
return 0;
}
本部分摘自博客园Do Better的文章:
C++string类总结
cmath
#include <cmath>
是一个预处理指令,它告诉预处理器在编译程序之前包含 <cmath> 头文件。<cmath> 头文件是 C++ 标准库的一部分,它提供了许多数学函数和常量的声明。这些函数和常量通常定义在 <math.h> 头文件中,但在 C++ 中,为了与 C 语言兼容,这些函数和常量被定义在 <cmath> 头文件中。
sin(x), cos(x), tan(x):三角函数,计算角 x 的正弦、余弦和正切值。
asin(x), acos(x), atan(x):反三角函数,计算正弦、余弦和正切值为 x 的角。
sinh(x), cosh(x), tanh(x):双曲函数,计算双曲正弦、余弦和正切值。
exp(x):计算 e 的 x 次幂,其中 e 是自然对数的底数。
log(x), log10(x):计算以 e 为底和以 10 为底的对数。
pow(x, y):计算 x 的 y 次幂。
sqrt(x):计算 x 的平方根。
ceil(x), floor(x), round(x):取整函数,分别返回大于或等于 x 的最小整数、小于或等于 x 的最大整数和最接近 x 的整数。
fabs(x), abs(x):计算 x 的绝对值。
fmod(x, y):计算 x 除以 y 的余数。
queue
queue队列容器是先进先出(FIFO,First In First Out)容器 ;该容器只允许在"队尾"进行插入操作, 而在" 队首"进行删除操作;该容器两边开口,一边用于插入元素 (不能删除),一边用于删除元素(不能插入):
1、push():在队列尾部插入一个元素;
2、pop():移除队列头部的元素。注意,如果队列为空,执行此操作将引发未定义行为;
3、front():返回队列头部的元素,但不移除它;
4、back():返回队列尾部的元素,但不移除它;
5、empty():检查队列是否为空,如果为空则返回true,否则返回false;
6、size():返回队列中的元素数量。
#include <iostream>
#include <queue>
using namespace std;
int main(){
queue<int> a;
for(int i=0;i<20;i++){
a.push(i);
}
cout << a.front() <<endl;
cout << a.back() <<endl;
cout << a.size() <<endl;
cout << a.empty() <<endl;
a.pop();
cout << a.front() <<endl;
}
stack
堆栈(Stack)代表了一个后进先出的对象集合。当您需要对各项进行后进先出的访问时,则使用堆栈。当您在列表中添加一项,称为推入元素,当您从列表中移除一项时,称为弹出元素:
1、push(num):将num入栈;
2、pop():栈顶数值出栈,栈顶改变;
3、top():返回栈顶数值,栈顶不变;
4、size():返回栈中元素数目;
5、empty():堆栈为空则返回真。
#include <iostream>
#include <stack>
using namespace std;
int main(){
stack<int> a,b;
for(int i=1;i<5;i++){
a.push(i*10);
}
for(int i=5;i<9;i++){
b.push(i*10);
}
cout << a.size() <<endl;
cout << a.top() << endl;
a.pop();
cout << a.size() <<endl;
cout << a.top() << endl;
}
bitset
bitset是C++语言的一个类库,用来方便地管理一系列的bit位而不用程序员自己来写代码,我们可以利用它来操作二进制数据。部分全排列的题目,可以尝试利用2进制数迭代的方式来实现,比如洛谷题号P2036。
#include<iostream>
#include<bitset>
using namespace std;
string toBin(int num){
bitset<10> binary(num);
return binary.to_string();
}
int main(){
cout << toBin(2);
}
bitset常用函数的补充说明:
bitset<一个常量>a;
//开一个存储0..一个常量-1的bitset
bitset<一个常量>b(一个只包含'0'和'1'的string);
a^=b
a&=b
a|=b
a<<=一个数
a>>=一个数
~a
a<<一个数
a>>一个数
a==b
a!=b
a&b
a|b
a^b
以上操作类比整数位运算
获取单个元素的引用(并改变值)
a[num]=0
a[num2]=1
然后是set和reset:
a.set()//初始化为1
a.reset()//初始化为0
a.set(num)//将a[num]变为1
a.reset(num)//将a[num]变为0
还有些奇怪的东西:
a.flip()//顾名思义
a.flip(num)//顾名思义
a.any()//返回是否有1
a.none()//返回是否没有1
a.count()//返回1的个数
a.to_ulong()//返回转化为unsigned long的结果,超出范围报错。
a.to_ullong()//同上,返回转化为ull的
当然还有STL清一色的
a.size()//返回大小,也就是位数
*numeric
注意在洛谷提交时似乎并不支持采用这个库~~所以加了*
号!C++ 标准库中的 <numeric>
头文件提供了一组用于数值计算的函数模板,这些函数可以对容器中的元素进行各种数值操作,如求和、乘积、最小值、最大值等。这些函数模板非常强大,可以应用于任何类型的容器,包括数组、向量、列表等。在使用 <numeric>
头文件中的函数之前,需要在你的 C++ 程序中包含这个头文件:(第一次知道这个库是在一道求最大公因数与最小公倍数的题目中)
#include<iostream>
#include<numeric>
using namespace std;
int main(){
cout << gcd(4,6) << endl;
cout << lcm(15,60) << endl;
}