1. 程式人生 > >C/C++面試問題分類大彙總 ZZ 【C++】

C/C++面試問題分類大彙總 ZZ 【C++】

http://www.mianwww.com/html/2014/05/21208.html

  1. 指標和引用的區別

指標指向一塊記憶體,它的內容是指向記憶體的地址;引用是某記憶體的別名

引用使用是無需解引用,指標需解引用

引用不能為空,指標可以為空

引用在定義是被初始化一次,之後不可變;指標可變

程式為指標變數分配記憶體區域,而引用不需要分配記憶體區域

  1. memcpy和strcpy的區別

memcpy用來記憶體拷貝的,它有指定的拷貝資料長度,他可以拷貝任何資料型別的物件

Strcpy它只能去拷貝字串,它遇到’\0′結束拷貝

  1. new和malloc的區別,free和delete的區別

malloc與free是C++/C語言的標準庫函式,new/delete是C++的運算子。它們都可用於申請動態記憶體和釋放記憶體。

對於非內部資料型別的物件而言,光用maloc/free無法滿足動態物件的要求。物件在建立的同時要自動執行建構函式,物件在消亡之前要自動執行解構函式。由於malloc/free是庫函式而不是運算子,不在編譯器控制權限之內,不能夠把執行建構函式和解構函式的任務強加於malloc/free。

因此C++語言需要一個能完成動態記憶體分配和初始化工作的運算子new,以及一個能完成清理與釋放記憶體工作的運算子delete。注意new/delete不是庫函式。

  1. struct和class的區別

    1.成員變數

    結構在預設情況下的成員是公共(public)的,

    而類在預設情況下的成員是私有(private)的。

    2.儲存

    struct保證成員按照宣告順序在記憶體中儲存。class不保證等等

    3.繼承

    struct A { };

    class B : A{ }; //private繼承

    struct C : B{ }; //public繼承

    這是由於class預設是private,struct預設是public。

  2. struct與union的區別.(一般假定在32位機器上)

1.一個union型別的變數,所有成員變數共享一塊記憶體,該記憶體的大小有這些成員變數中長度最大的一個來決定,struct中成員變數記憶體都是獨立的

2.union分配的記憶體是連續的,而struct不能保證分配的記憶體是連續的

  1. 佇列和棧有什麼區別?

    佇列先進先出,棧後進先出

  2. 指標在16位機、32位機、64位機分別佔用多少個位元組

    16位機        2位元組

    32位機        4位元組

    64位機        8位元組

  3. 如何引用一個已經定義過的全域性變數?

    extern

    可以用引用標頭檔案的方式,也可以用extern關鍵字,如果用引用標頭檔案方式來引用某個在標頭檔案中宣告的全域性變理,假定你將那個變寫錯了,那麼在編譯期間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,那麼在編譯期間不會報錯,而在連線期間報錯

  4. 全域性變數可不可以定義在可被多個.C檔案包含的標頭檔案中?為什麼?

    可以,在不同的C檔案中以static形式來宣告同名全域性變數。

    可以在不同的C檔案中宣告同名的全域性變數,前提是其中只能有一個C檔案中對此變數賦初值,此時連線不會出錯

  5. 語句for( ;1 ;)有什麼問題?它是什麼意思?

    for( ;1 ;)和while(1)相同。

  6. do……while和while……do有什麼區別?

    前一個迴圈一遍再判斷,後一個判斷以後再迴圈

  7. 請寫出下列程式碼的輸出內容

    #include<stdio.h>

    main()

    {

    int a,b,c,d;

    a=10;

    b=a++;

    c=++a;

    d=10*a++;

    printf(“b,c,d:%d,%d,%d”,b,c,d);

    return 0;

    }

    10,12,120

  8. 對於一個頻繁使用的短小函式,在C語言中應用什麼實現,在C++中應用什麼實現?

    c用巨集定義,c++用inline

  9. main 函式執行以前,還會執行什麼程式碼?

    全域性物件的建構函式會在main 函式之前執行。

  10. main 主函式執行完畢後,是否可能會再執行一段程式碼,給出說明?

    可以,可以用on_exit 註冊一個函式,它會在main 之後執行int fn1(void), fn2(void), fn3(void), fn4 (void);

    void main( void )

    {

    String str(“zhanglin”);

    on_exit( fn1 );

    on_exit( fn2 );

    on_exit( fn3 );

    on_exit( fn4 );

    printf( “This is executed first.\n” );

    }

    int fn1()

    {

    printf( “next.\n” );

    return 0;

    }

    int fn2()

    {

    printf( “executed ” );

    return 0;

    }

    int fn3()

    {

    printf( “is ” );

    return 0;

    }

    int fn4()

    {

    printf( “This ” );

    return 0;

    }

    The on_exit function is passed the address of a function (func) to be called when the program terminates normally. Successive calls to on_exit create a register of functions that are executed in LIFO (last-in-first-out) order. The functions passed to on_exit cannot take parameters.

This is executed next.

  1. 區域性變數能否和全域性變數重名?

    能,區域性會遮蔽全域性。要用全域性變數,需要使用”::”

    區域性變數可以與全域性變數同名,在函式內引用這個變數時,會用到同名的區域性變數,而不會用到全域性變數。對於有些編譯器而言,在同一個函式內可以定義多個同名的區域性變數,比如在兩個迴圈體內都定義一個同名的區域性變數,而那個區域性變數的作用域就在那個迴圈體內

  2. 描述記憶體分配方式以及它們的區別?

    1.從靜態儲存區域分配。記憶體在程式編譯的時候就已經分配好,這塊記憶體在程式的整個執行期間都存在。例如全域性變數,static 變數。

    2. 在棧上建立。在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函式執行結束時這些儲存單元自動被釋放。棧記憶體分配運算內置於處理器的指令集。

    3. 從堆上分配,亦稱動態記憶體分配。程式在執行的時候用malloc 或new 申請任意多少的記憶體,程式設計師自己負責在何時用free 或delete 釋放記憶體。動態記憶體的生存期由程式設計師決定,使用非常靈活,但問題也最多。

  3. 類成員函式的過載、覆蓋和隱藏區別?

    1.成員函式被過載的特徵:

    (1)相同的範圍(在同一個類中);

    (2)函式名字相同;

    (3)引數不同;

    (4)virtual 關鍵字可有可無。

    2.覆蓋是指派生類函式覆蓋基類函式,特徵是:

    (1)不同的範圍(分別位於派生類與基類);

    (2)函式名字相同;

    (3)引數相同;

    (4)基類函式必須有virtual 關鍵字。

    3.”隱藏”是指派生類的函式遮蔽了與其同名的基類函式,規則如下:

    (1)如果派生類的函式與基類的函式同名,但是引數不同。此時,不論有無virtual關鍵字,基類的函式將被隱藏(注意別與過載混淆)。

    (2)如果派生類的函式與基類的函式同名,並且引數也相同,但是基類函式沒有virtual 關鍵字。此時,基類的函式被隱藏(注意別與覆蓋混淆)

  4. static有什麼用途?(請至少說明兩種)

    1.限制變數的作用域

    2.設定變數的儲存域

  5. 請說出const與#define 相比,有何優點?

    1.const 常量有資料型別,而巨集常量沒有資料型別。編譯器可以對前者進行型別安全檢查。而對後者只進行字元替換,沒有型別安全檢查,並且在字元替換可能會產生意料不到的錯誤。

    2.有些整合化的除錯工具可以對const 常量進行除錯,但是不能對巨集常量進行除錯。

    堆疊溢位一般是由什麼原因導致的?

    沒有回收垃圾資源

  6. 簡述陣列與指標的區別?

    陣列要麼在靜態儲存區被建立(如全域性陣列),要麼在棧上被建立。指標可以隨時指向任意型別的記憶體塊。

    (1)修改內容上的差別

    char a[] = “hello”;

    a[0] = ‘X’;

    char *p = “world”; // 注意p 指向常量字串

    p[0] = ‘X’; // 編譯器不能發現該錯誤,執行時錯誤

    (2) 用運算子sizeof 可以計算出陣列的容量(位元組數)。sizeof(p),p 為指標得到的是一個指標變數的位元組數,而不是p 所指的記憶體容量。C++/C 語言沒有辦法知道指標所指的記憶體容量,除非在申請記憶體時記住它。注意當陣列作為函式的引數進行傳遞時,該陣列自動退化為同類型的指標。

    char a[] = “hello world”;

    char *p = a;

    cout<< sizeof(a) << endl; // 12 位元組

    cout<< sizeof(p) << endl; // 4 位元組

    計算陣列和指標的記憶體容量

    void Func(char a[100])

    {

    cout<< sizeof(a) << endl; // 4 位元組而不是100 位元組

    }

  7. There are two int variables: a and b, don’t use “if”, “? :”, “switch”or other judgement statements, find out the biggest one of the two numbers.

    ( ( a + b ) + abs( a – b ) ) / 2

  8. 氣泡排序演算法的時間複雜度是什麼?

    O(n^2)

  9. 什麼函式不能宣告為虛擬函式?

    建構函式(Constructor)

  10. 變數在記憶體中存放的位置

全域性變數                    全域性靜態區

全域性靜態變數                全域性靜態區

全域性常量

        有初始化            程式碼區

        無初始化            全域性靜態區

區域性變數                    堆疊區

區域性靜態變數                靜態區

區域性常量                    堆疊區

    new和malloc分配空間    堆區

  1. 程序間通訊方式

管道(有名管道,無名管道),共享記憶體,訊息佇列,訊號量,socket通訊

  1. 執行緒同步方式

臨界區:通過對多執行緒的序列化來訪問公共資源或一段程式碼,速度快,適合控制資料訪問

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

訊號量(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, int count)

{

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, int count)

{

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, int c, 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, int count)

{

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, int count)

{

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 int radix)

{

char *bufptr;

char *firstdig;

char temp;

unsigned int digval;

assert(buf != NULL);

bufptr = buf;

if (val < 0)

{

*bufptr++ = ‘-’; val = (unsigned int)(-(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)                //如果str為NULL,存空字串

{

        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 = new char[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,int high)

/*在下屆為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()

{

    char str[]=”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=new Singleton();

}

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

{

    string s=”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_t start=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);

}