面试

作者在 2008-03-07 10:00:56 发布以下内容

上面是基本问题,接下来是编程问题:


本人很弱,这几个题也搞不定,特来求救:
1)读文件file1.txt的内容(例如):
12
34
56
输出到file2.txt:
56
34
12
(逆序)
2)输出和为一个给定整数的所有组合
例如n=5
5=1+4;5=2+3(相加的数不能重复)
则输出
1,4;2,3。
望高手赐教!!

第一题,注意可增长数组的应用.
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
         int MAX = 10;
int *a = (int *)malloc(MAX * sizeof(int));
int *b;
   
FILE *fp1;
FILE *fp2;

fp1 = fopen("a.txt","r");
if(fp1 == NULL)
{printf("error1");
    exit(-1);
}

    fp2 = fopen("b.txt","w");
if(fp2 == NULL)
{printf("error2");
    exit(-1);
}

int i = 0;
    int j = 0;

while(fscanf(fp1,"%d",&a[i]) != EOF)
{
i++;
j++;
if(i >= MAX)
{
MAX = 2 * MAX;
b = (int*)realloc(a,MAX * sizeof(int));
if(b == NULL)
{
printf("error3");
exit(-1);
}
a = b;
}
}

for(;--j >= 0;)
   fprintf(fp2,"%d\n",a[j]);

fclose(fp1);
fclose(fp2);

return 0;


}

第二题.
#include <stdio.h>

int main(void)
{
unsigned long int i,j,k;

printf("please input the number\n");
scanf("%d",&i);
    if( i % 2 == 0)
        j = i / 2;
else
j = i / 2 + 1;

printf("The result is \n");
    for(k = 0; k < j; k++)
     printf("%d = %d + %d\n",i,k,i - k);
return 0;
}

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

兄弟,这样的题目若是做不出来实在是有些不应该, 给你一个递规反向输出字符串的例子,可谓是反序的经典例程.

void inverse(char *p)
{
    if( *p = = '\0' )
return;
    inverse( p+1 );
    printf( "%c", *p );
}

int main(int argc, char *argv[])
{
    inverse("abc\0");

    return 0;
}

借签了楼上的“递规反向输出”
#include <stdio.h>
void test(FILE *fread, FILE *fwrite)
{
        char buf[1024] = {0};
        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 0;
}

在对齐为4的情况下
struct BBB
{
   long num;
   char *name;
   short int data;
   char ha;
   short ba[5];
}*p;
p=0x1000000;
p+0x200=____;
(Ulong)p+0x200=____;
(char*)p+0x200=____;
希望各位达人给出答案和原因,谢谢拉
解答:假设在32位CPU上,
sizeof(long) = 4 bytes
sizeof(char *) = 4 bytes
sizeof(short int) = sizeof(short) = 2 bytes
sizeof(char) = 1 bytes

由于是4字节对齐,
sizeof(struct BBB) = sizeof(*p)
= 4 + 4 + 2 + 1 + 1/*补齐*/ + 2*5 + 2/*补齐*/ = 24 bytes  (经Dev-C++验证)

p=0x1000000;
p+0x200=____;
    = 0x1000000 + 0x200*24

(Ulong)p+0x200=____;
    = 0x1000000 + 0x200

(char*)p+0x200=____;
    = 0x1000000 + 0x200*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 - 1);
QSort (L,pl + 1,high);
}
}

intmain ()
{
intnarry[100],addr[100];
intsum = 1,t;

cout << "Input number:" << endl;
cin >> t;

while (t != -1)
{
narry[sum] = t;
addr[sum - 1] = t;
sum++;

cin >> t;
}

sum -= 1;
QSort (narry,1,sum);

for (int i = 1; i <= sum;i++)
cout << narry[i] << '\t';
cout << endl;

intk;
cout << "Please input place you want:" << endl;
cin >> k;

intaa = 1;
intkk = 0;
for (;;)
{
if (aa == k)
break;
if (narry[kk] != narry[kk + 1])
{
aa += 1;
kk++;
}

}

cout << "The NO." << k << "number is:" << narry[sum - kk] << endl;
cout << "And it's place is:" ;
for (i = 0;i < sum;i++)
{
if (addr[i] == narry[sum - kk])
cout << i << '\t';
}


return0;
}

1、找错
Void test1()
{
char string[10];
char* str1="0123456789";
strcpy(string, str1);// 溢出,应该包括一个存放'\0'的字符string[11]
}


Void test2()
{
char string[10], str1[10];
for(I=0; I<10;I++)
{
str1[i] ='a';
}
strcpy(string, str1);// I,i没有声明。
}

Void test3(char* str1)
{
char string[10];
if(strlen(str1)<=10)// 改成<10,字符溢出,将strlen改为sizeof也可以
{
strcpy(string, str1);
}
}

2.
void g(int**);
int main()
{
int line[10],i;
int *p=line; //p是地址的地址
for (i=0;i<10;i++)
{
*p=i;
g(&p);//数组对应的值加1
}
for(i=0;i<10;i++)
printf("%d\n",line[i]);
return 0;
}

void g(int**p)
{
(**p)++;
(*p)++;// 无效
}
输出:
1
2
3
4
5
6
7
8
9
10
3. 写出程序运行结果

int sum(int a)
{
auto int c=0;
static int b=3;
c+=1;
b+=2;
return(a+b+c);
}

void main()
{
int I;
int a=2;
for(I=0;I<5;I++)
{
printf("%d,", sum(a));
}
}
// static会保存上次结果,记住这一点,剩下的自己写
输出:8,10,12,14,16,


4.

int func(int a)
{
int b;
switch(a)
{
case 1: 30;
case 2: 20;
case 3: 16;
default: 0
}
return b;
}
则func(1)=?
// b定义后就没有赋值。

5:
int a[3];
a[0]=0; a[1]=1; a[2]=2;
int *p, *q;
p=a;
q=&a[2];
则a[q-p]=a[2]
解释:指针一次移动一个int但计数为1

今天早上的面试题9道,比较难,向牛人请教,国内的一牛公司,坐落在北京北四环某大厦:
1、线形表a、b为两个有序升序的线形表,编写一程序,使两个有序线形表合并成一个有序升序线形表h;
答案在 请化大学 严锐敏《数据结构第二版》第二章例题,数据结构当中,这个叫做:两路归并排序
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;
}
2、运用四色定理,为N个局域举行配色,颜色为1、2、3、4四种,另有数组adj[][N],如adj[i][j]=1则表示i区域与j区域相邻,数组color[N],如color[i]=1,表示i区域的颜色为1号颜色。
四色填充
3、用递归算法判断数组a[N]是否为一个递增数组。
递归的方法,记录当前最大的,并且判断当前的是否比这个还大,大则继续,否则返回false结束:
bool fun( int a[], int n )
{
if( n= =1 )
return true;
if( n= =2 )
return a[n-1] >= a[n-2];
return fun( a,n-1) && ( a[n-1] >= a[n-2] );
}
4、编写算法,从10亿个浮点数当中,选出其中最大的10000个。
用外部排序,在《数据结构》书上有
《计算方法导论》在找到第n大的数的算法上加工
5、编写一unix程序,防止僵尸进程的出现.

同学的4道面试题,应聘的职位是搜索引擎工程师,后两道超级难,(希望大家多给一些算发)
1.给两个数组和他们的大小,还有一动态开辟的内存,求交集,把交集放到动态内存dongtai,并且返回交集个数
long jiaoji(long* a[],long b[],long* alength,long blength,long* dongtai[])
2.单连表的建立,把'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);

3.可怕的题目终于来了
象搜索的输入信息是一个字符串,统计300万输入信息中的最热门的前十条,我们每次输入的一个字符串为不超过255byte,内存使用只有1G,
请描述思想,写出算发(c语言),空间和时间复杂度,
4.国内的一些帖吧,如baidu,有几十万个主题,假设每一个主题都有上亿的跟帖子,怎么样设计这个系统速度最好,请描述思想,写出算发(c语言),空间和时间复杂度,


#include   string.h
main(void)
{   char   *src="hello,world";
    char   *dest=NULL;
    dest=(char   *)malloc(strlen(src));
    int   len=strlen(str);
    char   *d=dest;
    char   *s=src[len];
    while(len--!=0)
      d++=s--;
    printf("%s",dest);
}
找出错误!!
#include   "string.h"
#include "stdio.h"
#include "malloc.h"
main(void)
{  
char   *src="hello,world";
    char   *dest=NULL;
    dest=(char   *)malloc(sizeof(char)*(strlen(src)+1));
    int   len=strlen(src);
    char   *d=dest;
    char   *s=src+len-1;
    while(len--!=0)
      *d++=*s--;
*d='\0';
    printf("%s",dest);
}

1.    简述一个Linux驱动程序的主要流程与功能。

2.    请列举一个软件中时间换空间或者空间换时间的例子。
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;
}
6.    请问一下程序将输出什么结果?
char *RetMenory(void)
{
       char p[] = “hellow world”;
       return p;
}
void Test(void)
{
       char *str = NULL;
       str = RetMemory();
       printf(str);
}
RetMenory执行完毕,p资源被回收,指向未知地址。返回地址,str的内容应是不可预测的, 打印的应该是str的地址


写一个函数,它的原形是int continumax(char *outputstr,char *intputstr)
功能:
在字符串中找出连续最长的数字串,并把这个串的长度返回,并把这个最长数字串付给其中一个函数参数outputstr所指内存。例如:"abcd12345ed125ss123456789"的首地址传给intputstr后,函数将返回
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;
}

不用库函数,用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;
}

前几天面试,有一题想不明白,请教大家!
  typedef struct
  {
     int a:2;
     int b:2;
     int c:1;
  }test;

  test t;
  t.a = 1;
  t.b = 3;
  t.c = 1;

  printf("%d",t.a);
  printf("%d",t.b);
  printf("%d",t.c);

  谢谢!
t.a为01,输出就是1
t.b为11,输出就是-1
t.c为1,输出也是-1
3个都是有符号数int嘛。
这是位扩展问题
01
11
1
编译器进行符号扩展


求组合数: 求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;
}

1、用指针的方法,将字符串“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;
}
2、有一分数序列: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;
}

有一个数组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;
}

试题:
void test2()
{
   char string[10], str1[10];
   int i;
   for(i=0; i<10; i++)
   {
      str1[i] = 'a';
   }
   strcpy( string, str1 );
}
解答:对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string, str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分;
str1不能在数组内结束:因为str1的存储为:{a,a,a,a,a,a,a,a,a,a},没有'\0'(字符串结束符),所以不能结束
strcpy( char *s1,char *s2)他的工作原理是,扫描s2指向的内存,逐个字符付到s1所指向的内存,直到碰到'\0',因为str1结尾没有'\0',所以具有不确定性,不知道他后面还会付什么东东。
正确应如下
void test2()
{
   char string[10], str1[10];
   int i;
   for(i=0; i<9; i++)
   {
      str1[i] = 'a'+i; //把abcdefghi赋值给字符数组
   }
   str[i]='\0';//加上结束符
   strcpy( string, str1 );
}

第二个code题是实现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;
}
第三个code题是实现子串定位
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;
}

分析:
int arr[] = {6,7,8,9,10};
int *ptr = arr;
*(ptr++)+=123;
printf(“ %d %d ”, *ptr, *(++ptr));
输出:8 8
过程:对于*(ptr++)+=123;先做加法6+123,然后++,指针指向7;对于printf(“ %d %d ”, *ptr, *(++ptr));从后往前执行,指针先++,指向8,然后输出8,紧接着再输出8

华为全套完整试题
高级题
6、已知一个单向链表的头,请写出删除其某一个结点的算法,要求,先找到此结点,然后删除。
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)
}

有一个16位的整数,每4位为一个数,写函数求他们的和。
解释:
整数1101010110110111
和  1101+0101+1011+0111
感觉应该不难,当时对题理解的不是很清楚,所以写了一个函数,也不知道对不对。
疑问:
    既然是16位的整数,1101010110110111是2进制的,那么函数参数怎么定义呢,请大虾指教。
答案:用十进制做参数,计算时按二进制考虑。
/* n就是16位的数,函数返回它的四个部分之和 */
char SumOfQuaters(unsigned short n)
{
    char c = 0;
    int i = 4;
    do
    {
        c += n & 15;
        n = n >> 4;
    } while (--i);

    return c;
}

 

有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;
}

(慧通)
1 写出程序把一个链表中的接点顺序倒排
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;
}
2 写出程序删除链表中的所有接点
void del_all(node *head)
{
node *p;
while(head!=NULL)
{
p=head->next;
free(head);
head=p;
}
cout<<"释放空间成功!"<<endl;
}
3两个字符串,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';
}


分析下面的代码:
char *a = "hello";
char *b = "hello";
if(a= =b)
printf("YES");
else
printf("NO");
这个简单的面试题目,我选输出 no(对比的应该是指针地址吧),可在VC是YES 在C是NO
lz的呢,是一个常量字符串。位于静态存储区,它在程序生命期内恒定不变。如果编译器优化的话,会有可能a和b同时指向同一个hello的。则地址相同。如果编译器没有优化,那么就是两个不同的地址,则不同

写一个函数,功能:完成内存之间的拷贝
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 }
公司考试这种题目主要考你编写的代码是否考虑到各种情况,是否安全(不会溢出)
各种情况包括:
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);
}


华为面试题:怎么判断链表中是否有环?
bool CircleInList(Link* pHead)
{
if(pHead = = NULL || pHead->next = = NULL)//无节点或只有一个节点并且无自环
return (false);
if(pHead->next = = pHead)//自环
return (true);
Link *pTemp1 = pHead;//step 1
Link *pTemp = pHead->next;//step 2
while(pTemp != pTemp1 && pTemp != NULL && pTemp->next != NULL)
{
pTemp1 = pTemp1->next;
pTemp = pTemp->next->next;
}
if(pTemp = = pTemp1)
return (true);
return (false);
}

两个字符串,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';
}

1。编写一个 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;
}     
2。请编写一个 C 函数,该函数在给定的内存区域搜索给定的字符,并返回该字符所在位置索引值。
int search(char *cpSource, int n, char ch)
{
         int i;
         for(i=0; i<n && *(cpSource+i) != ch; ++i);
         return i;
}

一个单向链表,不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点?
将这个指针指向的next节点值copy到本节点,将next指向next->next,并随后删除原next指向的节点。


#include <stdio.h>
void foo(int m, int n)
{
    printf("m=%d, n=%d\n", m, n);
}

int main()
{
    int b = 3;
    foo(b+=3, ++b);
    printf("b=%d\n", b);
return 0;
}
输出:m=7,n=4,b=7(VC6.0)
这种方式和编译器中得函数调用关系相关即先后入栈顺序。不过不同
编译器得处理不同。也是因为C标准中对这种方式说明为未定义,所以
各个编译器厂商都有自己得理解,所以最后产生得结果完全不同。
因为这样,所以遇见这种函数,我们首先要考虑我们得编译器会如何处理
这样得函数,其次看函数得调用方式,不同得调用方式,可能产生不同得
结果。最后是看编译器优化。


2.写一函数,实现删除字符串str1中含有的字符串str2.
第二个就是利用一个KMP匹配算法找到str2然后删除(用链表实现的话,便捷于数组)


/*雅虎笔试题(字符串操作)
给定字符串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);
}


11.写一个函数比较两个字符串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 );
}

3,求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;
}

 


1. 有双向循环链表结点定义为:
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;
}
}
}
2. 编程实现:找出两个字符串中最大公共子字符串,如"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;
}
}
}
}
3. 编程实现:把十进制数(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;
}

 


输入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");
   }
}


斐波拉契数列递归实现的方法如下:
 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

 

判断一个字符串是不是回文
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;
}

c语言 | 阅读 2358 次
文章评论,共0条
游客请输入验证码
浏览28544次
最新评论