C/C++_FAQ_Tips
目录
对unsigned 赋 负值 ,及与负数运算 (Test)
unsigned u = -1;
assert(u == pow(2, sizeof(unsigned) * 8) - 1); //将 -1 转化为unsigned ,再赋给 u
assert(u + 2 == 1); //unsigned 溢出, 溢出的数为1
u = 2;
int i = -1;
assert(u + i == 1); //将-1转换为无符号数,然后再进行相加 , 此处unsigned溢出
四舍五入
#include <bits/stdc++.h>
using namespace std;
double Round(double number, unsigned int bits)
{
stringstream ss;
ss << fixed << setprecision(bits) << number;
ss >> number;
return number;
}
int main(void)
{
//输出
double u = 14 / 3.0; //4.66666~
printf("%.2lf\n", u);
cout << fixed << setprecision(2) << u << endl;
//改变原值,四舍五入保留到整数
assert(round(u) == 5); //调用round()函数
u = (int)(u + 0.5); //巧妙运用类型转换, 若为负数 则 -0.5
assert(u == 5);
//改变原值,四舍五入到任意小数位
double i = 14 / 3.0;
i = Round(i, 2); // 4.670000~
assert(i - 4.67000 < 1e10);
return 0;
}
最大公约数GCD , 最小公倍数LCM
int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a % b); //欧几里得算法
}
//n个数的最大公约数算法:
//把n个数保存为一个数组
//参数为数组的指针和数组的大小(需要计算的数的个数)
//然后先求出gcd(a[0],a[1]), 然后将所求的gcd与数组的下一个元素作为gcd的参数继续求gcd
//这样就产生一个递归的求ngcd的算法
int ngcd(int *a, int n)
{
return n == 1 ? *a : gcd(a[n - 1], ngcd(a, n - 1));
}
// gcd*lcm=a*b
int lcm(int a, int b)
{
return a * b / (gcd(a, b));
}
//n个数的最小公倍数算法:
//算法过程和n个数的最大公约数求法类似
//求出头两个的最小公倍数,再将欺和大三个数求最小公倍数直到数组末尾
//这样产生一个递归的求nlcm的算法
int nlcm(int *a, int n)
{
return n == 1 ? *a : lcm(a[n - 1], nlcm(a, n - 1));
}
int main(void)
{
int a[5] = {18, 12, 30, 24, 36};
printf("%d %d %d %d", ngcd(a, 5), gcd(18, 12),lcm(10,12),nlcm(a,5));
return 0;
}
数字相关
__int128_t 输入,输出
inline __int128_t read()
{
__int128_t x = 0;
bool isPositive = true;
char ch = getchar();
while (isdigit(ch) == false)
{
if (ch == '-')
{
isPositive = false;
}
ch = getchar();
}
while (isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
return isPositive ? x : -x;
}
void write(__int128_t x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x > 9)
{
write(x / 10);
}
putchar(x % 10 + '0');
}
判断一个浮点数是否为整数
bool IsInteger_1(double x)
{
if (x - (int)x == 0)
{
return true;
}
else
{
return false;
}
}
bool IsInteger_2(double x)
{
if (fmod(x, 1) == 0)
{
return true;
}
else
{
return false;
}
}
整数的位数(长度)
unsigned LengthOfInt(int x)
{
unsigned count(0);
while (x)
{
x /= 10;
count++;
}
return count;
}
数字/字符串 互化
std::to_string;
atof() :将字符串转换为双精度浮点型值。
atoi() :将字符串转换为整型值。
atol() :将字符串转换为长整型s值。
翻转整数 120 -> 21
int ReverseInteger_1(int x)
{
string a = to_string(x);
stringstream in;
for (auto i = a.rbegin(); i != a.rend(); i++)
{
in << *i;
}
int re(0);
in >> re;
return re;
}
int ReverseInteger_2(int x)
{
int temp(0);
while (x)
{
temp = temp * 10 + x % 10;
x /= 10;
}
return temp;
}
排序算法
冒泡算法
#include <stdio.h>
void bubble_sort(int arr[], int len)
{
for (int i = 0; i < len - 1; i++) //外侧循环次数为 len-1 或 len
for (int j = 0; j < len - 1 - i; j++) //内循环次数为 len-1-i
{
int temp;
if (arr[j] > arr[j + 1]) //从小到大 升序
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
int main()
{
int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
int len = (int)sizeof(arr) / sizeof(*arr); // 数组长度
//sizeof测字节长度.
//short int 字节长 2 , int,long int,float 字节长为4 ,double ,long long int 字长 8
bubble_sort(arr, len);
return 0;
}
选择排序
#include <stdio.h>
void selection_sort(int arr[], int len)
{
for (int i = 0; i < len - 1; i++) //外侧循环次数为 len-1
for (int j = i + 1; j < len; j++) //内循环 为 len
{
if (arr[i] > arr[j]) //从小到大 升序
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
int main()
{
int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
int len = (int)sizeof(arr) / sizeof(*arr); // 数组长度
//sizeof测字节长度.
//short int 字节长 2 , int,long int,float 字节长为4 ,double ,long long int 字长 8
selection_sort(arr, len);
return 0;
}
打印问题
金字塔 _1
* * * * * * * * * * * * * * * * * * * * * * * * *
#include <stdio.h>
int main(void)
{
int rows;
scanf("%d", &rows);
for (int i = 1; i <= rows; i++)
{
for (int blank = 1; blank <= rows - i; blank++) //打印空格
{
printf(" "); //两个空格 第i行有2*(行数-i)个空格
}
for (int k = 0; k != 2 * i - 1; k++) //打印(星号+空格) 1-3-5-7-9...
{
printf("* ");
}
printf("\n");
}
return 0;
}
倒三角形_1
#include <stdio.h>
int main(int argc, char *argv[])
{
int rows;
scanf("%d", &rows);
for (int i = rows; i >= 1; i--)
{
//打印空格
for (int j = 0; j < rows - i; j++)
{
printf(" ");
}
for (int j = 0; j < 2 * i - 1; j++)
{
printf("* ");
}
printf("\n");
}
return 0;
}
数字三角形
1 2 3 2 3 4 5 4 3 4 5 6 7 6 5 4 5 6 7 8 9 8 7 6 5
#include <stdio.h>
int main(int argc, char *argv[])
{
int rows;
scanf("%d", &rows);
for (int i = 1; i <= rows; i++)
{
//打印空格
for (int j = 0; j < rows - i; j++)
{
printf(" ");
}
//左小一半
for (int k = i; k < 2 * i - 1; k++)
{
printf("%d ", k);
}
//右大半
for (int k = 2 * i - 1; k >= i; k--)
{
printf("%d ", k);
}
printf("\n");
}
return 0;
}
弗洛伊德三角
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#include <stdio.h>
int main()
{
int N;
scanf("%d", &N);
int j = 1;
for (int i = 1; i <= N; i++) //i控制打印行数
{
for (int l = 1; l <= i; l++, j++) //l 控制每行打印 l 个数字
printf("%5d", j); //j 为打印出来的数字,实为总共进行循环的次数
printf("\n");
}
return 0;
}
字符串相关
最长回文子串
#include <stdio.h>
#include <string.h>
int main(void)
{
char a[3000];
gets(a);
char b[3000];
int j = 0;
b[0] = 0;
for (int i = 1; a[j]; i++)
{
if ((i) % 2 == 0)
{
b[i] = a[j++];
b[i + 1] = '#';
b[i + 2] = 0;
}
else
{
b[i] = '#';
}
}
//ABCBA -> 0#A#A......#0
int max = 0;
for (int i = 1; b[i]; i++)
{
int current = 1, count = 0;
while (b[i - current] == b[i + current] && b[i - current] != 0 && b[i + current] != 0)
{
current++;
count++;
}
if (count > max)
{
max = count;
}
}
printf("%d", max);
return 0;
}
删除字符串中空格
//Version 1:
void remove_spaces(char *s)
{
char *d = s;
while (*s != 0)
{
while (*d == ' ')
{
d++;
}
*s = *d;
s++;
d++;
}
} // https://stackoverflow.com/questions/1726302/removing-spaces-from-a-string-in-c
//Version 2:
void delete_spaces(char *s)
{
for (int i = 0, j = 0; s[i] != 0; i++)
{
if (s[i] != ' ')
{
s[j] = s[i];
j++;
}
}
s[j] = 0;
}
交并差集
#include <vector>
#include <algorithm> //sort函数、交并补函数
#include <iterator> //求交并补使用到的迭代器
using namespace std;
//容器vector中元素的去重
vector<int> unique_element_in_vector(vector<int> v)
{
vector<int>::iterator vector_iterator;
//使用sort()进行排序,排序后的相同元素集中出现
sort(v.begin(), v.end());
//unique()函数将重复的元素放到vector的尾部(无序) 然后返回指向第一个重复元素的迭代器
vector_iterator = unique(v.begin(), v.end());
if (vector_iterator != v.end())
{
//再用erase函数擦除从这个元素到最后元素的所有的元素。
v.erase(vector_iterator, v.end());
}
return v;
}
//两个vector求交并差集
vector<int> vectors_intersection(vector<int> v1, vector<int> v2)
{
vector<int> v;
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(v)); //求交集
set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(v)); //求并集
set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(v));
//求差集 v1中有,v2中没有
//?差集与补集关系
return v;
}
迭代器
Insertion into a vector can invalidate iterators
children.insert(it, node); // this can invalidate `it', triggering a // segfault during the next iteration
for
循环使用 iterator , 并对容器进行 insert
, 会 [segmentation fault]
IO相关
cin >>
处理空格
当cin>>从缓冲区中读取数据时,若缓冲区中第一个字符是空格、tab或换行这些分隔符时,cin>>会将其忽略并清除,继续读取下一个字符,若缓冲区为空,则继续等待。但是如果读取成功,字符后面的分隔符是残留在缓冲区的,cin>>不做处理。
cin>>对缓冲区中的第一个换行符视而不见,采取的措施是忽略清除,继续阻塞等待缓冲区有效数据的到来。但是,getline()读取数据时,并非像cin>>那样忽略第一个换行符,getline()发现cin的缓冲区中有一个残留的换行符,不阻塞请求键盘输入,直接读取,送入目标字符串后,再将换行符替换为空字符’\0'.
scanf
读取 换行符
int n;
scanf("%d",&n);
char ch;
scanf("%c",&ch);
//以上ch为'\n'
scanf
后 gets
//形似
int n;char srt[10];
scanf("%d",&n);
//getchar(); //解决方法
gets(str); //这里gets不会执行
scanf
函数在读取字符以外的输入时,
不接收'\n'
,把'\n'
留存在输入缓冲区中,后面被gets
当一个字符接收了;
而gets
在读入'\n'
后就认为字符串结束了,所以你啥也没有看到而向下走了。
解决办法是在gets
前加一句getchar()
,把那些该死的'\n'
从缓冲区中取走.