C语言面试题3

时间:2023-01-23 15:23:30

编程题

1、读文件file1.txt的内容(例如):

123456

输出到file2.txt:

563412

#include <stdio.h>
#include <stdlib.h> int main(void)
{
int MAX = ;
int *a = (int *)malloc(MAX * sizeof(int));
int *b; FILE *fp1;
FILE *fp2;
fp1 = fopen("a.txt","r");
if(fp1 == NULL)
{
printf("error1");
exit(-);
} fp2 = fopen("b.txt","w");
if(fp2 == NULL)
{
printf("error2");
exit(-);
} int i = ;
int j = ;
while(fscanf(fp1,"%d",&a[i]) != EOF)
{
i++;j++;
if(i >= MAX)
{
MAX = * MAX;
b = (int*)realloc(a,MAX * sizeof(int));
if(b == NULL)
{
printf("error3");
      exit(-);
       }
      a = b;
     }
   } for(;--j >= ;)
fprintf(fp2,"%d\n",a[j]); fclose(fp1);
fclose(fp2);
return ;
}

对1的另一种做法:

 #include <stdio.h>
void test(FILE *fread, FILE *fwrite)
{
char buf[] = {};
if (!fgets(buf, sizeof(buf), fread))
return;
test( fread, fwrite );
fputs(buf, fwrite);
}
int main(int argc, char *argv[])
{
FILE *fr = NULL;
FILE *fw = NULL;
fr = fopen("data", "rb");
fw = fopen("dataout", "wb");
test(fr, fw);
fclose(fr);
fclose(fw);
return ;
}

2、输出和为一个给定整数的所有组合

例如n=5

5=1+4;5=2+3(相加的数不能重复)

则输出

1,4;2,3。

 #include <stdio.h>
int main(void)
{
unsigned long int i,j,k;
printf("please input the number\n");
scanf("%d",&i);
if( i % == )
j = i / ;
  else
   j = i / + ;
printf("The result is \n");
for(k = ; k < j; k++)
printf("%d = %d + %d\n",i,k,i - k); return ;
}

 #include <stdio.h>
void main()
{
unsigned long int a,i=;
scanf("%d",&a);
if(a%==)
{
for(i=;i<a/;i++)
printf("%d",a,a-i);
}
else
for(i=;i<=a/;i++)
printf(" %d, %d",i,a-i);
}

3、递规反向输出字符串的例子,可谓是反序的经典例程.

void inverse(char *p)
{
if( *p = = '\0' )
return;
inverse( p+ );
printf( "%c", *p );
} int main(int argc, char *argv[])
{
inverse("abc\0");
return ;
}

4、写一段程序,找出数组中第k大小的数,输出数所在的位置。例如{2,4,3,4,7}中,第一大的数是7,位置在4。第二大、第三大的数都是4,位置在1、3随便输出哪一个均可。函数接口为:int find_orderk(const int* narry,const int n,const int k)

要求算法复杂度不能是O(n^2)

谢谢!

可以先用快速排序进行排序,其中用另外一个进行地址查找

代码如下,在VC++6.0运行通过。给分吧^-^

 //快速排序 

 #include<iostream>
usingnamespacestd; intPartition (int*L,intlow,int high) { inttemp = L[low]; intpt = L[low]; while (low < high) { while (low < high && L[high] >= pt) --high; L[low] = L[high]; while (low < high && L[low] <= pt) ++low; L[low] = temp; } L[low] = temp; returnlow; } voidQSort (int*L,intlow,int high) { if (low < high) { intpl = Partition (L,low,high); QSort (L,low,pl - ); QSort (L,pl + ,high); } } intmain () { intnarry[],addr[]; intsum = ,t; cout << "Input number:" << endl; cin >> t; while (t != -) { narry[sum] = t; addr[sum - ] = t; sum++; cin >> t; } sum -= ; QSort (narry,,sum); for (int i = ; i <= sum;i++) cout << narry[i] << '\t'; cout << endl; intk; cout << "Please input place you want:" << endl; cin >> k; intaa = ; intkk = ; for (;;) { if (aa == k) break; if (narry[kk] != narry[kk + ]) { aa += ; kk++; } } cout << "The NO." << k << "number is:" << narry[sum - kk] << endl; cout << "And it's place is:" ; for (i = ;i < sum;i++) { if (addr[i] == narry[sum - kk]) cout << i << '\t'; } return0; }

5、两路归并排序

 Linklist *unio(Linklist *p,Linklist *q){

 linklist *R,*pa,*qa,*ra;

 pa=p;

 qa=q;

 R=ra=p;

 while(pa->next!=NULL&&qa->next!=NULL){

 if(pa->data>qa->data){

 ra->next=qa;

 qa=qa->next;

 }

 else{

 ra->next=pa;

 pa=pa->next;

 }

 }

 if(pa->next!=NULL)

 ra->next=pa;

 if(qa->next!=NULL)

 ra->next==qa;

 return R;

 }

6、用递归算法判断数组a[N]是否为一个递增数组。

递归的方法,记录当前最大的,并且判断当前的是否比这个还大,大则继续,否则返回false结束:

 bool fun( int a[], int n )

 {

 if( n= = )

 return true;

 if( n= = )

 return a[n-] >= a[n-];

 return fun( a,n-) && ( a[n-] >= a[n-] );

 }

7、单连表的建立,把'a'--'z'26个字母插入到连表中,并且倒叙,还要打印!

方法1:

typedef struct val

{   int date_1;

struct val *next;

}*p;

void main(void)

{   char c;

for(c=122;c>=97;c--)

{ p.date=c;

p=p->next;

}

p.next=NULL;

}

}

方法2:

node *p = NULL;

node *q = NULL;

node *head = (node*)malloc(sizeof(node));

head->data = ' ';head->next=NULL;

node *first = (node*)malloc(sizeof(node));

first->data = 'a';first->next=NULL;head->next = first;

p = first;

int longth = 'z' - 'b';

int i=0;

while ( i<=longth )

{

node *temp = (node*)malloc(sizeof(node));

temp->data = 'b'+i;temp->next=NULL;q=temp;

head->next = temp; temp->next=p;p=q;

i++;

}

print(head);

8、请列举一个软件中时间换空间或者空间换时间的例子。

void swap(int a,int b)

{

int c; c=a;a=b;b=a;

}

--->空优

void swap(int a,int b)

{

a=a+b;b=a-b;a=a-b;

}

9、outputstr所指的值为123456789

int continumax(char *outputstr, char *inputstr)

{

char *in = inputstr, *out = outputstr, *temp, *final;

int count = 0, maxlen = 0;

while( *in != '\0' )

{

if( *in > 47 && *in < 58 )

{

for(temp = in; *in > 47 && *in < 58 ; in++ )

count++;

}

else

in++;

if( maxlen < count )

{

maxlen = count;

count = 0;

final = temp;

}

}

for(int i = 0; i < maxlen; i++)

{

*out = *final;

out++;

final++;

}

*out = '\0';

return maxlen;

}

10、不用库函数,用C语言实现将一整型数字转化为字符串

方法1:

int getlen(char *s){

int n;

for(n = 0; *s != '\0'; s++)

n++;

return n;

}

void reverse(char s[])

{

int c,i,j;

for(i = 0,j = getlen(s) - 1; i < j; i++,j--){

c = s[i];

s[i] = s[j];

s[j] = c;

}

}

void itoa(int n,char s[])

{

int i,sign;

if((sign = n) < 0)

n = -n;

i = 0;

do{/*以反序生成数字*/

s[i++] = n%10 + '0';/*get next number*/

}while((n /= 10) > 0);/*delete the number*/

if(sign < 0)

s[i++] = '-';

s[i] = '\0';

reverse(s);

}

方法2:

#include <iostream>

using namespace std;

void itochar(int num);

void itochar(int num)

{

int i = 0;

int j ;

char stra[10];

char strb[10];

while ( num )

{

stra[i++]=num%10+48;

num=num/10;

}

stra[i] = '\0';

for( j=0; j < i; j++)

{

strb[j] = stra[i-j-1];

}

strb[j] = '\0';

cout<<strb<<endl;

}

int main()

{

int num;

cin>>num;

itochar(num);

return 0;

}

11、求组合数: 求n个数(1....n)中k个数的组合....

如:combination(5,3)

要求输出:543,542,541,532,531,521,432,431,421,321,

#include<stdio.h>

int pop(int *);

int push(int );

void combination(int ,int );

int stack[3]={0};

top=-1;

int main()

{

int n,m;

printf("Input two numbers:\n");

while( (2!=scanf("%d%*c%d",&n,&m)) )

{

fflush(stdin);

printf("Input error! Again:\n");

}

combination(n,m);

printf("\n");

}

void combination(int m,int n)

{

int temp=m;

push(temp);

while(1)

{

if(1==temp)

{

if(pop(&temp)&&stack[0]==n) //当栈底元素弹出&&为可能取的最小值,循环退出

break;

}

else if( push(--temp))

{

printf("%d%d%d  ",stack[0],stack[1],stack[2]);//§&auml;¨ì¤@?

pop(&temp);

}

}

}

int push(int i)

{

stack[++top]=i;

if(top<2)

return 0;

else

return 1;

}

int pop(int *i)

{

*i=stack[top--];

if(top>=0)

return 0;

else

return 1;

}

12、用指针的方法,将字符串“ABCD1234efgh”前后对调显示

#include <stdio.h>

#include <string.h>

#include <dos.h>

int main()

{

char str[] = "ABCD1234efgh";

int length = strlen(str);

char * p1 = str;

char * p2 = str + length - 1;

while(p1 < p2)

{

char c = *p1;

*p1 = *p2;

*p2 = c;

++p1;

--p2;

}

printf("str now is %s\n",str);

system("pause");

return 0;

}

13、有一分数序列:1/2,1/4,1/6,1/8……,用函数调用的方法,求此数列前20项的和

#include <stdio.h>

double getValue()

{

double result = 0;

int i = 2;

while(i < 42)

{

result += 1.0 / i;//一定要使用1.0做除数,不能用1,否则结果将自动转化成整数,即0.000000

i += 2;

}

return result;

}

int main()

{

printf("result is %f\n", getValue());

system("pause");

return 0;

}

14、有一个数组a[1000]存放0--1000;要求每隔二个数删掉一个数,到末尾时循环至开头继续进行,求最后一个被删掉的数的原始下标位置。

以7个数为例:

{0,1,2,3,4,5,6,7} 0-->1-->2(删除)-->3-->4-->5(删除)-->6-->7-->0(删除),如此循环直到最后一个数被删除。

方法1:数组

#include <iostream>

using namespace std;

#define null 1000

int main()

{

int arr[1000];

for (int i=0;i<1000;++i)

arr[i]=i;

int j=0;

int count=0;

while(count<999)

{

while(arr[j%1000]==null)

j=(++j)%1000;

j=(++j)%1000;

while(arr[j%1000]==null)

j=(++j)%1000;

j=(++j)%1000;

while(arr[j%1000]==null)

j=(++j)%1000;

arr[j]=null;

++count;

}

while(arr[j]==null)

j=(++j)%1000;

cout<<j<<endl;

return 0;

}方法2:链表

#include<iostream>

using namespace std;

#define null 0

struct node

{

int data;

node* next;

};

int main()

{

node* head=new node;

head->data=0;

head->next=null;

node* p=head;

for(int i=1;i<1000;i++)

{

node* tmp=new node;

tmp->data=i;

tmp->next=null;

head->next=tmp;

head=head->next;

}

head->next=p;

while(p!=p->next)

{

p->next->next=p->next->next->next;

p=p->next->next;

}

cout<<p->data;

return 0;

}

方法3:通用算法

#include <stdio.h>

#define MAXLINE 1000   //元素个数

/*

MAXLINE   元素个数

a[]       元素数组

R[]       指针场

suffix    下标

index     返回最后的下标序号

values    返回最后的下标对应的值

start     从第几个开始

K         间隔

*/

int find_n(int a[],int R[],int K,int& index,int& values,int s=0) {

int suffix;

int front_node,current_node;

suffix=0;

if(s==0) {

current_node=0;

front_node=MAXLINE-1;

}

else {

current_node=s;

front_node=s-1;

}

while(R[front_node]!=front_node) {

printf("%d\n",a[current_node]);

R[front_node]=R[current_node];

if(K==1) {

current_node=R[front_node];

continue;

}

for(int i=0;i<K;i++){

front_node=R[front_node];

}

current_node=R[front_node];

}

index=front_node;

values=a[front_node];

return 0;

}

int main(void) {

int a[MAXLINE],R[MAXLINE],suffix,index,values,start,i,K;

suffix=index=values=start=0;

K=2;

for(i=0;i<MAXLINE;i++) {

a[i]=i;

R[i]=i+1;

}

R[i-1]=0;

find_n(a,R,K,index,values,2);

printf("the value is %d,%d\n",index,values);

return 0;

}

15、实现strcmp

int StrCmp(const char *str1, const char *str2)

做是做对了,没有抄搞,比较乱

int StrCmp(const char *str1, const char *str2)

{

assert(str1 && srt2);

while (*str1 && *str2 && *str1 == *str2) {

str1++, str2++;

}

if (*str1 && *str2)

return (*str1-*str2);

elseif (*str1 && *str2==0)

return 1;

elseif (*str1 = = 0 && *str2)

return -1;

else

return 0;

}

int StrCmp(const char *str1, const char *str2)

{

//省略判断空指针(自己保证)

while(*str1 && *str1++ = = *str2++);

return *str1-*str2;

}

16、实现子串定位

int FindSubStr(const char *MainStr, const char *SubStr)

做是做对了,没有抄搞,比较乱

int MyStrstr(const char* MainStr, const char* SubStr)

{

const char *p;

const char *q;

const char * u = MainStr;

//assert((MainStr!=NULL)&&( SubStr!=NULL));//用断言对输入进行判断

while(*MainStr) //内部进行递增

{

p = MainStr;

q = SubStr;

while(*q && *p && *p++ == *q++);

if(!*q )

{

return MainStr - u +1 ;//MainStr指向当前起始位,u指向

}

MainStr ++;

}

return -1;

}

17、已知一个单向链表的头,请写出删除其某一个结点的算法,要求,先找到此结点,然后删除。

slnodetype *Delete(slnodetype *Head,int key){}中if(Head->number==key)

{

Head=Pointer->next;

free(Pointer);

break;

}

Back = Pointer;

Pointer=Pointer->next;

if(Pointer->number==key)

{

Back->next=Pointer->next;

free(Pointer);

break;

}

void delete(Node* p)

{

if(Head = Node)

while(p)

}

18、有1,2,....一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度O(1),使用交换,而且一次只能交换两个数.(华为)

#include<iostream.h>

int main()

{

int a[]  = {10,6,9,5,2,8,4,7,1,3};

int len = sizeof(a) / sizeof(int);

int temp;

for(int i = 0; i < len; )

{

temp = a[a[i] - 1];

a[a[i] - 1] = a[i];

a[i] = temp;

if ( a[i] == i + 1)

i++;

}

for (int j = 0; j < len; j++)

cout<<a[j]<<",";

return 0;

}

19、写出程序把一个链表中的接点顺序倒排

typedef struct linknode

{

int data;

struct linknode *next;

}node;

//将一个链表逆置

node *reverse(node *head)

{

node *p,*q,*r;

p=head;

q=p->next;

while(q!=NULL)

{

r=q->next;

q->next=p;

p=q;

q=r;

}

head->next=NULL;

head=p;

return head;

}

20、写出程序删除链表中的所有接点

void del_all(node *head)

{

node *p;

while(head!=NULL)

{

p=head->next;

free(head);

head=p;

}

cout<<"释放空间成功!"<<endl;

}

21、两个字符串,s,t;把t字符串插入到s字符串中,s字符串有足够的空间存放t字符串

void insert(char *s, char *t, int i)

{

char *q = t;

char *p =s;

if(q == NULL)return;

while(*p!='\0')

{

p++;

}

while(*q!=0)

{

*p=*q;

p++;

q++;

}

*p = '\0';

}

22、写一个函数,功能:完成内存之间的拷贝

memcpy source code:

270 void* memcpy( void *dst, const void *src, unsigned int len )

271 {

272    register char *d;

273    register char *s;

27

275    if (len == 0)

276       return dst;

277

278    if (is_overlap(dst, src, len, len))

279       complain3("memcpy", dst, src, len);

280

281    if ( dst > src ) {

282       d = (char *)dst + len - 1;

283       s = (char *)src + len - 1;

284       while ( len >= 4 ) {

285          *d-- = *s--;

286          *d-- = *s--;

287          *d-- = *s--;

288          *d-- = *s--;

289          len -= 4;

290       }

291       while ( len-- ) {

292          *d-- = *s--;

293       }

294    } else if ( dst < src ) {

295       d = (char *)dst;

296       s = (char *)src;

297       while ( len >= 4 ) {

298          *d++ = *s++;

299          *d++ = *s++;

300          *d++ = *s++;

301          *d++ = *s++;

302          len -= 4;

303       }

304       while ( len-- ) {

305          *d++ = *s++;

306       }

307    }

308    return dst;

309 }

23、公司考试这种题目主要考你编写的代码是否考虑到各种情况,是否安全(不会溢出)

各种情况包括:

1、参数是指针,检查指针是否有效

2、检查复制的源目标和目的地是否为同一个,若为同一个,则直接跳出

3、读写权限检查

4、安全检查,是否会溢出

memcpy拷贝一块内存,内存的大小你告诉它

strcpy是字符串拷贝,遇到'\0'结束

/* memcpy ─── 拷贝不重叠的内存块 */

void memcpy(void* pvTo, void* pvFrom, size_t size)

{

void* pbTo = (byte*)pvTo;

void* pbFrom = (byte*)pvFrom;

ASSERT(pvTo != NULL && pvFrom != NULL); //检查输入指针的有效性

ASSERT(pbTo>=pbFrom+size || pbFrom>=pbTo+size);//检查两个指针指向的内存是否重叠

while(size-->0)

*pbTo++ == *pbFrom++;

return(pvTo);

}

24、两个字符串,s,t;把t字符串插入到s字符串中,s字符串有足够的空间存放t字符串

void insert(char *s, char *t, int i)

{

memcpy(&s[strlen(t)+i],&s[i],strlen(s)-i);

memcpy(&s[i],t,strlen(t));

s[strlen(s)+strlen(t)]='\0';

}

25、编写一个 C 函数,该函数在一个字符串中找到可能的最长的子字符串,且该字符串是由同一字符组成的。

char * search(char *cpSource, char ch)

{

char *cpTemp=NULL, *cpDest=NULL;

int iTemp, iCount=0;

while(*cpSource)

{

if(*cpSource == ch)

{

iTemp = 0;

cpTemp = cpSource;

while(*cpSource == ch)

++iTemp, ++cpSource;

if(iTemp > iCount)

iCount = iTemp, cpDest = cpTemp;

if(!*cpSource)

break;

}

++cpSource;

}

return cpDest;

}

26、请编写一个 C 函数,该函数在给定的内存区域搜索给定的字符,并返回该字符所在位置索引值。

int search(char *cpSource, int n, char ch)

{

int i;

for(i=0; i<n && *(cpSource+i) != ch; ++i);

return i;

}

27、给定字符串A和B,输出A和B中的最大公共子串。

比如A="aocdfe" B="pmcdfa" 则输出"cdf"

*/

//Author: azhen

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

char *commanstring(char shortstring[], char longstring[])

{

int i, j;

char *substring=malloc(256);

if(strstr(longstring, shortstring)!=NULL)              //如果……,那么返回shortstring

return shortstring;

for(i=strlen(shortstring)-1;i>0; i--)                 //否则,开始循环计算

{

for(j=0; j<=strlen(shortstring)-i; j++){

memcpy(substring, &shortstring[j], i);

substring[i]='\0';

if(strstr(longstring, substring)!=NULL)

return substring;

}

}

return NULL;

}

main()

{

char *str1=malloc(256);

char *str2=malloc(256);

char *comman=NULL;

gets(str1);

gets(str2);

if(strlen(str1)>strlen(str2))                         //将短的字符串放前面

comman=commanstring(str2, str1);

else

comman=commanstring(str1, str2);

printf("the longest comman string is: %s\n", comman);

}

28、写一个函数比较两个字符串str1和str2的大小,若相等返回0,若str1大于

str2返回1,若str1小于str2返回-1

int strcmp ( const char * src,const char * dst)

{

int ret = 0 ;

while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)

{

++src;

++dst;

}

if ( ret < 0 )

ret = -1 ;

else if ( ret > 0 )

ret = 1 ;

return( ret );

}

29、求1000!的未尾有几个0(用素数相乘的方法来做,如72=2*2*2*3*3);

求出1->1000里,能被5整除的数的个数n1,能被25整除的数的个数n2,能被125整除的数的个数n3,

能被625整除的数的个数n4.

1000!末尾的零的个数=n1+n2+n3+n4;

#include<stdio.h>

#define NUM 1000

int find5(int num){

int ret=0;

while(num%5==0){

num/=5;

ret++;

}

return ret;

}

int main(){

int result=0;

int i;

for(i=5;i<=NUM;i+=5)

{

result+=find5(i);

}

printf(" the total zero number is %d\n",result);

return 0;

}

30、有双向循环链表结点定义为:

struct node

{ int data;

struct node *front,*next;

};

有两个双向循环链表A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两链表中data值相同的结点删除

BOOL DeteleNode(Node *pHeader, DataType Value)

{

if (pHeader == NULL) return;

BOOL bRet = FALSE;

Node *pNode = pHead;

while (pNode != NULL)

{

if (pNode->data == Value)

{

if (pNode->front == NULL)

{

pHeader = pNode->next;

pHeader->front = NULL;

}

else

{

if (pNode->next != NULL)

{

pNode->next->front = pNode->front;

}

pNode->front->next = pNode->next;

}

Node *pNextNode = pNode->next;

delete pNode;

pNode = pNextNode;

bRet = TRUE;

//不要break或return, 删除所有

}

else

{

pNode = pNode->next;

}

}

return bRet;

}

void DE(Node *pHeadA, Node *pHeadB)

{

if (pHeadA == NULL || pHeadB == NULL)

{

return;

}

Node *pNode = pHeadA;

while (pNode != NULL)

{

if (DeteleNode(pHeadB, pNode->data))

{

if (pNode->front == NULL)

{

pHeadA = pNode->next;

pHeadA->front = NULL;

}

else

{

pNode->front->next = pNode->next;

if (pNode->next != NULL)

{

pNode->next->front = pNode->front;

}

}

Node *pNextNode = pNode->next;

delete pNode;

pNode = pNextNode;

}

else

{

pNode = pNode->next;

}

}

}

31、编程实现:找出两个字符串中最大公共子字符串,如"abccade","dgcadde"的最大子串为"cad"

int GetCommon(char *s1, char *s2, char **r1, char **r2)

{

int len1 = strlen(s1);

int len2 = strlen(s2);

int maxlen = 0;

for(int i = 0; i < len1; i++)

{

for(int j = 0; j < len2; j++)

{

if(s1[i] == s2[j])

{

int as = i, bs = j, count = 1;

while(as + 1 < len1 && bs + 1 < len2 && s1[++as] == s2[++bs])

count++;

if(count > maxlen)

{

maxlen = count;

*r1 = s1 + i;

*r2 = s2 + j;

}

}

}

}

32、编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列库函数

char* test3(long num) {

char* buffer = (char*)malloc(11);

buffer[0] = '0';

buffer[1] = 'x';

buffer[10] = '\0';

char* temp = buffer + 2;

for (int i=0; i < 8; i++) {

temp[i] = (char)(num<<4*i>>28);

temp[i] = temp[i] >= 0 ? temp[i] : temp[i] + 16;

temp[i] = temp[i] < 10 ? temp[i] + 48 : temp[i] + 55;

}

return buffer;

}

33、输入N, 打印 N*N 矩阵

比如 N = 3,打印:

1  2  3

8  9  4

7  6  5

N = 4,打印:

1   2   3   4

12  13  14  5

11  16  15  6

10  9   8   7

解答:

1 #define N 15

int s[N][N];

void main()

{

int k = 0, i = 0, j = 0;

int a = 1;

for( ; k < (N+1)/2; k++ )

{

while( j < N-k ) s[i][j++] = a++; i++; j--;

while( i < N-k ) s[i++][j] = a++; i--; j--;

while( j > k-1 ) s[i][j--] = a++; i--; j++;

while( i > k )   s[i--][j] = a++; i++; j++;

}

for( i = 0; i < N; i++ )

{

for( j = 0; j < N; j++ )

cout << s[i][j] << '\t';

cout << endl;

}

}

2 define MAX_N  100

int matrix[MAX_N][MAX_N];

/*

*(x,y):第一个元素的坐标

* start:第一个元素的值

* n:矩阵的大小

*/

void SetMatrix(int x, int y, int start, int n) {

int i, j;

if (n <= 0)    //递归结束条件

return;

if (n == 1) {  //矩阵大小为1时

matrix[x][y] = start;

return;

}

for (i = x; i < x + n-1; i++)   //矩阵上部

matrix[y][i] = start++;

for (j = y; j < y + n-1; j++)   //右部

matrix[j][x+n-1] = start++;

for (i = x+n-1; i > x; i--)     //底部

matrix[y+n-1][i] = start++;

for (j = y+n-1; j > y; j--)     //左部

matrix[j][x] = start++;

SetMatrix(x+1, y+1, start, n-2);   //递归

}

void main() {

int i, j;

int n;

scanf("%d", &n);

SetMatrix(0, 0, 1, n);

//打印螺旋矩阵

for(i = 0; i < n; i++) {

for (j = 0; j < n; j++)

printf("%4d", matrix[i][j]);

printf("\n");

}

}

34、斐波拉契数列递归实现的方法如下:

int  Funct( int n )

{

if(n==0) return 1;

if(n==1) return 1;

retrurn  Funct(n-1) + Funct(n-2);

}

请问,如何不使用递归,来实现上述函数?

请教各位高手!

解答:int  Funct( int n )  //  n 为非负整数

{

int a=0;

int b=1;

int c;

if(n==0) c=1;

else if(n==1) c=1;

else for(int i=2;i<=n;i++)  //应该n从2开始算起

{

c=a+b;

a=b;

b=c;

}

return c;

}

解答:

现在大多数系统都是将低字位放在前面,而结构体中位域的申明一般是先声明高位。

100  的二进制是 001 100 100

低位在前   高位在后

001----s3

100----s2

100----s1

所以结果应该是 1

如果先申明的在低位则:

001----s1

100----s2

100----s3

结果是 4

1、原题跟little-endian,big-endian没有关系

2、原题跟位域的存储空间分配有关,到底是从低字节分配还是从高字节分配,从Dev C++和VC7.1上看,都是从低字节开始分配,并且连续分配,中间不空,不像谭的书那样会留空位

3、原题跟编译器有关,编译器在未用堆栈空间的默认值分配上有所不同,Dev C++未用空间分配为

01110111b,VC7.1下为11001100b,所以在Dev C++下的结果为5,在VC7.1下为1。

注:PC一般采用little-endian,即高高低低,但在网络传输上,一般采用big-endian,即高低低高,华为是做网络的,所以可能考虑big-endian模式,这样输出结果可能为4

35、判断一个字符串是不是回文

int IsReverseStr(char *aStr)

{

int i,j;

int found=1;

if(aStr==NULL)

return -1;

j=strlen(aStr);

for(i=0;i<j/2;i++)

if(*(aStr+i)!=*(aStr+j-i-1))

{

found=0;

break;

}

return found;

}

36、Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

数组实现:

#include <stdio.h>

#include <malloc.h>

int Josephu(int n, int m)

{

int flag, i, j = 0;

int *arr = (int *)malloc(n * sizeof(int));

for (i = 0; i < n; ++i)

arr[i] = 1;

for (i = 1; i < n; ++i)

{

flag = 0;

while (flag < m)

{

if (j == n)

j = 0;

if (arr[j])

++flag;

++j;

}

arr[j - 1] = 0;

printf("第%4d个出局的人是:%4d号\n", i, j);

}

free(arr);

return j;

}

int main()

{

int n, m;

scanf("%d%d", &n, &m);

printf("最后胜利的是%d号!\n", Josephu(n, m));

system("pause");

return 0;

}

链表实现:

#include <stdio.h>

#include <malloc.h>

typedef struct Node

{

int index;

struct Node *next;

}JosephuNode;

int Josephu(int n, int m)

{

int i, j;

JosephuNode *head, *tail;

head = tail = (JosephuNode *)malloc(sizeof(JosephuNode));

for (i = 1; i < n; ++i)

{

tail->index = i;

tail->next = (JosephuNode *)malloc(sizeof(JosephuNode));

tail = tail->next;

}

tail->index = i;

tail->next = head;

for (i = 1; tail != head; ++i)

{

for (j = 1; j < m; ++j)

{

tail = head;

head = head->next;

}

tail->next = head->next;

printf("第%4d个出局的人是:%4d号\n", i, head->index);

free(head);

head = tail->next;

}

i = head->index;

free(head);

return i;

}

int main()

{

int n, m;

scanf("%d%d", &n, &m);

printf("最后胜利的是%d号!\n", Josephu(n, m));

system("pause");

return 0;

}

37、已知strcpy函数的原型是:

char * strcpy(char * strDest,const char * strSrc);

1.不调用库函数,实现strcpy函数。

2.解释为什么要返回char *。

解说:

1.strcpy的实现代码

char * strcpy(char * strDest,const char * strSrc)

{

if ((strDest==NULL)||(strSrc==NULL)) file://[/1]

throw "Invalid argument(s)"; //[2]

char * strDestCopy=strDest;  file://[/3]

while ((*strDest++=*strSrc++)!='\0'); file://[/4]

return strDestCopy;

}

错误的做法:

[1]

(A)不检查指针的有效性,说明答题者不注重代码的健壮性。

(B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),说明答题者对C语言中类型的隐式转换没有深刻认识。在本例中char *转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。所以C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式。

(C)检查指针的有效性时使用((strDest==0)||(strSrc==0)),说明答题者不知道使用常量的好处。直接使用字面常量(如本例中的0)会减少程序的可维护性。0虽然简单,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错误,很难排除。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。

[2]

(A)return new string("Invalid argument(s)");,说明答题者根本不知道返回值的用途,并且他对内存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。

(B)return 0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。

[3]

(A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。

[4]

(A)循环写成while (*strDest++=*strSrc++);,同[1](B)。

(B)循环写成while (*strSrc!='\0') *strDest++=*strSrc++;,说明答题者对边界条件的检查不力。循环体结束后,strDest字符串的末尾没有正确地加上'\0'。