问答题
问答题1:假设在一个 32 位 little endian 的机器上运行下面的程序,结果是多少?
#include <stdio.h>
int main(){
long long a = 1, b = 2, c = 3;
printf("%d %d %d\n", a, b, c);
return 0;
}
提示:变量 a,b,c的类型都是long long
,占 8个字节 ,而 printf
取出来使用4个字节的,所以会出现偏差,另外printf()
是一个库函数,C/C++
函数的参数是从右往左入栈的;栈的生长方向是从高往低的;小端模式是低位存储在低字节
问答题2:如何捕获异常可以使得代码通过编译?
class A {
public:
A(){}
};
void foo(){
throw new A;
}
(A)catch (A && x)
(B)catch (A * x)
(C)catch (A & x)
(D)以上都是
提示:throw new A;
throw
出的是A * 类型的指针所以 catch(A * x);
问答题3:下列代码应该如何修改?
template <class T>
struct sum {
static void foo(T op1, T op2) {
cout << op1 << op2;
}
};
sum::foo(1, 3);
提示:函数模板可以不说明对象,类模板必须要说明类型,所以在类名的后面加<int>
,意思就是加上 <int>才算是一个类,否则上面定义的那个 sum 只是一个模板.
问答题4:下列程序输出啥?
class A {
public:
~A() {
cout << "~A()";
}
};
class B{
public:
virtual ~B() {
cout << "~B()";
}
};
class C: public A, public B {
public:
~C() {
cout << "~C()";
}
};
int main() {
C * c = new C;
B * b1 = dynamic_cast<B *>(c);
A * a2 = dynamic_cast<A *>(b1);
delete a2;
}
(A) ~C() ~B() ~A()
(B) ~C() ~A() ~B()
(C) A,B 都有可能
(D) 以上都不对
提示:dynamic_cast
动态转换从派生类转基类的时候可以,但是从基类转派生类可能会出错.因为要进行类型检测
dynamic_cast的转换格式:dynamic_cast (expression)
如果 expression
是type-id
的基类,使用dynamic_cast
进行转换时,在运行时就会检查expression
是否真正的指向一个type-id
类型的对象,如果是,则能进行正确的转换,获得对应的值;否则返回NULL
,如果是引用,则在运行时就会抛出异常;
编程题
编程题1:完全数
完美数是一些特殊的自然数,它所有的真因子恰好等于它本身
真因子是除本身之外所有的约数,例 28
真因子为1,2,4,7,14
有 1 + 2 + 4 + 7 + 14 = 28
给定函数 count(int n)
用于计算 n 以内完全数的个数,返回n以内完全数的个数,异常情况返回-1
#include <iostream>
using namespace std;
int perfect(int m){
int sum = 0;
for (int i = 1; i < (m/2)+1; ++i) {
if (m%i == 0) {
sum += i;
}
}
if (sum == m) {
return 1;
}
else {
return 0;
}
}
void count(int n){
int num = 0;
for (int i = 3; i < n + 1; ++i) {
if (perfect(i) == 1) {
++num;
}
}
if (num != 0) {
cout << num<<endl;
}else {
cout << -1<<endl;
}
}
int main(){
int N = 0;
while (cin >> N) {
count(N);
}
return 0;
}
代码优化
优化部分,在寻找约数的时候,只要遍历到平方根的时候,就可以了;例 36 的约数,只要遍历到 6 就可以把所有的约数加起来.
#include <iostream>
#include <algorithm>
using namespace std;
int count(int num){
int cnt = 0;
if(num > 500000 || num <=0){
return -1;
}
for(int i=2;i<num+1;++i){
int sum = 0;
for(int j=2;j<sqrt(i);++j){
if(i%j == 0){
// 平方数
if(i/j==j){
sum+=j;
}else{
sum+= j+i/j;
}
}
}
if(sum+1==i){
cnt++;
}
}
return cnt;
}
int main(){
int n;
while(cin>>n){
cout<<count(n)<<endl;
}
return 0;
}
编程题2:扑克牌大小
一副扑克牌由54张组成,含 3~A
有四张、2 有 4 张,小王1张,大王1张
牌面从小到大用如下字符和字符串表示(小写joker
表示小王,大写JOKER
表示大王)
请比较两手牌大小,输出较大的牌,如果不存在比较关系则输出ERROR
基本规则如下:
(1) 输入每手牌可能是单牌、对子牌、顺子牌(连续5张)、三个牌、炸弹(四张相同)牌,王炸牌 这六种情况
(2) 除了炸弹和王炸可以和所有牌比较之外,其他类型的牌只能跟相同类型的存在比较关系
(3)大小规则跟大家平时了解的常见规则相同,按大小比较,炸弹可以炸单牌,对子牌,顺子牌,三个牌,另外炸弹之间也比较牌面大小,对王是最大的牌;
(4) 输入的两手牌不会出现相等的情况
输入描述:输入两手牌,两手牌之间用"-"
连接,每手牌的每张牌以空格分隔,"-"
两边没有空格,如 4 4 4 4-joker JOKER
输出描述:输出两手牌中较大的那手,不含连接符,扑克牌顺序不变,仍以空格隔开;如果不存在比较关系则输出ERROR
例:
输入:4 4 4 4-joker JOKER
输出:joker JOKER
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string line;
while (getline(cin, line)) {
// 王炸最大,直接输出
if (line.find("joker JOKER") != -1)
cout << "joker JOKER" << endl;
else {
int dash = line.find('-');
// 分开两手牌
string car1 = line.substr(0, dash);
string car2 = line.substr(dash + 1);
// 获取空格的次数,牌数为 c + 1
int c1 = count(car1.begin(), car1.end(), ' ');
int c2 = count(car2.begin(), car2.end(), ' ');
// 拿到第一张牌
string first1 = car1.substr(0, car1.find(' '));
string first2 = car2.substr(0, car2.find(' '));
string str = "345678910JQKA2jokerJOKER";
if (c1 == c2) {
// 只要牌数相等,则第一张牌大的即为大
if (str.find(first1) > str.find(first2))
cout << car1 << endl;
else
cout << car2 << endl;
}
else{
// 牌数不相同,说明类型不同 , 只有炸弹可以和其它牌比较
// 其它类型都是错误的
if (c1 == 3)
cout << car1 << endl;
else if (c2 == 3)
cout << car2 << endl;
else
cout << "ERROR" << endl;
}
}
}
}