PTA_Basic 总结

1. 字符数组和整形之间的转换

  1. 一般方法(不推荐):利用标准库 < cstdlib > 中的函数
// 将 value 转化为 radix 进制的数
// *string: 保存转换后得到的字符串
// 注意当string为char数组时,应保证其长度至少为整数长度 + 1
char* itoa(int value, char *string, int radix);	
int atoi(const char *nptr);
  1. 重复利用stringstream对象(推荐):< sstream >
	stringstream s;
	int ival = 123;
	double dval;
	char cval[5];
	s << ival;
	s >> cval;
	s.clear();	// 每次使用后应手动清除,否则会影响下次使用
	cout << cval << endl;
	cout << s.str() << endl;
	cval[3] = '.';
	cval[4] = '6';
	s << cval;
	s >> dval;
	cout << dval << endl;

说明:stingstream 能将任何类型转变为字符串类型,也能将字符串类型转变为数字类型,类似于 <stdio.h> 中的 sprintf 和 sscanf 函数,但是 stringstream 操作更加的安全、不会产生数组溢出等问题,而且操作简单
注意:stringstream 不会主动释放内存,要使用其自带的 clear() 函数 释放内存
参考
C/C++中字符串与数字转换
clear函数的真正用途


2. 输入输出格式

  1. scanf / printf:< cstdio >(推荐)
	double d = 12.34;
	scanf("%lf",&d);
	print("%f",d);	// 注意此处的区别

	int a = 123;
	printf("%5d",a);	// %md : 向右对齐,空格填充
	printf("%-5d", a);	// %-md : 向左对齐,空格填充
	printf("%05d",a);	// %0md : 0填充
	printf("%.3f",d);	// %.mf : 保留 m 位小数,向偶舍入
  1. cin / cout:< iostream >、< iomanip >(速度较慢)
cout << fixed << setprecision(2) << N <<endl;	
cout << setw(2) << setfill('0') << M << endl;	// 0填充
char c[5];
cin.get(c,3) 	// 表示读取 3 个字符到 c
//注意: setw 的作用是一次性的

参考
C++ cout格式化输出(输出格式)完全攻略
注意:两种 I/O 方式不能混用


3. STL 相关

  1. vector:动态数组
#include <vector>
using namespace std;
/* -------------------------------------- */
	vector<TypeName> v;
	vector<TypeName> v(MaxSize, InitialValue);
	vector<vector<TypeName> > v;		// 注意此处为 > > 而非 >>
	vector<TypeName> v[ArraySize];
/* -------------------------------------- */
	vector<TypeName>::iterator it;		// 迭代器
	it = v.begin();		// 指向队首元素
	it = v.end();		// 指向队尾元素+1
	v[i] 等价于 	*(v.begin()+i)
	应满足: v.begin() + i <= v.end()
/* -------------------------------------- */
	// 遍历
	for(int i=0; i<v.size(); i++)
		cout << v[i] << " ";
	
	for(vector<TypeName>::it=v.begin(); i != v.end(); it++)	// 结束条件: it != v.end() 
		cout << *it << " ";
/* -------------------------------------- */
	v.at(int pos); 		// 返回 pos 位置的引用; 
	v.front(); v.back();	// 返回 队首/队尾 元素
	v.push_back(x);		// 在数组末尾添加 x
	v.pop_back();		// 删除末尾元素
	v.size();			// 获取元素个数
	v.empty();			// 若数组为空, 返回 1
	v.clear();			//  清空数组
	v.insert(it,x);		// 在迭代器 it 的位置插入 x, 不能为数组下标
	v.erase(it);		// 删除 迭代器 it 处的元素
	v.erase(it, it+i);	// 删除 [it, it+i) 范围内的所有元素,注意为 左闭右开
/* -------------------------------------- */

/* -------------------------------------- */
1.若向量长度较长,容易导致内存泄漏,且效率低
2.vector作为函数的参数或者返回值时,需注意:
   double Distance(vector<int>&a, vector<int>&b) // 注意: & 
3.除 vector 和 string 以外的 STL 都不支持 *(it + i) 的访问方式

  1. set:集合,内部自动有序(递增)且不含重复元素
#include <set>
using namespace std;
/* -------------------------------------- */
set<TypeName> s;
set<TypeName>::iterator it;
/* -------------------------------------- */
	for(set<TypeName>::iterator it = s.begin();it != s.end();it++)
        cout<<*it<<" ";
// 注意: set 不能使用 s[i] 数组下标的形式进行访问
/* -------------------------------------- */
	s.begin(); s.end()
	s.empty(); s.size(); s.clear();
	s.insert(x); 
	s.erase(it); s.erase(value); s.erase(first, last);
	s.find(value);			// 返回对应迭代器, 若没找到则返回 end()

  1. string
#include <string>	// 注意与 <string.h>/<cstring> 区别
using namespace std;
/* -------------------------------------- */
	string str;
	str.size(); str.length(); str.clear();
	str.insert(pos, string);
	str.insert(it, first, last);	// 在 it 处插入[first, last), 三者均为迭代器
	str.erase(it); str.erase(first, last); str.erase(pos, len);
	str.substr(pos, len);		// 返回从 pos 开始长度为 len 的子串
	str.find(str2);	str.find(str2, pos)		// 寻找子串str2, 返回其首次出现的位置下标,否则返回 string::npos 【注意判断条件!】
	str.rfind(str2);			// 返回最后一个匹配的子串
	str.replace(pos, len, str2); str.replace(first, last, str2)		// [first, last)
/* string::npos == -1	// true
   string::npos == 4294967295	// true, 其为 unsigned
*/ 
/* -------------------------------------- */
	operator += : 字符串的拼接
	compare operator : 比较字典序 
/* -------------------------------------- */
// scanf/printf 输入输出
	str.resize(9);    // 预先分配空间
    scanf("%s", &str[0]);
    printf("%s", str.c_str()); 
/* -------------------------------------- */
1.<string.h>: C版本的头文件,包含strcpy、strcat之类的字符串处理函数;
2.<cstring>: 在C++标准化(1998)过程中,为了兼容旧版本,标准化组织将所有这些文件都进行了新的定义,加入到了标准库中
3.<string>: C++标准定义的头文件,定义了一个string的字符串类
//包含了string类的各种操作,如s.size(), s.erase(), s.insert()等, 同时也包含了老的C版本的字符串操作如strcpy、strcat等;

需要注意的是:
1.若要使用 cin/cout 直接输入输出 string 类型字符串,需要<string>
2.memset 函数定义在<cstring>头文件中

  1. map:映射
#include <map>
using namespace std;
/* -------------------------------------- */
	map<TypeName1, TypeName2> m;		// map<key, value>
	map<TypeName1, TypeName2>::iterator it;
1.可用下标访问,注意键值唯一;
2.通过迭代器访问:
	for(it = m.begin(); it != m.end(); it++)
		cout<<it->first<<" "<<it->second<<endl;
// map 会按照 key 递增自动排序
/* -------------------------------------- */
	m.size(); m.clear(); m.empty();
	m.insert(pair<TypeName1, TypeName2>(key, value)); 
	m.find(key);		// 返回 迭代器
	m.erase(it); m.erase(key); m.erase(first, last);
/* --------------------------------------- */
	if(C.find(name) != C.end())		// 条件语句中需要加上具体的判断条件

  1. queue:队列、优先队列
#include <queue>
using namespace std;
/* -------------------------------------- */
	queue<TypeName> q;
	q.size(); q.empty(); 
	q.front(); q.back();	// 使用前必须判断队列是否为空,否则会发生错误
	q.push(x); q.pop();
/* -------------------------------------- */
	priority_queue<int> q2;	// 最大堆
	priority_queue<int, vector<int>, greater<int> > q3;	// 最小堆
	int p = q2.top();		// 优先队列没有 front 和 back 函数, 其他函数调用相同
/* -------------------------------------- */
// 结构体的优先级设置
struct fruit{
	string name;
	int price;
	friend bool operator < (fruit f1, fruit f2){	// 注意: 只能重载 <
		return f1.price < f2.price;			// 最大堆
	}
}
queue<fruit> q_fruit;	// 价格高的水果优先级高

  1. stack:栈
#include <stack>
using namespace std;
/* -------------------------------------- */
	stack<TypeName> s;
	s.size(); s.empty(); 
	s.top();
	s.push(x); s.pop();

  1. pair:相当于有两个元素的结构体
#include <uility>	// 包含于 <map>
using namespace std;
/* -------------------------------------- */
	pair<TypeName1, TypeName2> p;
	pair<string, int> p1("abc", 5);
	pair<string, int> p2 = make_pair(first, second);
	cout<<p.first<<" "<<p.second;
/* -------------------------------------- */
compare: < == > != ....., 先以 first 的大小为标准, 只有在 first 相等时, 才会去比较 second
  1. algorithm:一些常用函数
#include <algorithm>
using namespace std;
/* -------------------------------------- */
	max(x,y); min(x,y); abs(x);
	swap(x,y);
	reverse(it,it2);	// 交换指针或迭代器所指向元素位置
	fill(a, a+N, num);		// 较 memset 效率稍低
	lower_bound(first, last, val);	// 返回[first,last)范围内第一个大于等于val的数组指针或迭代器,否则返回可插入地址
	upper_bound(first,last,val);	// 返回第一个大于val的数组指针或迭代器
	lower_bound(a, a+N, value);		// 注意: 若 a[0]==value, 则继续往后查
	sort(a, a+N); sort(a, a+N; cmp);	// 默认为 非递减
/* -------------------------------------- */
bool cmp1(int a, int b) {
	return a > b;	// > : 降序,由大到小(非递增)
}

bool cmp2(int a, int b) {
	return a < b;	// < : 升序,由小到大(非递减)
}

4. 数学相关

  1. 素数
bool prime(int n){
    if(n <= 1)   return false;
    int r = sqrt(n);
    for(int i=2; i<=r; i++){
        if(n % i == 0)
            return false;
    }
    return true;
}
  1. 最大公约数(欧几里得算法): g c d ( a , b ) = g c d ( b , a % b ) gcd(a,b)=gcd(b,a\%b) gcd(a,b)=gcd(b,a%b)
  2. 最小公倍数: l c m ( a , b ) = ( a ∗ b ) / g c d ( a , b ) = a / ( b ∗ g c d ( a , b ) ) lcm(a,b)=(a*b)/gcd(a,b)=a/(b*gcd(a,b)) lcm(a,b)=(ab)/gcd(a,b)=a/(bgcd(a,b)),后者防止溢出
int gcd(int M, int N)
{
	int tmp;
	while (N > 0) {
		tmp = M % N;
		M = N;
		N = tmp;
	}
	return M;
}
  1. 快速幂运算: X N % m X^N\%m XN%m
typedef long long LL;
LL quick_pow(LL X, unsigned N, LL m)
{
    if(N == 0)  return 0;
    if(N == 1)  return X;
    if(N%2 == 1)	// 奇数    
        return quick_pow(X, N-1, m)*X % m;	// X^N = X^(N-1)*X 	
    else{	// 偶数    
        LL mul = quick_pow(X, N/2, m);	// X^N = X^(N/2)*X^(N/2)
        return mul*mul % m;
    }
}
  1. 将任意进制的数转换为十进制数:
	int sum = 0;	// 此处需要注意判断 sum 的范围, 必要时应使用 long long
	for(int i=0;num[i]!='\0';i++
		sum = sum*radix + num[i] - '0';

5. 杂项

  1. 判断溢出
	int A,B;
	if (A > 0 && B > 0 && A + B < A) //向上溢出 
	if (A < 0 && B < 0 && A + B > A) //向下溢出 

/*--- 关于大数溢出的判断方法:		*/
	long long num;
	......		// 保证正常情况下 num >= 0
	if(num < 0)
		// 溢出
  1. 当输入中可能存在空字符串时:
	string str;
	getline(cin, keys);
	// cin >> str 无法读取空字符串
  1. 二分查找
	while(low<=high){
		mid = low + (high-low)/2;	// 避免 (low+high) 发生溢出
		if(...)
			low = mid + 1;
		else
			high = mid - 1;

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值