目录
一、选择题
二、编程题
1、组队竞赛
2、删除公共字符
一、选择题
1、
解析:%s遇到'\0'会停止,%m.ns中m表示字符串宽度,n表示左起取目标字符串n个字符,右对齐,(如果想要左对齐,可以写成%-m.ns)不够的补空格。注意:如果n>m,那么m就会失效,输出的宽度就是n,如果n>字符串长度,将输出全部字符串,不管m是多少。
所以本题答案是computer, com。
2、
解析:在表达式中,不同类型的数据参与运算时,编译器会自动把较小的类型转换为较大的类型,然后在进行计算。在本例中,char 和 int 都是较小的类型,double 是较大的类型,所以 ‘A’ 和 a 都会被转换为 double 类型,然后与 b 相加,得到一个 double 类型的结果。本题选C。
3、
解析:当使用free释放掉一个指针后,free喊叔叔并不会自动把指针bianlinag设为NULL,它只是释放了指针之乡的内存空间,程序员还需要显式地给指针变量赋值为NULL。本题选A。
4、
解析:const在指针中的使用遵循这样的规则,
(1)如果const在星号的左边,那么const修饰指针指向的变量,即指针指向为常量。例如const int*p和int const*p都表示p是一个指向const int的指针,p可以改变指向,但不可以通过p改变变量的值。
(2)如果const在星号的右边,那么const修饰指针本身,即指针本身为常量。例如int *const p表示p是一个指向int 的常量指针,p不能改变指向,但可以通过票改变指向的值。
(3)如果const同时在星号的左右,那么既不能修改p的指向,也不能通过p修改所指向的值,例如const int* const p。
因此,该程序中有以下错误:
(1) 行:常量指针p1没有初始化,应该给定一个初始地址,且必须是变量地址。(答案少了这个)
(6) 行:常量指针p2不能修改其指向的变量的值,应该去掉这一行。
(7) 行:指针常量p3不能改变指向,应该去掉这一行。
5、
解析:宏定义的常量并不一定比const常量更容易理解,因为宏定义的常量没有类型信息,而且可能会被重复定义或取消定义.。另外,const常量可以避免一些宏定义可能导致的运算优先级或副作用。本题选B。
6、
解析:一个有10个指针的数组,可以用int *a[10]
来声明,这意味着a
是一个数组,它的元素是指向整型数的指针。一个指向函数的指针,可以用int (*a)(int)
来声明,这意味着a
是一个指针,它指向一个有一个整型参数并返回一个整型数的函数。
因此,如果我们想要一个有10个指针的数组,而这些指针都指向同样类型的函数,我们可以用int (*a[10])(int)
来声明,这意味着a
是一个数组,它的元素是指向有一个整型参数并返回一个整型数的函数的指针。
7、
解析:在32位CPU上,缺省对齐的情况下,结构体的总大小为结构体最宽基本类型成员大小的整数倍。在这个例子中,结构体最宽的基本类型成员是unsigned int,占4个字节。结构体中的位域成员按照其所属的基本类型进行对齐。
在这个例子中,所有的位域成员都属于unsigned int类型,所以它们都按照4个字节进行对齐。结构体中的位域成员如果不能被其所属的基本类型整除,那么会从下一个基本类型开始存放。在这个例子中,a、b、c共占用19+11+4=34位,所以c放在第二个4字节里,4+29=33位,所以d放在第三个4字节里面。
因此,结构体中共占用了3个unsigned int和1个char,总共占用了3*4+1=13个字节。但是由于结构体的总大小要为4的整数倍,所以还需要在末尾补上3个字节的填充,使得结构体的总大小为16个字节。
8、
解析:&a和a的区别主要取决于a的类型和使用的上下文。一般来说,&a表示取a的地址,而a表示取a的值。但是,如果a是一个数组或一个函数,那么它们的区别就比较复杂。
如果a是一个数组,比如int a[10],那么&a和a都表示数组的首地址,但是它们的类型不同。&a的类型是指向数组的指针,即int(*)[10],而a的类型是指向数组第一个元素的指针,即int *。因此,&a+1和a+1的值也不同,&a+1表示跳过整个数组,而a+1表示跳过一个元素。
如果a是一个函数,比如int a(int x),那么&a和a都表示函数的地址,但是它们的类型不同。&a的类型是指向函数的指针,即int (*)(int),而a的类型是函数类型,即int (int)。因此,在调用函数时,可以直接使用a(x)或者(*a)(x),也可以使用(&a)(x)或者(**&a)(x)等等。
现在来看题目:
&a
是一个指向数组的指针,它的类型是int (*)[4]
,即指向有4个整型元素的数组的指针。
&a+1
是将&a
向后移动一个单位,即移动了一个数组的长度,也就是4个整型数的长度,即4*4=16个字节。
(int*)(&a+1)
是将&a+1
强制转换为一个指向整型数的指针,它的类型是int *
,即指向整型数的指针。
ptr=(int*)(&a+1)
是将(int*)(&a+1)
赋值给ptr
,这样ptr
就指向了数组a
之后的第一个位置,也就是内存中存放着数组a
的下一个变量的位置。
*(ptr-1)
是将ptr
向前移动一个单位,即移动了一个整型数的长度,即4个字节,然后取出它所指向的值。这样就相当于取出了数组a
的最后一个元素,也就是4。
二、编程题
1、组队竞赛
解析:本题的主要思路是贪心算法,贪心算法其实很简单,就是每次选值时都选当前能看到的局部最优解,所以这里的贪心就是保证每组的第二个值取到能选择的最大值就可以,我们每次尽量取最大,但是最大的数不可能是中位数,所以退而求其次,取每组中第二大的。
代码如下:
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
int n;
while(cin>>n)
{
long long sum=0;
vector<int> team;
team.resize(3*n);
for(int i=0;i<3*n;i++)
{
cin>>team[i];
}
sort(team.begin(),team.end());
for(int i=0;i<n;i++)
{
sum+=team[team.size()-(2*i+1)-1];
}
cout<<sum;
}
}
2、删除公共字符
解析:本题如果使用传统的暴力查找方式,如判断第一个串的字符是否在第二个串中,在再挪动字符删除这个字符的方式,效率为O(N^2),效率太低,很难让人满意。
1. 将第二个字符串的字符都映射到一个hash数组中,用来判断一个字符在这个字符串。
2. 判断一个字符在第二个字符串,不要使用删除,这样效率太低,因为每次删除都伴随数据挪动。这里可以考虑把字符添加到一个新字符串,最后返回新字符串。
代码如下:
#include <iostream>
#include<string>
using namespace std;
int main() {
string str1,str2;
getline(cin,str1);
getline(cin,str2);
int hash[256]={0};
for(int i=0;i<str2.size();i++)
{
hash[str2[i]]++;
}
string newstr="";
for(int i=0;i<str1.size();i++)
{
if(hash[str1[i]]==0)newstr+=str1[i];
}
cout<<newstr<<endl;
}