面试题(6)

链表的基本概念:

  • 表头结点:链表中的第一个结点,包含指向第一个数据元素的指针以及链表自身的一些信息
  • 数据结点:链表中代表数据元素的节点,包含下一个数据元素的指针和数据元素
  • 尾节点:链表中的最后一个数据结点,其下一个元素指针为空,表示无后继

已知链表的头结点head,写一个函数把这个链表逆序

Node* ReverseList(Node* head)
{
    if(head == NULL || head->next == NULL)
        return NULL;    
    Node* p1 = head;
    Node* p2 = p1->next;
    Node* p3 - p2->next;
    p1->next = NULL;
    while(p3 != NULL)
    {
        p2->next = p1;
        p1 = p2;
        p2 = p3;
        p3 = p3->next;      
    }           
    p2->next = p1;
    head = p2;
    return head;    
} 

已知两个链表head1和head2各自有序升序排列,请把它们合并成一个链表并依然有序,并要求保留所有节点

Node* Merge(Node* head1,Node* head2)
{
    Node* head = NULL;
    if(head1 == NULL)
        return head2;
    if(head2 == NULL)
        return head1;
    if(head1->data < head2->data)
    {
        head = head1;
        head1 = head1->next;        
    }
    else
    {
        head = head2;
        head2 = head2->next;        
    }
    while(head1 != NULL && head2 != NULL)
    {
        if(head1->data < head2->data)   
        {
            head->next = head1;
            head = head1;
            head1 = head1->next;            
        }   
        else
        {
            head->next = head2;
            head = head2;
            head2= head2->next;         
        }       
    }   
    if(head1 == NULL)
    {
        head->next = head2;     
    }   
    else
    {
        head->next = head1;     
    }   
    return temp;    
}

用递归方法:已知两个链表head1和head2各自升序排列,请把它们合并成一个链表依然有序

Node* MergeRecursive(Node* head1,Node* haed2)
{
    if(head1 == NULL)
    {
        return head2;       
    }
    else
    {
        return head1;
    }
    Node* head = NULL;
    if(head1->data < head2->data)
    {
        head = head1;
        head->next = MergeRecursive(head1->next,head2);     
    }   
    else
    {
        head = head2;
        head->next = MergeRecursive(head1,head2->next); 
}

设变量名为var,分别给出bool、int、float和指针变量与“零值”比较的if语句

  • if(!var)
  • if(var ==0)
  • const float EPSINON = 0.00001;if( x>= -EPSINON && x <= EPSINON)
  • if(var == NULL)

编写一个函数,把一个char组成的字符串循环右移n位,例如,原来是“abcdefghi”,如果n=2,移位后是“hiabcdefg”

strcpy, memcpy和memset
- char* strcpy(char* dest, const char *src);
- void *memcpy(void *dest, const void *src, size_t n);
- void *memset(void *s, int ch, size_t n);

(1) void LoopMove(char* pStr,int steps)
{
    int length = strlen(pStr);  
    int temp = steps % length;
    strcpy(temp, pStr+n);
    strcpy(temp+n, pStr);
    *(temp + length) = '\0';
    strcpy(pStr, temp);
}

(2) void LoopMove(char* pStr, int steps)
{
    int length = strlen(pStr);
    int n = steps % length;
    char temp[256];
    memcpy(temp, pStr+n, (length - n));
    memcpy(temp + (length-n), pStr, n);
    memcpy(pStr, temp, length);
}

编写类String的构造函数,析构函数和赋值函数

已知类String的原型如下,*编写类String的构造函数,析构函数和赋值函数

class String
{
public:
    String(const char* str = NULL);
    String(const String& other);
    ~String(void);
    String& operator = (const String& other);
private:
    char* m_data;   
};

String::String(const char* str = NUlL)
{
    if(str == NULL)
    {
        m_data = new char[1];
        m_data[0] = '\0';
    }
    else
    {
        int length = strlen(str);
        m_data = new char[length+1];
        strcpy(m_data,str);     
    }   
}

String::~String(void)
{
    delete[] m_data;    
}

String::String(const String& other)
{
    int length = strlen(other.m_data);
    m_data = new char[length+1];
    strcpy(m_data, other.m_data);   
}

String& String::operator = (const String& other)
{
    if(this == &other)
        return *this;
    delete [] m_data;
    int length = strlen(other.m_data);
    m_data = new char[length+1];
    strcpy(m_data,other.m_data);
    return *this;       
}

写一个C函数,判断不同模式处理器的返回值

int checkCPU()
{
    union
    {
        int a;
        char b;     
    }u;
    u.a = 1;
    return (u.b == 1);
}

写一个函数返回1+2+3…+n的值

扫描二维码关注公众号,回复: 1883407 查看本文章
long Sum(int n)
{
    long sum = 0;
    for(int i=1;i<=n;i++)
    {
        sum += i;       
    }       
    return sum; 
}

long Sum(int n)
{
    return (long)(n+1)*n / 2;   
}

找出两个数中最大的一个

int max = ((a+b)+abs(a-b)) / 2;

打印出当前源文件的文件名及当前行号

printf("File:%s,Line:%ld\n",__FILE__,__LINE__);

main函数执行完毕后,是否可能会再执行一段代码

  • 会执行另一些代码,进行处理工作;
  • 可以使用atexit()函数(注册结束函数),注册一个函数
  • atexit()注册的函数类型为不接受任意参数的void函数,exit调用atexit()函数的顺序与它们登记时候的顺序相反

一个关于指针的问题

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

  • c是数组名,是一个二维指针,它的值就是数组的首地址,也即第一行元素的首地址
  • *c:第一行元素的首地址,是一个一维地址
  • **c:二维数组的第一个元素的值,即:c[0][0]
  • (c+1):c是行指针,(c+1)是在c的基础上加上二维数组一行的地址长度,即从&c[0][0]变到&c[1][0]
  • (*c+1):*c是列指针,(*c+1)是在 *c 的基础上加上二维数组一个元素的长度,即从&&c[0][0]变到&&c[0][1];

已知strcpy()的函数原型为char* strcpy(char* strDest, const char* strSrc),要求不调用C++/C的字符串库函数,编写函数strcpy

char* strcpy(char* strDest,const char* strSrc)
{
    if((strDest == NULL) || (strSrc == NULL))
        return NULL;
    if(strDest == strSrc)
        return strDest;
    char* tempptr = strDest;
    while((*strDest++ = *strSrc++) != '\0')
        return tempptr;     
}

数组和指针的区别

  • 用运算符sizeof可以计算出数组的容量(字节数),而sizeof(p),p为指针得到的是指针变量的字节数,而不是p所指的内存容量。
  • 数组作为函数的参数进行传递时,该数组自动退化为同类型的指针
  • 修改内容上的差别;char* p = “world”;p[0] = ‘X’;p指向常量字符串,编译器不能发生错误,运行时错误

关于C/C++编译器的问题

如何判断一段程序是由C编译器编译的还是由C++编译器编译的?

#ifdef __cplusplus
    cout << "C++";
#else
    cout << "C";
#endif

文件中有一组整数,要求排序输出到另外一个文件

    #include <iostream>
    #incldue <fstream>
    #include <vector>

    int main()
    {
        vector<int> data;
        iftream in("C:\\data.txt");
        if(!in)
        {
            cout << "file error!":
            exit(1);    
        }
        int temp;
        while(!in.eof())
        {
            in >> temp;
            data.push_back(temp);           
        }
        in.close();
        Sort(data);//冒泡排序
        ofstream out("C:\\result.txt");
        if(!out)
        {
            cout << "file error!";
            exit(1);        
        }
        for(int i=0;i<data.size();i++)
            out << data[i] << " ";
        out.close();    
    }

找出一个整数数组中的第二大数

int类型(8位)的取值范围:(-2的15次方)(2的15次方-1)

int find_Sec_Max(int data[],int count)
{
    int maxNum = data[0];
    int secMax = -32768;
    for(int i=1;i<count;i++)
    {
        if(data[i] > maxNum)
            secNum = maxNum;
            maxNum = data[i];
        else
        {
            if(data[i] > secNum)
                secNum = data[i];
        }
    }
    return secNum;
}

判断一个单链表有环

已知:struct node{char var; node* next};
bool check(const node* head){}

bool check(const node* head)
{
    if(node == NULL)
        return false;
    node* slow = head;
    node* fast = head->next;
    while((fast != NULL)&&(fast->next != NULL))
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
            return true;        
    }   
    return false;       
}

一个关于如何处理溢出的问题

定义了int a,b,c,请写函数实现c=a+b。要求不能改变数据类型,如c改为long int。关键是如何处理溢出

bool add(int a,int b, int* c)
{
    *c = a + b;
    return ((a > 0)&&(b > 0)&&(*c < a || *c <b)) || ((a < 0)&&(b < 0)&&(*c > a || *c > b)); 
}

如何用C语言将一个字符转换成整形

long atol(const char* nptr)
{
    if(nptr == NULL)
    {
        return -1;  
    }   
    int length = strlen(nptr);
    long array[256];
    int ret = 0;
    for(int i=0;i<length;i++)
    {
        long temp = nptr[i] - 48;
        array[i] = temp;
        ret = ret + array[i] * pow(10,length-i-i)   
    } 
}

volatile含义,并给出三个不同的例子

  • 定义为volatile的变量就是说变量可能会被意想不到地改变,每次用到这个变量编译器不会去优化,使用保存在寄存器里的备份,而是每次小心地去内存重新读取这个变量的值
  • 并行设备的硬件寄存器(状态寄存器)
  • 一个中断服务子程序中访问到的非自动变量
  • 多线程间共享的变量

一个参数既可以是const还可以是volatile吗

  • 可以,比如状态寄存器,它是volatile因为它可能被意想不到地改变;它是const因为程序不应该视图去修改它

一个指针可以是volatile吗

  • 可以,比如一个中断服务子程序修改一个指向一个buffer的指针时

    int square(volatile int* ptr)
    {
            return *ptr * *ptr;//int a,b; a = *ptr;  b = *ptr;  return a * b;
    }
    

    由于*ptr的值可能被意想不到地改变,所以a和b的值可能是不同的

猜你喜欢

转载自blog.csdn.net/qq_34121068/article/details/77995880
今日推荐