信大捷安的笔试题(c/c++)

一      请问运行Test函数会有什么样的结果?

NO1

void GetMemory(char *p)

{

p=(char *)malloc(100);

}

void Test()

{

char * str=NULL;

GetMemory(str);

strcpy(str,"Hello world");

printf(str);

}

实质:GetMemory(str)在调用时会生成一个_str与str指向同一个数,这是因为C语言中函数传递形参不改变实参的内容,但是指针指向的内容是相同的,因此可以用指针控制数据。题中的GetMemory(str),实质是对_str的操作,并没有对str操作,函数结束后_str撤销,因此不会产生新的内存空间,str仍然是一个空指针。

NO2

char *GetMemory()

{

char p[]="Hello World";

return p;

}

void Test()

{

char * str=NULL;

str=GetMemory();

printf(str);

}

实质:当一个函数调用结束后会释放内存空间,释放它所有变量所占用的空间,所以数组空间被释放掉了,也就是说str所指向的内容不确定是什么东西。但是返回的指针指向的地址是一定的。

NO3

char *GetMemory()

{

Return “hello world”;

}

void Test()

{

char * str=NULL;

str=GetMemory();

printf(str);

}

实质:本例打印hello world,因为返回常量区,而且并没有修改过。在上一个例子中不一定能打印hello world,因为指向的是栈区。

NO4

void GetMemory(char **p,int num)

{

*p=(char *)malloc(num);

}

void Test()

{

char * str=NULL;

GetMemory(&str,100);

strcpy(str,"Hello");

printf(str);

}

可以正确的打印Hello但是内存泄露了,在GetMemory()中使用了malloc申请内存,但是在最后却没有对申请的内存做任何处理,因此可能导致内存的泄露,非常危险。

NO5

void Test()

{

char *str=(char *)malloc(100);

strcpy(str,"Hello");

free(str);

if (str!=NULL)

{

strcpy(str,"World");

printf(str);

}

}

申请空间,拷贝字符串,释放空间,前三步操作都没有问题,到了if语句里的判断条件开始出错了。因为一个指针被释放了之后其内容并不是NULL,而是一个不确定的值,所以if语句永远不能被执行,这也是著名的“野”指针问题。

NO6

void GetMemory(void)

{

char *str=(char *)malloc(100);

strcpy(str,"hello");

free(str);

if (str !=NULL)

{

strcpy(str,"world");

printf(str);

}

}

Str 为野指针,打印的结果不能确定。

 

 

二  .猴子吃桃问题。猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第十天早上在想吃时,就只剩一个桃子了。求第一天共摘了多少个桃子?   写程序:

方法一:用的逆向思维,由后向前推

#include <stdio.h>
main()
 {
	int day,x1,x2; 
	day=9; 
	x2=1; 
	while(day>0) 
	{
		x1=(x2+1)*2;/*第一天的桃子数是第2天桃子数加1后的2倍*/ 
        x2=x1;
        day--; 
	} 
   printf("the total is %d\n",x1); 
}


 

方法二:用的回溯和递归

#include "stdio.h" 
int Chidiao(int day);
void main()
{
	printf("%d\n", Chidiao(1));//输出桃子总数
}

int Chidiao(int day)//计算第几天的桃子数目
{
   int x,n = day;
   if(n == 10)   //第10天的桃子数目
	   x = 1;
   else
	   x = (Chidiao(n+1)+1)*2;  //第一天的桃子数目等于第二天的数量加1乘2
  return x;/*递归返回桃子数*/
}

 

或者

 

int fun(int x){ 
if(x==10) 
return 1; 
else 
return ( fun(x+1)+1 ) * 2; 
} 

main() 
{ 
printf("%d\n",fun(1)); 
}


在网上看到了一个最简单的,天呐,真是没想到还有这么简单的方法,好吧,我实在太久没复习了(这题我首先想到的是递归):

 

#include <stdio.h>
int main() 
{ 
int i, n = 1; 
for(i = 1; i < 10; i++) 
n = (n + 1) * 2; 
printf("第1天的桃子个数是%d个\n", n); 
return 0; 
} 


 三.

老伯伯拿着鱼,带狗.猫过河到对岸. 有一条船. 只能坐一个人.老伯每次只能带一样动物过河. 当老伯不在的时侯

狗会咬猫.猫会吃鱼. 请问怎么顺序过河呢? 请写出流程图. 最好附上代码:

 

我只知道这个,但是写不出来代码:第一次带猫过去,然后回来,第二次带狗过去,把猫带回来,第三次,把鱼带过去,第四次把猫带去过

下面是在网上看到的代码,不是太理解:

#include<stdio.h>
 #define NUM 3
 
typedef enum {FALSE,TRUE}boolean;
 boolean Right[NUM]={TRUE,TRUE,TRUE};
 boolean Left[NUM]={FALSE,FALSE,FALSE};
 boolean ManRight=TRUE;
 char name[3][6]={"dog","cat","fish"};
 int step=1;
 int JustBringTo=-1;
 void Show(void);
 void ManToLeft(void);
 void ManToRight(void);
 boolean CheckIsOK(boolean);
 void main()
 {
 while(!(Left[0]&&Left[1]&&Left[2]))//终止条件是,所有动物都到左边了
{
  Show();  //显示当前左右边的动物
  if(ManRight)//判断人在左还是右?
  {
  ManToLeft();//人带动物从右到左
  }
else
 {
     ManToRight();//人回到右边,可带动物,也可不带
}
step++;
 }
  Show();
 }
 
void Show()
 {
 int i;
 printf("\nstep %d:",step);
 if(ManRight)
 {
 printf("Man is at Right!");
 }
 else
 {
 printf("Man is at Left!");
 }
 printf("\nRight animals:");
 for(i=0;i<NUM;i++)
 {
 if(Right[i])
 {
 printf("%s\t",name[i]);
 }
 }
 printf("\nLeft animals:");
 for(i=0;i<NUM;i++)
 {
 if(Left[i])
 {
 printf("%s\t",name[i]);
 }
 }
 }
 
boolean CheckIsOK(boolean flag)
 {
 if(flag)
 {
 if((Right[0]&&Right[1])||(Right[1]&&Right[2]))
 return FALSE;
 else
 return TRUE;
 }
 else
 {
 if((Left[0]&&Left[1])||(Left[1]&&Left[2]))
 return FALSE;
 else
 return TRUE;
 }
 }
 
void ManToLeft()
 {
 int i;
 for(i=0;i<NUM;i++)
 {
 if(Right[i]&&(i!=JustBringTo))
 {
 Right[i]=FALSE;
 if(CheckIsOK(TRUE))
 {
 Left[i]=TRUE;
 ManRight=FALSE;
 JustBringTo=i;
 break;
 }
 else
 {
 Right[i]=TRUE;
 }
 }
 }
 }
 
void ManToRight()
 {
 int i;
 if(CheckIsOK(FALSE))
 {
 ManRight=TRUE;
 JustBringTo=-1;
 return;
 }
 for(i=0;i<NUM;i++)
 {
 if(Left[i]&&(i!=JustBringTo))
 {
 Left[i]=FALSE;
 if(CheckIsOK(FALSE))
 {
 Right[i]=TRUE;
             ManRight=TRUE;
 JustBringTo=i;
 break;
 }
 else
 {
 Left[i]=TRUE;
 }
 }
 }
}

 

还有这个:

 

#include <iostream>
 #include <string>
 using namespace std;
 
enum {
 DOG=0,
 CAT,
 FISH
 };
 
int preference[3]= {0, 0, 0};
 

void InitArray(short (*a)[3]){
 for(int ix=0; ix<3; ix++)
 for(int iy=0; iy<3; iy++){
 *(*(a+ix)+iy)= ((ix==1) || (iy==1)) ? 1 : 0;
 }
 a[1][1]=0;
 }
 
bool clash(short *p, short (*a)[3]){
 int x=0, y=0, time =0;
 for(int ix=0; ix<3; ix++){
 if(p[ix]){
 time++;
 ((time==1) ? x : y )=  ix;
 }
 }
 if(time==1)
 return false;
 else
 return (a[x][y] ) ? true : false;
 }
 

void print(short *i, short *b){
 string name[3]={"dog", "cat", "fish"};
 
for(int ix=0; ix<3; ix++){
 cout<<(i[ix] ? name[ix] : "   ")
 <<"\t --------- ---------\t"
 <<(b[ix] ? name[ix] : "   ")<<endl;
 }
 cout<<endl;
 }
 

int findfirst(short *p){
 int result=0, first=100;
 for(int ix=0; ix<3; ix++){
 if(p[ix]){
 if(first==100){
 first = preference[ix];
 result = ix;
 }
 else if(first > preference[ix]){ 
 first = preference[ix];
 result = ix;
 }
 }
 }
 return result;
 }
 




bool solve(short *i, short *b, short (*a)[3]){
 bool loc = true;
 while(i[0] || i[1] || i[2]){
 if(loc){
 int ix= findfirst(i);
 if(i[ix]){
 i[ix]=0, b[ix]=1;
 preference[ix]++;
 if(clash(i, a)){
 i[ix]=1, b[ix]=0;
 }else{
 loc=false;
 print(i,b);
 }
 }
 }
 else{
 int ix= findfirst(b);
 if(b[ix]){
 if(clash(b, a)){
 preference[ix]++;
 b[ix]=0, i[ix]=1;
 }else{
 loc=true;
 }
 }
 }
 }
 return true;
 }
 

int main(){
 short relate[3][3];  //relate talbe
 short init_relate[3]={1, 1, 1}; 
 short bank_relate[3]={0, 0, 0};
 

InitArray(relate);  //initial matrix

 solve(init_relate, bank_relate, relate);
 
cout<<"ok!"<<endl;
 
return 0;
 }

 


1~50 号运动员按顺序排成一排。
教练下令:“单数运动员出列!”剩下的运动员重新排队编号。教练又下令:“单数运动员出列!”如此下去,最后只剩下一个人,他是几号运动员?
如果教练下的令是“双数运动员出列!”最后剩下的又是谁?

只写出来答案,前者是32,后者是1,但是写不出来代码(实在是太生疏了)

下面这个是在http://bbs.csdn.net/topics/390938446?page=1#post-398570839上看到的:

用的递归:

#include<stdio.h>
int fun(int *p ,int nNum)
{
    if (nNum > 1)
    {
        int i = 0;       // 双数出列的话,改为 1
        for (; i < nNum/2; i++)
        {
            p[i] = p[2*i+1];    // 双数出列的话改为 p[i] = p[2*i];
        }
        fun(p ,i);
    }
    return p[0];
}
 
int main(int argc, char* argv[])
{
    int n[50] = {0};    
    for (int i = 0; i != 50; i++)
    {
        n[i] = i + 1;    // 初始化为1~49
    }
    printf("最后剩下第 %d 号\n" ,fun(n,50));
    return 0;
}

还有这个:

#include <stdio.h>
#define SIZE 50
 
int main() {
    int ath[SIZE] = {0};
    int odd, i;
    int flag;
    int count = SIZE;
    printf("请选择:0-单数出列\t1-双数出列");
    scanf("%d", &odd);
     
    while(count >= 1) {
        flag = 0;
        for(i=0; i<SIZE; i++){
            if(ath[i] == 0){
                if(count == 1) {
                    printf("最后剩下的是%d\n", i + 1);
                    return 0;
                }
                if(flag == odd){
                    ath[i] = 1;
                    count--;
                } 
                flag = 1 - flag;
            }
        }
    }
    return 0;
}

和:

#include <stdio.h>
#include <math.h>
 
int main() {
    int n, odd;
    printf("请输入运动员人数:");
    scanf("%d", &n);
    printf("请选择:0-单数出列\t1-双数出列");
    scanf("%d", &odd);
    switch(odd){
    case 0: printf("最后剩下的是%d\n", (int)(pow(2, (int)(log(n)/log(2))))); break;
    case 1: printf("最后剩下的是1\n"); break;
    }
    return 0;
}


 

老师让6名学生围坐成一圈,另让一名学生坐在中央,并拿出七顶帽子,其中四顶白色,三顶黑色。然后蒙住七名学生的眼睛,并给坐在中央的学生戴一顶帽子,而只解开坐在圈上的六名学生的眼罩。这时,由于坐在中央的学生的阻挡,每个人只能看到五个人的帽子。老师说:“现在,你们七人猜一猜自己的头上戴的帽子颜色。”大家静静地思索了好大一会。最后,坐在中央的、被蒙住双眼的学生举手说:“我猜到了。”请问:中央的被蒙住双眼的学生带的是什么颜色的帽子?他是怎样猜到的?

 他戴的是白色的帽子。
因为周围的人迟迟不能回答,说明他们都不能判定自己戴的是什么颜色的帽子,换句话说,他们看到的五顶帽子的颜色必然是三白二黑,(看到四顶白帽或三顶黑帽都能立即判断出自己戴的是什么颜色的帽子)所以坐在周围的人一定是有一半戴着白帽,一半戴着黑帽,而且是黑白相对地坐着的,这样无论自己戴的是白帽还是黑帽看到的情况才会一致。而最后一顶白帽,就必然戴在了中间那个人的头上。(可以推测出每一个人和对面的人(就是他看不到的那个)帽子颜色不同,所以一圈六人必然是三白三黑,于是中央的人就能猜出他是白色。)

 

 


 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值