机试零碎知识点总结
格式化输出
1.使用%.2f进行保留两位小数输出时会自动进行四舍五入操作
pow(x, y)的使用
pow
函数的计算结果默认是double
,如果直接使用int
强转为整数,则是直接截断,很容易出错,例如:https://blog.youkuaiyun.com/qq_41911859/article/details/108186786中的例4.3,如果在计算结果时直接强行转换,则最后结果总是差1,最佳的办法是(int) (pow(x, y) + 0.5)
,来源:https://blog.youkuaiyun.com/wuli_dear_wang/article/details/8037325
C/C++中scanf、getline、gets、cin、cin.get、cin.getline等输入函数的问题
方法 | 以什么为界 | 是否回丢弃末尾的换行符 |
---|---|---|
scanf | 读取单个字符时所有字符都通吃,会读入换行和空白字符,读取字符串以空白字符为界,不会读入空白字符 | 当读取字符串时不会读取,也不会丢弃,换行符保留在输入流中 |
cin | 读取单个字符和字符串时都是以空白字符为界,不会读入空白字符 | 不会读取换行符,也不会丢弃,换行符保留在输入流中 |
cin.get | 读取单个字符时和scanf一样,通吃,空白字符也会被读入,也可以用来读取一行数据,以换行符结束,也可以指定结束符,保存到字符串中(只能放到char*中,而不能放到string中) | 不会对换行符进行处理,换行符保留在输入流中 |
cin.getline | 用来读取一行,以换行符结束,也可以指定结束符 | 不会将换行符保留,会进行丢弃 |
getline | 用来读取一行,默认以换行符结束,也可以指定结束符,C++的函数,包含在string库中,返回值为指针,难以用来判断文件末尾 | 会读取换行符,当最后会被替代为空字符,相当于丢弃 |
gets | 用来读取一行,但不会限定上限,可能会溢出,C语言函数,包含在stdio.h库中,当读入到EOF时返回NULL指针 | 不会读取换行符,但是会丢弃换行符 |
当读取单个数据和读取一行数据连用的时候可能会出现残留的换行符影响的现象,这时候可以使用istream &ignore( streamsize num=1, int delim=EOF );
函数,其中第一个参数用来指明清除多少个字符,第二个参数用来指明结束符。一般可以使用cin.ignore(numeric_limits<std::streamsize>::max(),'\n');
来清除当前行的所有残余数据,其中numeric_limits::max()
是头文件中规定的流的最大值。
参考博客:https://blog.youkuaiyun.com/bravedence/article/details/77282039
https://blog.youkuaiyun.com/u010078776/article/details/14454773
gets()函数详解:https://www.cnblogs.com/dushikang/p/8328032.html
C/C++中数组和字符串的复制
对于C语言中的字符数组复制不能直接使用=,而需要使用char* strcpy(char* dst, const char* src);
函数。同时对于C++中是string
对象的拷贝有浅拷贝(只赋值地址,会改变原变量的值)和深拷贝(重新开辟存储空间,对数据进行赋值)之分,在拷贝时直接使用=,默认是深拷贝,其他细节可见:https://blog.youkuaiyun.com/tattooe/article/details/78444815
对于数组的复制使用void *memcpy(void *dest, const void *src, size_t n);
C/C++中long long 数据类型的格式化输入输出问题
如果使用scanf 和printf对long long 类型的数据进行输入输出,不能使用%d,而需要使用%lld 或者%I64d,不过在一些平台上%lld 无法通过,所以还是一致使用%I64d。来源:https://blog.youkuaiyun.com/u014665013/article/details/38369509
C/C++中的一些杂项
- 对于字符数组和
string
来说,索引为0的数据就是最左边的数据,索引从左至右逐渐增大。 - 简单记忆ASCII码表,数字’0’对应的十进制数为48,大写字母’A’对应的十进制数为65,小写字母’a’对应的十进制数为97。来源:https://blog.youkuaiyun.com/qq_35831134/article/details/90484568
- 在运算时要灵活使用运算顺序来避免溢出,当既有除法又有乘法时,可以优先做除法再做乘法(当为整数时没有误差)
- 对于大范围数据,需要注意的是,两个操作数的运算结果首先会保存在一个和操作数大小相同的数据空间中,然后才会再被赋值给另一个变量。所以当一个操作数的数据范围在一个数据类型的边界附近时,如果还要对该操作数进行运算,则最后设置更大的存储空间,避免溢出。
- C/C++中自带的字母大小写转换函数,
tolower(),toupper()
,包含在头文件<ctype.h>或者< cctype >中,能够把单个字符转换为大写或者小写,如果要转换字符串,则需要使用循环。 - 难以用返回值判断文件末尾的都使用
cin.eof()
来判断。 - 对于输入缓冲区中残余的回车,在使用C++时可以使用cin.ignore(1),来清除,在使用C时,可以直接通过getchar()来进行清除。
C/C++中sprintf函数使用中可能出现的错误
使用sprintf(s, “%d”, x)的话,sprintf函数会自动在s的后一个位置加上’\0’,这样可能会导致错误
C/C++中提取一行数据中的整数(为事先告知整数数目)
当输入一行整数,但是事先没有告知整数的数目时提取整数数据的方法:以下代码数据类型不一定要使用unsigned long long
int in(unsigned long long data[]){
char str[MAX];
unsigned long long res = 0;
cin.getline(str, MAX);
int s = strlen(str);
int i, cmt = 0;
for(i=0; i<s; i++){
if(str[i] >= '0' && str[i] <= '9'){
res *= 10;
res += str[i] - '0';
}
if(str[i] == ' ' || i == s-1){
data[cmt] = res;
res = 0;
cmt++;
}
}
return cmt;
}
C/C++中sqrt()函数的问题
C/C++中的double sqrt(double);
函数问题,此函数输入和输出都属double类型,在使用时一般都需要使用int进行强制类型转换,同时sqrt函数计算比较耗时,不推荐在循环计算,可以使用临时变量,以空间换时间,或者使用i*i<= m
的判断形式来替代。
C/C++中矩阵相乘的运算模板
void multiple(int a[][MAX], int b[][MAX], int n)
{
int i, j, k;
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
for(k=0; k<n; k++)
{
mulres[i][j] = ((a[i][k] % M) * (b[k][j] % M) + mulres[i][j]) % M;
}
}
}
}
C/C++中二维数组作为函数参数的问题
将二维数组作为函数的参数的问题,C语言中二维数组是按行存储的,在将二维数组作为函数参数时必须指定列数,行数可以不指定。可以体现为void Func(int array[3][10]);
,void Func(int array[][10]);
和void print(int (*a)[3]);
等形式。参考博客:https://www.cnblogs.com/Anker/archive/2013/03/09/2951878.html
C/C++中memcpy函数的使用问题
memcpy()
函数的使用,该函数在<string.h>
头文件中,函数原型为void *memcpy(void *dest, const void *src, size_t n);
可以从src所指向的地址空间中拷贝n个字节的内容到目标地址空间中。参考博客:https://blog.youkuaiyun.com/qq_38993096/article/details/88377285
C/C++中大整数加法、乘法、除法和取余运算的实现
大整数的加法、乘法、除法和取余运算的实现,可以多熟悉,之后直接使用。如下
int multiple(int data[], int a, int n)
{
int i, temp;
int carry = 0;
for(i=0; i<n; i++)
{
temp = data[i] * a + carry;
carry = temp / 10;
data[i] = temp % 10;
}
while(carry % 10 != 0)
{
data[n++] = carry % 10;
carry /= 10;
}
return n;
}
int add(int data1[], int s1, int data2[], int s2)
{
int s = (s1 >= s2) ? s1 : s2;
int i, temp, carry = 0;
for(i=0; i<s; i++)
{
temp = data1[i] + data2[i] + carry;
carry = temp / 10;
data1[i] = temp % 10;
}
if(carry != 0)
data1[s++] = carry;
return s;
}
int division(int data[], int a, int n, int &remain)//特别注意,每次做除法时要把remain清零
{
int i, temp, s = n;
int borrow = 0;
bool flag = false;
remain = 0;
for(i=n-1; i>=0; i--)
{
temp = data[i] + 10 * borrow;
if(temp < a)
{
data[i] = 0;
borrow = temp;
if(!flag)
s--;
}
else
{
flag = true;
data[i] = temp / a;
borrow = temp % a;
}
}
if(borrow != 0)
remain = borrow;
return s;
}