问答题1:以下程序统计给定输入中每个大写字母的出现次数
void AlphabetCounting(char a[], int n) {
int count[26] = {}, i, kind = 0;
for (i = 0; i < n; ++i){
// pass 1
}
for (i = 0; i < 26; ++i) {
if (++kind > 1) putchar(';');
printf("%c=%d",'Z'-i,count[i]);
}
}
提示:第一个循环是一个计数,但是数组只能容纳26大小的字符,对于A-Z的ASCII码值过大,所以需要 Z-a[i] 进行计算.
答案:pass1 为: ++count['Z'-a[i]];
问答题2:请找出下面程序中有哪些错误?
int main(){
int i=10;
int j=1;
const int *p1;//(1)
int const *p2=&i; //(2)
p2=&j;//(3)
int *const p3=&i;//(4)
*p3=20;//(5)
*p2=30;//(6)
p3=&j;//(7)
return 0;
}
提示:const int * p1 = &i;
表示 p1 指向了 i 的地址,它的地址值不可改变,和 int const * p1 = &i
的意思一样,而 int * const p1 = &i;
的意思是指针 p1 的指向不可改变.
答案:(6),(7)
问答题3:假定有类AB,有相应的构造函数定义,能正确执行
AB a(4),b(5),c[3],*p[2]={&a,&b};语句,请问执行完此语句后共调用该类的构造函数次数为?
提示:a,b 为有参构造,c为三次的无参数构造,对于指针数组只是进行定义指向一个地址而已,并没有 new 出来一个对象,所以不进行内存的分配,因此没有发生构造.
问答题4:有如下程序,执行后输出的结果是?
#include
class cla{
public:
cla(){n++;}
~cla(){n--;}
static int get_n(){
return n;
}
private:
static int n;
};
int cla::n= 0;
int main(){
cla *p =new cla;
delete p;
cout<<"n="<<cla::get_n()<<endl;
return 0;
}
提示:对于指针没有new对象,那就不进行构造,所以n的值仍然为0
答案:n=0
问答题5:以下程序输出结果是?
class A{
public:
A ():m_iVal(0){
test();
}
virtual void func() {
std::cout<<m_iVal<<‘ ’;
}
void test(){
func();
}
public:
int m_iVal;
};
class B : public A{
public:
B(){
test();
}
virtual void func(){
++m_iVal;
std::cout<<m_iVal<<‘ ’;
}
};
int main(int argc ,char* argv[]){
A*p = new B;
p->test();
return 0;
}
提示:在 main 函数中,new 出一个B对象,先调用基类的构造函数,输出 m_iVal = 0;然后调用派生类的构造函数,里面有函数 test ,虽然B类中没有 test 函数,但是由于继承关系,类A中的 test 继承到B中,在 test 还有一个函数 fun,这时候会调用基类中的 fun 函数.
由于基类的指针p指向了子类对象,所以指针调用 test 会调用子类的 test,然后又会对 m_iVal ++ 操作,所以输出 2
答案:0 1 2
编程题1:汽水瓶
有这样一道智力题:“某商店规定:三个空汽水瓶可以换一瓶汽水
小张手上有十个空汽水瓶,她最多可以换5瓶汽水喝?
方法如下:先用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子。然后你让老板先借给你一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板。如果小张手上有n个空汽水瓶,最多可以换多少瓶汽水喝?
输入描述:输入文件最多包含10组测试数据,每个数据占一行,仅包含一个正整数 n(1<=n<=100),表示小张手上的空汽水瓶数。n=0表示输入结束,你的程序不应当处理这一行
输出描述:对于每组测试数据,输出一行,表示最多可以喝的汽水瓶数,如果一瓶也喝不到,输出 0
输入
3
10
81
0
输出
1
5
40
#include
#include
using namespace std;
int calculateNum(int num){
int sum = 0;
while (num > 1){
int result = num / 3;
int reminder = num % 3;
sum = sum + result;
num = result + reminder;
if (num == 2){
++sum;
break;
}
}
return sum;
}
int main(){
int n;
while(cin>>n){
cout<<calculateNum(n)<<endl;
}
return 0;
}
编程题2:查找两个字符串a,b中的最长公共子串
查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个
输入描述:输入两个字符串
输出描述:返回重复出现的字符
输入
a b c d e f g h i j k l m n o p
a b c s a f j k l m n o p q r s t u v w
输出
j k l m n o p
提示:动态规划
dp[i][j]
记录短字符串 s1 前 i 个字符和长字符串 s2 前 j 个字符的最长子串的长度,初始化所有值为 0
当 s1[i-1] == s2[j-1]
时,dp[i][j] = dp[i - 1][j - 1] + 1
,这里使用一个额外的值,start
来记录最长子串在短字符串 s1 中出现的起始位置,max
记录当前最长子串的长度
#include
#include
#include
using namespace std;
int main(){
string str1,str2;
while(cin>>str1>>str2){
if(str1.size()>str2.size()){
swap(str1,str2);
}
int max=0,start=0;
vector<vector<int>>dp(str1.size()+1,\
vector<int>(str2.size()+1,0));
for(int i = 1;i<str1.size()+1;++i){
for(int j = 1;j<str2.size()+1;++j){
if(str1[i-1]==str2[j-1]){
dp[i][j] = dp[i-1][j-1]+1;
}
if(dp[i][j]>max){
max = dp[i][j];
start = i-max;
}
}
}
cout<<str1.substr(start,max)<<endl;
}
return 0;
}
编程题3: 两种排序方法
考拉有n个字符串字符串,任意两个字符串长度都是不同的。考拉最近学习到有两种字符串的排序方法:
根据字符串的字典序排序
“car” < “carriage” < “cats” <"doggies < “koala”
据字符串的长度排序
“car” < “cats” < “koala” <“doggies” < “carriage”
考拉想知道自己的这些字符串排列顺序是否满足这两种排序方法,考拉要忙着吃树叶,所以需要你来帮忙验证
输入描述:输入第一行为字符串个数n(n ≤ 100)接下来的n行,每行一个字符串,字符串长度均小于100,均由小写字母组成
输出描述:如果这些字符串是根据字典序排列而不是根据长度排列输出"lexicographically"
,如果根据长度排列而不是字典序排列输出"lengths"
,如果两种方式都符合输出"both"
,否则输出"none"
例,输入 :3 a aa bbb 输出 :both
提示 把字符串放到容器 vector
#include
#include
using namespace std;
int main(){
int n;
while(cin>>n){
vector<string>v(n);
for(int i=0;i<n;++i){
cin>>v[i];
}
// 判断是否满足字典序
int dicsort = 1;
for(int i=1;i<n;++i){
if(v[i-1] > v[i]){
dicsort = 0;
break;
}
}
// 判断是否满足长度排序
int sizesort = 1;
for(int i=1;i<n;++i){
if(v[i-1].size() > v[i].size()){
sizesort = 0;
break;
}
}
if(dicsort==1 && sizesort==1){
cout<<"both"<<endl;
}
if(dicsort == 1 && sizesort ==0){
cout<<"lexicographically"<<endl;
}
if(sizesort == 1 && dicsort == 0){
cout<<"lengths"<<endl;
}
if (sizesort == 0 && dicsort ==0){
cout<<"none"<<endl;
}
}
return 0;
}
编程题4:求最小公倍数
正整数A和正整数B 的最小公倍数是指 能被A和B整除的最小的正整数值,设计一个算法,求输入A和B的最小公倍数
输入描述:输入两个正整数A和B
输出描述:输出A和B的最小公倍数
例:输入:5 7 输出:35
方法一:暴力法,找到比较大的那个数,然后一直进行 前置++操作,直到可以被两个数字整除为止
#include
using namespace std;
int main(){
int A;
int B;
cin>>A;
cin>>B;
if(A>B){
int temp = A;
A = B;
B = temp;
}
for(int i = B;i<=A*B;++i){
if(i%A==0 && i%B ==0){
cout<<i;
break;
}
}
return 0;
}
方法二:利用辗转相除法(循环),求出最大公约数,那么最小公倍数 == 两数积 / 最大公约数
例:15 和 20 ,他们的积为 300 ,他们最大公约数为 5 ,所以最小公倍数为 300/5 = 60
#include
using namespace std;
int gcd(int a, int b){
int r = 0;
while (r = a % b) {
a = b;
b = r;
}
return b;
}
int main(){
int a, b;
while (cin >> a >> b) {
cout << a * b / gcd(a, b) << endl;
}
return 0;
}
方法三:利用辗转相除法(递归)
#include
using namespace std;
int gcd(int a,int b){
if(b==0){
return a;
}
return gcd(b,a%b);
}
int main(){
int a,b;
while(cin>>a>>b){
cout<<a*b/gcd(a,b)<<endl;
}
return 0;
}