整理的經典面試題及各類庫函數的本身實現

  1. 進程間通訊方式

管道(有名管道,無名管道),共享內存,消息隊列,信號量,socket通訊ios

  1. 線程同步方式

臨界區:經過對多線程的串行化來訪問公共資源或一段代碼,速度快,適合控制數據訪問c++

互斥量:爲協調共同對一個共享資源的單獨訪問而設計算法

信號量(PV操做):爲控制一個具備有限數量用戶資源而設計數據庫

事件:用來通知線程有一些事件已編程

  1. 進程和線程的區別

資源:進程是擁有資源的一個獨立單位,線程是不擁有資源。數組

調度:線程做爲調度和分配的基本單位,進程是做爲資源的基本單位服務器

併發性:進程之間能夠有併發性進行,同一個進程中的多個線程是能夠併發執行網絡

系統開銷:進程在建立和撤銷的時候,因爲系統要分配和回收資源,致使系統的開銷明顯大於線程多線程

一個進程能夠擁有多個線程。併發

  1. 局部變量和全局變量可否重名

能,局部屏蔽全局。在C++裏使用全局,須要使用::。在C語言裏,extern

  1. 虛函數和純虛函數的區別

虛函數必須實現,純虛函數沒有實現

虛函數在子類裏能夠不重載,可是純虛函數必須在每個子類裏去實現

在動態內存分配的時候,析構函數必須是虛函數,但沒有必要是純虛函數

  1. 面向對象的三大特性(四大特性)

封裝、繼承、多態(抽象)

封裝:把客觀事物封裝成抽象的類,而且類能夠把本身的數據和方法只讓可信的類或者對象操做,對不可信的進行信息隱藏

繼承:子類能夠擁有父類的屬性和方法,但父類沒有子類的屬性和方法

多態:容許將子類類型的指針賦值給父類類型的指針

實現多態,有二種方式,覆蓋,重載

覆蓋,是指子類從新定義父類的虛函數的作法

重載,是指容許存在多個同名函數,而這些函數的參數表不一樣(或許參數個數不一樣,或許參數類型不一樣,或許二者都不一樣)

  1. vi編輯器打開時跳到指定的行

vi +5000 filename

  1. int型在Touble C裏佔多少個字節

2個字節

  1. 判斷一個單鏈表是否有環

兩個指針指向鏈表頭,一個指針每次走一步,另外一個指針每次走兩步,如有一個指針先指向爲NULL表示這個鏈表無環。若兩個指針重合表示鏈表有環

  1. 刷新緩衝區方式?

換行刷新緩衝區

printf(「\n」);

使用函數刷新緩衝區

fflush(stdout);

程序結束刷新緩衝區

return 0;

  1. 類和對象的兩個基本概念什麼?

對象就是對客觀事物在計算機中的抽象描述。

類就是對具體類似屬性和行爲的一組對象的統一描述。

類的包括:類說明和類實現兩大部分:

類說明提供了對該類全部數據成員和成員函數的描述。

類實現提供了全部成員函數的實現代碼。

  1. 數據庫三範式

第一範式:沒有重複的列

第二範式:非主屬的部分依賴於主屬部分

第三範式:屬性部分不依賴於其餘非主屬部分

  1. ASSERT( )是幹什麼用的

是在調試程序使用的一個宏,括號裏面要知足,若是不知足,程序將報告錯誤,並將終止執行。

  1. 若是隻想讓程序有一個實例運行,不能運行兩個。像winamp同樣,只能開一個窗口,怎樣實現?

用內存映射或全局原子(互斥變量)、查找窗口句柄

FindWindow,互斥,寫標誌到文件或註冊表,共享內存

  1. 如何截取鍵盤的響應,讓全部的’a’變成’b’?

鍵盤鉤子SetWindowsHookEx

  1. 網絡編程中設計併發服務器,使用多進程 與 多線程 ,請問有什麼區別?

1.進程:子進程是父進程的複製品。子進程得到父進程數據空間、堆和棧的複製品。

2.線程:相對與進程而言,線程是一個更加接近與執行體的概念,它能夠與同進程的其餘線程共享數據,但擁有本身的棧空間,擁有獨立的執行序列。

二者均可以提升程序的併發度,提升程序運行效率和響應時間。

線程和進程在使用上各有優缺點:線程執行開銷小,但不利於資源管理和保護;而進程正相反。同時,線程適合於在SMP機器上運行,而進程則能夠跨機器遷移。

編程

字符串實現

strcat

char *strcat(char *strDes, const char *strSrc)

{

assert((strDes != NULL) && (strSrc !=NULL));

char *address = strDes;

while (*strDes != ‘\0′)

++ strDes;

while ((*strDes ++ = *strSrc ++) != ‘\0′)

NULL;

return address;

}

strncat

char *strncat(char *strDes, const char *strSrc,int count)

{

assert((strDes != NULL) && (strSrc !=NULL));

char *address = strDes;

while (*strDes != ‘\0′)

++ strDes;

while (count — && *strSrc != ‘\0′ )

*strDes ++ = *strSrc ++;

*strDes = ‘\0′;

return address;

}

strcmp

int strcmp(const char *s, const char *t)

{

assert(s != NULL && t != NULL);

while (*s && *t && *s == *t)

{

++ s;

++ t;

}

return (*s – *t);

}

strncmp

int strncmp(const char *s, const char *t, intcount)

{

assert((s != NULL) && (t != NULL));

while (*s && *t && *s == *t&& count –)

{

++ s;

++ t;

}

return (*s – *t);

}

strcpy

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

{

assert((strDes != NULL) && (strSrc !=NULL));

char *address = strDes;

while ((*strDes ++ = *strSrc ++) != ‘\0′)

NULL;

return address;

}

 

strncpy

char *strncpy(char *strDes, const char *strSrc,int count)

{

assert(strDes != NULL && strSrc !=NULL);

char *address = strDes;

while (count — && *strSrc != ‘\0′)

*strDes ++ = *strSrc ++;

return address;

}

strlen

int strlen(const char *str)

{

assert(str != NULL);

int len = 0;

while (*str ++ != ‘\0′)

++ len;

return len;

}

strpbrk

char *strpbrk(const char *strSrc, const char*str)

{

assert((strSrc != NULL) && (str !=NULL));

const char *s;

while (*strSrc != ‘\0′)

{

s = str;

while (*s != ‘\0′)

{

if (*strSrc == *s)

return (char *) strSrc;

++ s;

}

++ strSrc;

}

return NULL;

}

strstr

char *strstr(const char *strSrc, const char*str)

{

assert(strSrc != NULL && str != NULL);

const char *s = strSrc;

const char *t = str;

for (; *t != ‘\0′; ++ strSrc)

{

for (s = strSrc, t = str; *t != ‘\0′ &&*s == *t; ++s, ++t)

NULL;

if (*t == ‘\0′)

return (char *) strSrc;

}

return NULL;

}

strcspn

int strcspn(const char *strSrc, const char*str)

{

assert((strSrc != NULL) && (str !=NULL));

const char *s;

const char *t = strSrc;

while (*t != ‘\0′)

{

s = str;

while (*s != ‘\0′)

{

if (*t == *s)

return t – strSrc;

++ s;

}

++ t;

}

return 0;

}

strspn

int strspn(const char *strSrc, const char *str)

{

assert((strSrc != NULL) && (str !=NULL));

const char *s;

const char *t = strSrc;

while (*t != ‘\0′)

{

s = str;

while (*s != ‘\0′)

{

if (*t == *s)

break;

++ s;

}

if (*s == ‘\0′)

return t – strSrc;

++ t;

}

return 0;

}

strrchr

char *strrchr(const char *str, int c)

{

assert(str != NULL);

const char *s = str;

while (*s != ‘\0′)

++ s;

for (– s; *s != (char) c; — s)

if (s == str)

return NULL;

return (char *) s;

}

strrev

char* strrev(char *str)

{

assert(str != NULL);

char *s = str, *t = str, c;

while (*t != ‘\0′)

++ t;

for (– t; s < t; ++ s, — t)

{

c = *s;

*s = *t;

*t = c;

}

return str;

}

strnset

char *strnset(char *str, int c, int count)

{

assert(str != NULL);

char *s = str;

for (; *s != ‘\0′ && s – str <count; ++ s)

*s = (char) c;

return str;

}

strset

char *strset(char *str, int c)

{

assert(str != NULL);

char *s = str;

for (; *s != ‘\0′; ++ s)

*s = (char) c;

return str;

}

strtok

char *strtok(char *strToken, const char *str)

{

assert(strToken != NULL && str !=NULL);

char *s = strToken;

const char *t = str;

while (*s != ‘\0′)

{

t = str;

while (*t != ‘\0′)

{

if (*s == *t)

{

*(strToken + (s – strToken)) = ‘\0′;

return strToken;

}

++ t;

}

++ s;

}

return NULL;

}

strupr

char *strupr(char *str)

{

assert(str != NULL);

char *s = str;

while (*s != ‘\0′)

{

if (*s >= ‘a’ && *s <= ‘z’)

*s -= 0×20;

s ++;

}

return str;

}

strlwr

char *strlwr(char *str)

{

assert(str != NULL);

char *s = str;

while (*s != ‘\0′)

{

if (*s >= ‘A’ && *s <= ‘Z’)

*s += 0×20;

s ++;

}

return str;

}

memcpy

void *memcpy(void *dest, const void *src, intcount)

{

assert((dest != NULL) && (src !=NULL));

void *address = dest;

while (count –)

{

*(char *) dest = *(char *) src;

dest = (char *) dest + 1;

src = (char *) src + 1;

}

return address;

}

memccpy

void *memccpy(void *dest, const void *src, intc, unsigned int count)

{

assert((dest != NULL) && (src !=NULL));

while (count –)

{

*(char *) dest = *(char *) src;

if (* (char *) src == (char) c)

return ((char *)dest + 1);

dest = (char *) dest + 1;

src = (char *) src + 1;

}

return NULL;

}

memchr

void *memchr(const void *buf, int c, int count)

{

assert(buf != NULL);

while (count –)

{

if (*(char *) buf == c)

return (void *) buf;

buf = (char *) buf + 1;

}

return NULL;

}

memcmp

int memcmp(const void *s, const void *t, intcount)

{

assert((s != NULL) && (t != NULL));

while (*(char *) s && *(char *) t&& *(char *) s == *(char *) t && count –)

{

s = (char *) s + 1;

t = (char *) t + 1;

}

return (*(char *) s – *(char *) t);

}

memmove

void *memmove(void *dest, const void *src, intcount)

{

assert(dest != NULL && src != NULL);

void *address = dest;

while (count –)

{

*(char *) dest = *(char *) src;

dest = (char *) dest + 1;

src = (const char *)src + 1;

}

return address;

}

memset

void *memset(void *str, int c, int count)

{

assert(str != NULL);

void *s = str;

while (count –)

{

*(char *) s = (char) c;

s = (char *) s + 1;

}

return str;

}

 

strdup

char *strdup(const char *strSrc)

{

assert(strSrc != NULL);

int len = 0;

while (*strSrc ++ != ‘\0′)

++ len;

char *strDes = (char *) malloc (len + 1);

while ((*strDes ++ = *strSrc ++) != ‘\0′)

NULL;

return strDes;

}

strchr_

char *strchr_(char *str, int c)

{

assert(str != NULL);

while ((*str != (char) c) && (*str !=‘\0′))

str ++;

if (*str != ‘\0′)

return str;

return NULL;

}

strchr

char *strchr(const char *str, int c)

{

assert(str != NULL);

for (; *str != (char) c; ++ str)

if (*str == ‘\0′)

return NULL;

return (char *) str;

}

atoi

int atoi(const char* str)

{

    int x=0;

    const char* p=str;

    if(*str==’-’||*str==’+’)

    {

     str++;

    }

    while(*str!=0)

    {

        if((*str>’9′)||(*str<’0′))

        {

        break;

        }

        x=x*10+(*str-’0′);

        str++;

    }

    if(*p==’-’)

    {

        x=-x;

    }

    return x;

}

itoa

char* itoa(int val,char* buf,unsigned intradix)

{

char *bufptr;

char *firstdig;

char temp;

unsigned int digval;

assert(buf != NULL);

bufptr = buf;

if (val < 0)

{

*bufptr++ = ‘-’; val = (unsignedint)(-(int)val);

}

firstdig = bufptr;

do

{

digval =(unsigned int) val % radix; val /=radix;

if (digval > 9)

{

*bufptr++ = (char)(digval – 10 + ‘a’);

}

else

{

*bufptr++ = (char)(digval + ’0′);

}

} while(val > 0);

*bufptr– = ‘\0′;//設置字符串末尾,並將指針指向最後一個字符

do //反轉字符

{

temp = *bufptr; *bufptr = *firstdig; *firstdig= temp;

–bufptr; ++firstdig;

} while(firstdig < bufptr);

return buf;

}

String實現

已知String原型爲:

class String

{

public:

//普通構造函數

String(const char *str =NULL)

//拷貝構造函數

String(const String&other)

//析構函數

~String(void);

//賦值函數

String &operator=(String &other) //oh,原題目打錯了,string但是一個關鍵字

private:

char* m_str;

unsigned m_uCount;

};

分別實現以上四個函數

//普通構造函數

String::String(const char* str)

{

    if(str==NULL)                //若是strNULL,存空字符串

{

        m_str= new char[1];        //分配一個字節

        *m_str=‘\0′;            //賦一個’\0′

}else

    {

        m_str= new char[strlen(str) + 1];//分配空間容納str內容

        strcpy(m_str,str);         //複製str到私有成員m_str

    }

}

//析構函數

String::~String()

{

    if(m_str!=NULL)    //若是m_str不爲NULL,釋放堆內存

{

        delete[] m_str;

        m_str= NULL;

}

}

//拷貝構造函數

String::String(const String &other)

{

    m_str = new char[strlen(other.m_str)+1];    //分配空間容納str內容

    strcpy(m_str,other.m_str);            //複製other.m_str到私有成員m_str    

}

//賦值函數

String & String::operator=(String&other)

{

    if(this ==&other)                //若對象與other是同一個對象,直接返回自己

{

        return*this

}

    delete []m_str;                //不然,先釋放當前對象堆內存

    m_str = newchar[strlen(other.m_str)+1];    //分配空間容納str內容

    strcpy(m_str,other.m_str);            //複製other.m_str到私有成員m_str

    return *this

}

編寫一個二分查找的功能函數

int BSearch(elemtype a[],elemtype x,int low,inthigh)

/*在下屆爲low,上界爲high的數組a中折半查找數據元素x*/

{

int mid;

if(low>high)

return -1;

mid=(low+high)/2;

if(x==a[mid])

return mid;

if(x<a[mid])

return(BSearch(a,x,low,mid-1));

else

return(BSearch(a,x,mid+1,high));

}

2) 非遞歸方法實現:

int BSearch(elemtype a[],keytype key,int n)

{

int low,high,mid;

low=0;high=n-1;

while(low<=high)

{

mid=(low+high)/2;

if(a[mid].key==key)

return mid;

else if(a[mid].key<key)

low=mid+1;

else

high=mid-1;

}

return -1;

}

字符串逆序

方法一

#include <stdio.h>

#include <string.h>

void main()

{

    charstr[]=」hello,world」;

    int len=strlen(str);

    char t;

    int i;

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

    {

        t=str[i];

        str[i]=str[len-i-1];

str[len-i-1]=t;

    }

    printf(「%s\n」,str);

    return 0;

}

方法二

#include <stdio.h>

int main(){

char* src = 「hello,world」;

int len = strlen(src);

char* dest =(char*)malloc(len+1);//要爲\0分配一個空間

char* d = dest;

char* s =&src[len-1];//指向最後一個字符

while( len– != 0 )

*d++=*s–;

*d = 0;//尾部要加\0

printf(「%s\n」,dest);

free(dest);// 使用完,應當釋放空間,以避免形成內存匯泄露

return 0;

}

排序

冒泡排序

void bubble_sort(int a[],int n)

{

int i,j;

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

{

bool x=ture;

for(j=0;j<n-1-i;j++)

{

int temp;

if(a[j]>a[j+1])

{

temp=a[j];

a[j]=a[j+1];

a[j+1]=temp;

x=false;

}

}

if(x) break;

}

}

時間複雜度O(N^2)

選擇排序

void select_sort(int a[],int n)

{

int i,j;

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

{

int min=i;

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

{

if(a[j]<a[min])

min=j;

if(min!=i)

{

int temp=a[j];

a[j]=a[min];

a[min]=temp;

}

}

}

}

時間複雜度O(N^2)

插入排序

void insert_sort(int a[],int n)

{

int i,j;

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

{

int x=a[i];

for(j=i;j>0&&x<a[j-1];j–)

a[j]=a[j-1];

a[j]=x;

}

}

時間複雜度O(N^2)

快速排序

void quick_sort(int a[],int ileft,int iright)

{

int iPivot=(left+right)/2;

int nPivot=a[iPivot];

for(int i=ileft,j=iright;i<j;)

{

while(!(i>=iPivot||nPivot<a[i]))

i++;

if(i<iPivot)

{

a[iPivot]=a[i];

iPivot=i;

}

while(!(j<=iPivot||nPivot>a[j]))

j–;

if(j>iPivot)

{

a[iPivot]=a[j];

iPivot=j;

}

}

a[iPivot]=nPivot;

if(iPivot-ileft>1)

quick_sort(a,ileft,iPivot-1);

if(iright-iPivot>1)

quick_sort(a,iPivot+1,iright);

}

時間複雜度O(NlogN)

鏈表

單鏈表

雙鏈表

循環鏈表

單鏈表逆置

void reverse(link *head)

{

    link *p, *s, *t;

    p = head;

    s = p->next;

    while(s->next!=NULL)

    {

        t= s->next;

        s->next= p;

        p= s;

        s= t;

    }

    s->next = p;

    head->next->next= NULL;    //尾指針置爲空

    head->next = s;        //賦值到頭指針後一位

}

鏈表合併

Node * Merge(Node *head1 , Node *head2)

{

if ( head1 == NULL)

return head2 ;

if ( head2 == NULL)

return head1 ;

Node *head = NULL ;

Node *p1 = NULL;

Node *p2 = NULL;

if ( head1->data <head2->data )

{

head = head1 ;

p1 = head1->next;

p2 = head2 ;

}else

{

head = head2 ;

p2 = head2->next ;

p1 = head1 ;

}

Node *pcurrent = head ;

while ( p1 != NULL&& p2 != NULL)

{

if ( p1->data <=p2->data )

{

pcurrent->next = p1 ;

pcurrent = p1 ;

p1 = p1->next ;

}else

{

pcurrent->next = p2 ;

pcurrent = p2 ;

p2 = p2->next ;

}

}

if ( p1 != NULL )

pcurrent->next = p1 ;

if ( p2 != NULL )

pcurrent->next = p2 ;

return head ;

}

 

遞歸方式:

Node * MergeRecursive(Node *head1 , Node*head2)

{

if ( head1 == NULL )

return head2 ;

if ( head2 == NULL)

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);

}

return head ;

}

寫一個Singleton模式

#include<iostream>

using namespace std;

class Singleton

{

    private:

    static Singleton*_instance;

    protected:

    Singleton()

{

    cout<<」Singleton」<<endl;

}

    public:

    static Singleton*Instance()

{

if(NULL==_instance)

{

    _instance=newSingleton();

}

return _instance;

}

};

static Singleton* Singleton::_instance=NULL;

int main()

{

    Singleton * s=Singleton::Instance();

    Singleton *s1=Singleton::Instance();

}

如何對String類型數據的某個字符進行訪問?

#include<iostream>

using namespace std;

int main()

{

    strings=」abcdefg」;    

    const char*c=s.c_str();

    while(*c!=’\0′)

    {

        printf(「%c」,*c++);

    }

}

文件加密、解密

1.加密(encryption):

#include<stdio.h>

void encryption(char *ch)

{

    (*ch)^=0xFF; //算法可自行修改調整,使用AES加密算法

}

int main(int argc,char *argv[])

{

    if(argc<2)

    {

        printf(「參數不足」);

        return-1;

    }

    //文件的打開(fopen函數)

    /*

    r    read    只讀

    w    write    只寫

    a    append    追加

    t    text    文本文件,可省略不寫

    b    banary    二進制文件

    +    讀和寫

     */

a.out a.c b.txt

argv[0] argv[1] argv[2]

 

 

 

    FILE* fpr=NULL;

    FILE* fpw=NULL;

    //文件打開失敗返回一個空指針值NULL

    if(NULL==(fpr=fopen(argv[1],」r」))){printf(「%m\n」);return-1;}

    if(NULL==(fpw=fopen(argv[2],」w+」))){printf(「%m\n」);return-1;}

    char ch;

    while((ch=fgetc(fpr))!=EOF)

    {

        //putchar(ch);

        encryption(&ch);//加密函數

        printf(「%c」,ch);//加密後字符顯示

        fputc(ch,fpw);//存放進文件

    }

    printf(「\n文件加密成功!\n」);

 

    //文件的關閉(fclose函數)

    fclose(fpr);

    fclose(fpw);

}

 

2.解密(decryption):

#include<stdio.h>

#include<time.h>

 

void show()

{

    time_tstart=time(NULL);

    while(start==time(NULL));

}

void decryption(char ch)

{

    (*ch)^=0xFF;//算法可自行修改調整

}

int main(int argc,char *argv[])

{

    if(argc<2)

    {

        printf(「參數不足」);

        return-1;

    }

    //文件的打開(fopen函數)

    /*

    r    read    只讀

    w    write    只寫

    a    append    追加

    t    text    文本文件,可省略不寫

    b    banary    二進制文件

    +    讀和寫

     */

    FILE* fpr=NULL;

    FILE* fpw=NULL;

    //文件打開失敗返回一個空指針值NULL

    if(NULL==(fpr=fopen(argv[1],」r」))){printf(「%m\n」);return-1;}

    if(NULL==(fpw=fopen(argv[2],」w+」))){printf(「%m\n」);return-1;}

    char ch;

    printf(「開始解密!\n」);

    while((ch=fgetc(fpr))!=EOF)

    {

        show();

        ch=decryption(ch);//解密函數

        printf(「%c」,ch);//解密後字符顯示

        fputc(ch,fpw);//存放進文件

        fflush(stdout);//刷新顯示

    }

    printf(「\n文件解密成功!\n」);

 

    //文件的關閉(fclose函數)

    fclose(fpr);

    fclose(fpw);

}

斐波那契數列(Fibonacci sequence

int Funct( int n )

{

if( n==0 || n==1 ) return 1;

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

}

相關文章
相關標籤/搜索