C语言面试题七——其他篇2

来源:互联网 发布:昆明最新网络咨询招聘 编辑:程序博客网 时间:2024/05/20 07:15

同学的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
写一个函数,功能:完成内存之间的拷贝
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);
}


原创粉丝点击