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溢出

More

四舍五入

#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

https://oi-wiki.org/math/gcd/

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

More

for循环使用 iterator , 并对容器进行 insert , 会 [segmentation fault]

IO相关

cin >> 处理空格

当cin>>从缓冲区中读取数据时,若缓冲区中第一个字符是空格、tab或换行这些分隔符时,cin>>会将其忽略并清除,继续读取下一个字符,若缓冲区为空,则继续等待。但是如果读取成功,字符后面的分隔符是残留在缓冲区的,cin>>不做处理。
cin>>对缓冲区中的第一个换行符视而不见,采取的措施是忽略清除,继续阻塞等待缓冲区有效数据的到来。但是,getline()读取数据时,并非像cin>>那样忽略第一个换行符,getline()发现cin的缓冲区中有一个残留的换行符,不阻塞请求键盘输入,直接读取,送入目标字符串后,再将换行符替换为空字符’\0'.

More

scanf 读取 换行符

int n;
scanf("%d",&n);
char ch;
scanf("%c",&ch);
//以上ch为'\n'

Click here

scanfgets

//形似
int n;char srt[10];
scanf("%d",&n);
//getchar();        //解决方法
gets(str);   //这里gets不会执行

scanf函数在读取字符以外的输入时,
不接收'\n',把'\n'留存在输入缓冲区中,后面被gets当一个字符接收了;
gets在读入'\n'后就认为字符串结束了,所以你啥也没有看到而向下走了。
解决办法是在gets前加一句getchar(),把那些该死的'\n'从缓冲区中取走.

posted @ 2019-12-24 09:43  Delta_in_Cnblogs  阅读(296)  评论(0编辑  收藏  举报