題目類型
a.C++與C差異(1-18)
1.C和C++中struct有什么區別?
C沒有Protection行為,不能定義函數,但可以有函數指針。
C++有Protection行為,默認是public(class默認private),可以定義函數;
2.C++中的struct和class有什么區別?
struct可以class所有功能,本質上是一個東西,struct成員和繼承默認是public,class成員和繼承默認是private。
3.如何判斷一個程序是由c編譯程序還是由C++編譯程序編譯的?
判斷:檢測宏
#ifdef __cpluspluc
cout<<"c++";
#else
printf("c“);
#endif
4.C和C++有什么不同?
機制上:C面向過程的(但也可編寫面向對象);C++編寫面向對象的程序比C容易
適用的方向:c適合要求代碼體積小的,效率高的場合,如嵌入式;C++更適合上層的,復雜的
C語言是結構化編程語言,C++是面向對象編程語言。
C++側重于對象而不是過程,側重于類的設計而不是邏輯的設計。
5.“引用”與指針的區別是什么?
指針通過某個指針變量指向一個對象后,對它所指向的變量間接操作。程序中使用指針,程序的可讀性差;而引用本身就是目標變量的別名,對引用的操作就是對目標變量的操作。
6.虛函數
虛函數是可以通過接口繼承的
7.int id[sizeof(unsigned long)];這個對嗎?
對
8.某文件定義靜態全局變量,他的作用域。
靜態全局變量只在源文件內有效,避免引用出錯。類里面的靜態變量可以不用實例化。C++沒有靜態類。
9.C++值的傳遞
三種:值傳遞,指針傳遞,引用傳遞
10.頻繁使用的短小函數,C語言和C++?
C用宏定義#define,C++用inline函數(一般函數浪費的是調用和返回的時間)
11.引用和指針的差別?
引用須被初始化,指針不必。(C++11引用是可以改變的)
引用初始化不能被改變,但指針可以改變所指對象。
不存在指向空值的引用,但是存在指向空值的指針。
12.virtual與inline的含義分別是什么?
virtual意味著聲明為虛函數,inline與函數定義體放在一起,使該函數稱為內聯。inline是一種用于實現的關鍵字,而不是用于聲明的關鍵字。
虛函數的特點:如果希望派生類能夠重新定義基類的方法,則在基類中將該方法定義為虛方法,這樣可以啟用動態聯編。(多繼承下只產生一個虛基類)
動態聯編 和 靜態聯編
http://blog.csdn.net/gaoxin1076/article/details/8298279
內聯函數的特點:使用內聯函數的目的是為了提高函數的運行效率。
內聯函數體的代碼不能過長,因為內聯函數省去調用函數的時間是以代碼膨脹為代價的。
內聯函數不能包含循環語句,因為執行循環語句要比調用函數的開銷大。
13.VC中,編譯工具Debug與Release選項是什么含義?
Debug通常稱為調試版本,包含調試信息,不做優化,便于程序員調試進程。Release稱為發布版本,它往往是進行了各種優化,使得程序在代碼大小和運行速度上都是最優的,以便用戶很好地使用。Debug帶有大量的挑調試代碼和信息,運行需要相應的庫,發布模式程序緊湊不含有調試代碼和信息,可以直接運行(不需要運行庫)。
14.函數assert的用法?
斷言assert是僅在debug版本起作用的宏,用于檢查“不應該”發生的情況。程序員可以把assert看成是一個任何系統狀態下都可以安全使用的無害測試手段。
15.const與#define的比較,const有什么優點?
const常量有數據類型(定義不讀內存),而宏常量沒有數據類型,編譯器可以對前者進行類型安全檢查。而對后者只進行字符替換,沒有類型安全檢查,并且在字符替換可能會產生意料不到的錯誤(邊際效應)
有些集成化的調試工具可以對const常量進行調試,但是不能對宏常量進行調試。
16.談談引用和指針的區別:
引用被創建的同時必須被初始化(指針可以在任何時候初始化)
不能有NULL引用,左值引用必須與合法的存儲單元關聯(指針可以是NULL)內存,右值引用引用寄存器。
一旦引用被初始化,就不能改變引用的關系(指針可以隨時改變所指的對象)
17.有了malloc/free為什么還要new/delete?
malloc/free是C/C++語言的標準函數庫,new/delete是C++ 的運算符,它們都可以申請動態內存和釋放內存。
由于對象在創建的同時要自動執行構造函數,消亡之前要自動執行析構函數,因為malloc/free是庫函數而不是運算符,不在編譯器的控制權之內,不能把任務強加于malloc/free。因此需要一個能完成動態內存分配和初始化的運算符new,以及一個能清理和釋放內存工作的運算符delete。
new可以把內存開在靜態區,防止內存泄漏。
18.如果再申請動態內存找不到足夠大的內存塊,malloc和new將返回NULL指針,宣告內存申請失敗。你是怎么處理內存耗盡的?
判斷指針是否為NULL,是則馬上return語句終止函數
判斷指針是否為NULL,是則馬上用exit(1)終止程序運行
為new和malloc設置異常處理函數。 例如Visual C++可以用_set_new_hander函數為new設置用戶自己定義的異常處理函數,也可以讓malloc享用與new 相同的異常處理函數。
#include big *p; p = new(std::nothrow) big[1000];
b.數據類型、關鍵字(19-37)
19.C++是不是類型安全的?
不是,兩個不同類型的指針是可以強制轉換的(用reinterpret cast)
20.const符號常量(1)const char *p(2)char const *p(3)char * const p 區別
(1)p是一個指向const char 的指針,p是可以改變指向的,但是p指向的值時不能改變的。
(2)p指向的恰好是一個指向const的char的普通指針。
(3)p是一個指針,這個指針是指向char的const指針,
(1)和(2)的定義是一樣的,*左邊值不能改變,*右邊指針不能改變
21.用C++寫個程序,如何判斷一個操作系統是16位、32位?
定義一個指針,sizeof(p),4是32位,2是16位,如果64位系統兼容32位的話也是4字節
22.用C++寫個程序,如何判斷一個操作系統是16位、32位?不用sizeof()函數
int a = ~0;
if(a>65535){ cout<<"32"bit<
else{ cout<<"16"bit<
23.void *(*(*fp1)(int))[10]; float(*(* fp2)(int,int,int))(int); int(*(*fp3)())[10]();
(1)void *(*(*fp1)(int))[10]; fp1是一個指針,指向一個函數,這個函數的參數為int型,函數的返回值是一個指針,這個指針指向一個數組,這個數組有10個元素,每個元素是一個void*型指針。
(2)float(*(* fp2)(int,int,int))(int); fp2是一個指針,指向一個函數,這個函數的參數為3個int型,函數的返回值是一個指針,這個指針指向一個函數,這個函數的參數為int型,函數的返回值是float型。
(3)int(*(*fp3)())[10]();fp3是一個指針,指向一個函數,這個函數的參數為空,函數的返回值是一個指針,這個指針指向一個數組,這個數組有10個元素,每個元素是一個指針,指向一個函數,這個參數為空,函數的返回值是int型。
24.多態類中的虛函數表示Compile-Time,還是Run-Time時建立的?
虛擬函數表是在編譯期就建立了,各個虛擬函數這時被組織成了一個虛擬函數的入口地址的數組。而對象的隱藏成員--虛擬函數表指針是在運行期--也就是構造函數被調用時進行初始化,這是實現多態的關鍵。(動態聯編)
25.錯誤的轉義字符'\091'八進制不能有9
26。數組名做實參,指針變量做形參,傳數組名傳過去的是數組的第一個元素地址
27.變量的指針指的是變量的地址
28.內存的分配方式有幾種?
在四個地方分配內存1.靜態存儲區域。2.棧上創建。3.堆上動態內存分配。4.代碼區
a從靜態存儲區分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。例如全局變量。
b在棧上創建。在執行函數時,函數內部局部變量的存儲單元都可以在棧上創建,,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。
c在堆上分配,亦稱動態內存分配。程序在運行的時候用malloc或new申請任意多少的內存,程序員自己負責在何時用free或delete釋放內存。動態內存的生存期由我們決定,使用非常靈活,但問題也多。
棧連續,堆不連續(鏈表)
29.float a,b,c,問等式(a+b)+c==(b+a)+c 和 (a+b)+c==(a+c)+b能否成立?
兩者都不行。在比較float或double時,不能簡單地比較。由于計算誤差,相等的概率很低。應判斷兩數之差是否落在區間(-e,e)內。這個e應比浮點數的精度大一個數量級。
30.全局變量和局部變量有什么區別?是怎么實現的?操作系統和編譯器是怎么知道的?
生命周期不同:全局變量隨主程序創建而創建,隨主程序的銷毀而銷毀;
局部變量在局部函數內,甚至局部循環體等內部存在,退出就不存在;
內存中分配在全局數據區
使用方式不同:通過聲明后全局變量程序的各個部分都可以用到;
局部變量只能在局部使用;
分配在棧區。
操作系統和編譯器通過內存分配的位置來知道的,
全局變量分配在全局數據段并且在程序開始運行的時候被加載。
局部變量則分配在堆棧里面。
31.Heap與Stack 的差別
Heap是堆,Stack是棧(高效地節約內存,用完就馬上釋放)。
Stack的空間由操作系統自動分配/釋放,Heap上的空間手動分配/釋放
Stack空間有限,Heap是很大的只有存儲區
C中的malloc函數分配的內存空間即在堆上,C++中對應的是new操作符
程序在編譯期對變量和函數 分配內存都在棧上進行,且程序運行過程中函數調用時參數的傳遞也在棧上進行。
32.explict protected
explict關鍵字用來修飾類的構造函數,表明該構造函數是顯式的,在某些情況下,我們要求類的使用者必須顯示調用類的構造函數時就需要使用explicit,反之默認類型轉換可能會造成無法預期的問題。
protected控制的是一個函數對一個類的成員(包括成員變量及成員方法)的訪問權限。protected成員只有該類的成員函數及其派生類的成員可以訪問。
33.重復多次fclose一個打開過一次的FILE *fp指針會有什么后果,解釋
考察點:導致文件描述符結構中指針指向的內存被重復釋放,進而導致一些不可預期的異常。
34.為什么數組名作為參數,會改變數組的內容,而其他類型如int卻不會改變變量的值?
數組名為參數時,傳遞的實際上是地址。而其他類型如int作為參數時,由于函數參數值實質上是實參的一份拷貝,被調函數內部對形參的改變并不影響實參的值。
35.你覺得如果不使用常量,直接在程序中填寫數字或字符串,將會有什么麻煩?
(1)程序的可讀性(可理解性)變差。程序員自己會忘記那些數字或字符串是什么意思,用戶則更加不知它們從何處來、表示什么。
(2)在程序的很多地方輸入同樣的數字或字符串,難保不發生書寫錯誤。
(3)如果要修改數字或字符串,則會在很多地方改動,既麻煩又容易出錯。
36.為什么需要使用堆,使用堆空間的原因?
直到運行時才知道一個對象需要多少內存空間;不知道對象的生存期到底有多長。
37.const關鍵字?有哪些作用?
(1)欲阻止一個變量被改變,可以使用const關鍵字。在定義該const變量時,通常需要對它進行初始化,因為以后就沒有機會再去改變它了;
(2)對指針來說,可以指定指針本身為const,也可以指定指針所指的數據為const,或二者同時指定為const;
(3)在一個函數聲明中,const可以修飾形參,表明它是一個輸入參數,在函數內部不能改變其值;(4)對于類的成員函數,若指定其為const類型,則表明其實一個常函數,不能修改類的成員變量;
(5)對于類的成員函數,有時候必須指定其返回值為const類型,以使得其返回值不為“左值”。
c.面型對象的特性(38-61)
38.是不是一個父類寫了一個virtual函數,如果子類覆蓋它的函數不加virtual,也能實現多態?
virtual修飾符會被隱形繼承的。virtual可加不可加。子類的空間里有父類的所有變量(static除外)。同一個函數只存在一個實體(inline除外)。子類覆蓋它的函數不加virtual,也能實現多態。在子類的空間里,有父類的私有變量。私有變量不能直接訪問。
39.面向對象的三個基本特征,并簡單敘述?
(1)封裝:將客觀事物抽象成類,每個類對自身的數據和方法實行protection(private,protected,public)
(2)繼承:廣義的繼承有三種形式:實現繼承(指使用基類的屬性和方法而無需額外編碼的能力)、可視繼承(子窗體使用父窗體的外觀和實現代碼)、接口繼承(僅使用屬性和方法,實現滯后到子類實現)。
前兩種(類繼承)和后一種(對象組合=>接口繼承以及純虛函數)構成了功能復用的兩種方式。
(3)多態:是將父對象設置成為和一個或更多的與他的子對象的特性以不同的方式運作。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。
40.重載(overload)、重寫(override,有的叫覆蓋)、重定義(redefinition)的區別?
名稱名字空間區別
重載同一名字空間是指允許存在多個同名函數,而這些函數的參數表不同
重定義/隱藏不同名字空間用于繼承,派生類與基類的函數同名,屏蔽基類的函數
重寫/覆蓋不同名字空間用于繼承,子類重新定義父類虛函數的方法
41.多態的作用?
主要的是兩個:
(1)隱藏實現細節,使得代碼能夠模塊化;擴展代碼模塊,實現代碼重用;
(2)接口重用:為了類在繼承和派生的時候,保證使用家族中任一類的實例的某一屬性時的正確調用。
42.當一個類A中沒有聲明任何成員變量與成員函數,這時sizeof(A)的值時多少?如果不是零,請解釋一下編譯器為什么沒有讓它為零?
sizeof(A)=1
一個空類對象的大小是1byte。這是被編譯器安插進去的一個字節,這樣就使得這個空類的兩個實例得以在內存中配置獨一無二的地址。
43.如果ClassA中定義并實現虛函數int func(void),ClassB中也實現該函數,那么上述變量a->func()將調用哪個類里面的函數?如果int func(void)不是虛函數,情況又如何?為什么?
第一問是調用B的。第二問是調用A的。虛函數的一個典型應用,虛函數只能借助于指針或者引用來達到多態的效果
44.C++里面是不是所有的動作都是main()函數引起的?如果不是請舉例
class A{};
A a; //a的構造函數限執行
int main(){}
45.內聯函數在編譯的時候是否做參數類型檢查?
內聯函數要做參數類型檢查,這是內聯函數跟宏相比的優勢。
46.講一講析構函數和虛函數的用法和作用?
析構函數是特殊的類成員函數,它沒有返回類型,沒有參數,不能隨意調用,也沒有重載,只有在類對象的生命期結束的時候,系統自動調用。有釋放內存空間的作用。(析構函數可以是虛函數,構造函數不行)
虛函數是C++多態的一種表現,使用虛函數,我們可以靈活的進行動態綁定,當然是以一定的開銷為代價。
47.“new" in C++ is a: operator
malloc是庫函數,不在編譯器的控制范圍之內;
new是運算符,從堆中申請內存;調用new時,從堆中申請內存并為內存調用構造函數。
48. 對于C++中類(class)與結構(struct)的描述正確的為:
D 結構和類對象都可以用new創建
49.類內部成員函數可以用private函數。
50.A對調用的虛函數和模板類都進行遲后編譯,調用需要時間
B virtual,派生類必須要求名字相同,參數類型相同,但是返回類型可以不同
C inline內聯函數可以是虛函數。靜態成員函數不能是虛函數(因為不需要實例化就可以調用),友元函數,構造函數不能是虛函數,析構函數可以。
51.C++中有沒有純虛構造函數?
構造函數不能是虛的,只能有虛的析構函數。
52.throw表達式
(1)class? exception Type{};
throw exception Type();//函數需要括號
(2)enum mathErr { overflow, underflow, zeroDivide };
throw zeroDivide;//枚舉不需要括號
53.談談你怎么認識C++ 的模板的?
模板使程序員能夠快速建立具有類型安全的類庫集合和函數集合,它的實現,方便了大規模的軟件開發。(結合stl更好)
54.在C++的一個類中聲明一個static成員變量有沒有用?
在C++類的成員變量被聲明為static(稱為靜態成員變量),意味著它為該類的所有實例所共享,也就是說當某個類的實例修改了該靜態成員變量,也就是說不管創建多少對象,static修飾的變量只占有一塊內存。其修改值為該類的其他所有實例所見;而類的靜態成員 函數也只能訪問靜態成員(變量或函數)。static是加了訪問控制的全局變量,不被繼承。
55.C++中為什么要用模板類。
(1)可用來創建動態增長和減小的數據結構.
(2)它是類型無關的,因此具有很高的可復用性。
(3)它在編譯時而不是運行時檢查數據類型,保證了類型安全
(4)它是平臺無關的,可移植性
(5)可用于基本數據類型
56.函數模板與類模板有什么區別?聯系?
函數模板的實例化是由編譯程序在處理函數調用時自動完成的
類模板的實例化必須由程序員在程序中顯示地指定
57.
58.談談 在類中如何使用const的?
有時我們希望某些常量只在類中有效。由于#define定義的宏常量是全局的,不能達到目的,于是想當然地覺得應該用const修飾數據成員來實現。const數據成員的確是存在的,但其含義卻不是我們所期望的。const數據成員只在某個對象生存期內是常量,而對于整個類而言卻是可變的,因為類可以創建多個對象,不同的對象其const數據成員的值可以不同。不能在類聲明中初始化const數據成員。
const數據成員的初始化只能在類構造函數的初始化表中進行。
59.函數重載,靠什么來區分調用的哪個函數,靠返回值判斷可以不可以?
如果同名函數的參數不同(包括類型、順序不同),那么容易區別出它們是不同的。如果同名函數僅僅是返回值類型不同,有時可以區分,有時卻不能,例如:
void func(void);與int func(void);
C/C++程序中,可以忽略函數的返回值,但是這種情況下,編譯器和程序員都不知道哪個func函數被調用,所以只能靠參數而不能靠返回值類型的不同來區分重載函數。
60.所有運算符都能重載嗎?
有一些不行。這種限制是出于安全方面的考慮,可防止錯誤和混亂。
(1)不能改變C++內部數據類型(如int,float等)的運算符。
(2)不能重載'.',因為'.'在類中對任何成員都有意義,已經成為標準用法。
(3)不能重載目前C++運算符集合中沒有的符號,如#,@,$等。
原因有兩點,一是難以理解,二是難以確定優先級。
(4)對已經存在的運算符進行重載時,不能改變優先級規則,否則將引起混亂。
61.基類的析構函數不是虛函數,會帶來什么問題?
派生類的西溝函數用不上,會造成資源的泄漏。
d.程序閱讀題(62-90)
62.main函數執行以前,還會執行什么代碼?
全局對象的構造函數會在main函數之前執行
63.不使用判斷,找出a和b中最大值。
((a+b)+abs(a-b))/2
64.如何打印出當前源文件的文件名以及源文件的當前行號?
cout << __FILE__;
cout << __LINE__;
__FILE__和__LINE__是由系統預定義宏,這種宏并不是在某個文件中定義的,而是由編譯器定義的。(C也有)
65下面有兩種if語句判斷方式。請問哪種寫法更好?為什么?
int n;
if(n==10)//第一種
if(10==n)//第二種
這是一個風格問題,第二種方式如果少了個=號,編譯時就會報錯,減少了出錯的可能性,可以檢測出是否少了=。
66.寫出運行結果:
{char str[]="word";cout<
char *p=str;cout<
char i=10;cout<
void *pp=malloc(10);cout<
6:4:1:4
67.不用第三方參數的情況下,交換兩個參數的值。
(1)異或
(2)a=a+b; b=a-b; a=a-b;
68.以下代碼如果有錯,請改正,并寫出輸出結果?
main(void)
{int nArrLength(400), i=546;//命名上有問題
for(int i=0;i<99999999999;i++);//考對變量的越界理解,改為unsigned int a=~((int)0)/2,整數0取反,
cout<
cout<
69.int i=5,b=7;
cout<<(i+++b)<
不用調試,說出在gcc編譯后的結果;
(i++ +b) 12
70.寫一個能作為左值的函數(方法有很多)。
如:max(x,y) +=2874+55;? ? drwline(x,y)++;
int &max(int &x, int &y){
return x>y?x:y;
}
int x=55,y=77;
max(x,y)+=12+11;
cout<<"x="<
71.
class human{
public:
~human(){cout<<"human over...."<
void Disp(){cout<<"human disp...."<
};
class man:public human{
public:
~man(){cout<<"man over...."<
void Disp(){cout<<"man disp...."<
};
int main(){
human *p = new man;
p->Disp();
delete p;
return 0;
}
human disp....
human over....
72.下面的函數實現在一個固定的數上加上一個數,有什么錯誤,改正:
int add_n(int n){
static int i=100;
i+=n;
return i;}
因為static使得i的值會保留上次的值。以后的i會一直更新,使得第二次調用出現錯誤。
去掉static即可
73.unsigned short array[]={1,2,3,4,5,6,7};
int i=3;
cout<<*(array+i)<
4
74.寫一個函數當參數為n(n很大)時的值1-2+3-4+5-6+7....+n.
long fn(long n)
{if(n<-0){printf("error:n >must >0");exit(1);}
if(0==n%2) return(n/2)*(-1);
else return (n/2)*(-1)+n;}
75.字符指針、浮點數指針、以及函數指針這三種類型的變量哪個占用內存最大?為什么?
指針變量也占用內存單元,而且所有指針變量占用內存單元的數量都是相同的。就是說,不管是指向何種對象的指針變量,它們占用內存的字節數都是一樣的,并且要足夠把程序中所能用到的最大地址表示出來(通常是一個機器字長)。4
76.以下三條輸出語句輸出
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
cout<
cout<
cout<
分別輸出false,false,true。
str1和str2都是字符數組,每個都有其自己的存儲區,它們的值則是各存儲區首地址,不等;
str3和str4同上,只是按const語義,它們所指向的數據區不能修改。
str5和str6并非數組而是字符指針,并不分配存儲區,其后的“abc”以常量形式存于靜態數據區,而它們自己僅是指向該區首地址的指針,相等。
77.以下代碼有什么問題?
(true?1:“1”)<
三元表達式“?:” 問號后面的兩個操作數必須為同一類型。
78.能夠編譯
unsigned int const size1 = 2;
char str1[size1];
unsigned int temp = 0;
cin >> temp;
unsigned int const size2 = temp;
char str2[size2];
str2定義出錯,size2非編譯器期間常量,而數組定義要求長度必須為編譯器常量。
79.以下代碼輸出語句為0嗎?為什么?
struct CLS{
int m_i;
CLS(int i):m_i(i){}
// m_i沒有初始化
CLS()
{
CLS(0);
}
};
CLS obj;
cout<
不能。在默認構造函數內部再調用帶參的構造函數屬用戶行為而非編譯器行為, 亦即僅執行函數調用,而不會執行其后的初始化表達式。只有在生成對象時,初始化表達式才會隨相應的構造函數調用。
80.死循環
while(1){} 或 for(;1;;)
81.
int a=5,b=7,c;
c = a+++b;
a=6,b=7,c=12
82.在排序方法中,關鍵碼比較次數與記錄地初始排列無關的是() 選擇排序
83.代碼
void func(){static int val; ...}中,變量val的內存地址位于:A。已初始化數據段
84 入棧
85.判斷表達式,寫出a的值
int a = 4;
A.a+=(a++); B.a+=(++a); C.(a++)+=a;D.(++a)+=(a++);
a++是個右值,C錯; 可改成(++a)=+a;答案:9,10,10,11
86.談談如何使用return語句
(1)return語句不可返回指向"棧內存"的“指針”或者“引用”,因為該內存在函數體結束時被自動銷毀。
(2)要搞清楚返回的究竟是“值”、“指針”還是“引用”。
(3)如果函數返回值是一個對象,要考慮return語句的效率。
87.(1)return String(s1+s2); 和(2)String temp(s1+s2);return temp;一樣嗎?
(1)是臨時對象的語法,表示“創建一個臨時對象并返回它”。
(2)將發生三件事:
首先,temp對象被創建,同時完成初始化;
然后拷貝構造函數把temp拷貝到保存返回值的外部存儲單元中;
最后,temp在函數結束時被銷毀(調用析構函數)。
然而“創建一個臨時對象并返回它”的過程是不同的,編譯器直接把臨時對象創建并初始化在外部存儲單元中,省去了拷貝和析構的花費,提高了效率
88.下列程序的運行結果
const char *str="vermeer";
int main()
{const char *pstr=str;
cout<<pstr<<endl;}
vermeer
89.inline void max_out(int val1,int val2)
{ cout<<(val1>val2)?val1:val2;}
int main(){
int ix=10,jx=20;
cout<
cout<
max_out(ix,jx);}
<<優先級大于?優先級,所以輸出的是(val1>val2)
90.? int max(int *ia, int sz);
int max(int *,int =10);
算函數重載?還是重復聲明?
如果在兩個函數的參數表中只有缺省實參不同則第二個聲明被視為第一個的重復聲明。
e.編程練習(91-100)
91.被置1的位的個數。
unsigned int One0(char log)
{
int? il
unsigned int num=0,val;
for(i=0;i<8;i++)
{val=log>>i;//移位
val &= 0x01;//與1相與
if(val) num++;}
return num;}
92.十六進制組成的字符串轉換成十進制數字并返回
bool HexToDec(char* shex,int& idec)
{
int i,mid;
int len = strlen(shex);
if(len>8) return false;
mid=0, idec=0;
for(i=0;i
{
if(shex[i]>='0' && shex[i]<='9')
mid = shex[i]-'0';
else if(shex[i]>='a'&&shex[i]<='f')
mid = shex[i]-'a'+10;
else if(shex[i]>='A'&&shex[i]<='F')
mid = shex[i]-'A'+10;
else
return false;
mid <<= ((len-i-1)<<2);//移位表示變為2的n次方倍
idec =idec+mid;
}
return true;
}
93.字符串逆序輸出
第一種:
void main()
{
char a[50];
memset(a,0,sizeof(a));
int i=0,j;
char t;
cin.geiline(a,50,'\n');
for(i=0,j=strlen(a)-1;i
{ t=a[i];a[i]=a[j];a[j]=t;}
}
第二種:
string str;
cin>>str;
str.replace;
cout<
94.編寫一個算法frequency,統計在一個輸入字符串中各個不同字符出現的頻度。用適當的測試數據來驗證這個算法。
void frequency(string& s,char A[],int C[],int& k)
{
int i,j,len=s.length();
if(!len){cout<<"empty"<
else{
A[0]=s[0];C[0]=1;k=1; /*語句s[i]是串的重載操作*/
for(i=1;i
for(i=1;i
{ //檢測串中所有字符
j=0;while(j
if(j==k)
{A[k]=s[i];C[k]++;k++;}? //s[i]從未檢測過
else C[j]++; //s[i]已經檢測過
}
}
}
95.假設以數組Q[m]存放循環隊列中的元素,同時以rear和length分別指示環形隊列中的隊尾位置和隊列中所含元素的個數。試給出該循環隊列的隊空條件和隊滿條件,并寫 出相應的插入(enqueue)和刪除(dlqueue)元素的操作。
#include
template class Queue {? ? //循環隊列的類定義
public:
Queue ( int=10 );
~Queue ( ) { delete [ ] elements; }
void EnQueue ( Type & item );
Type DeQueue ( );
Type GetFront ( );
void MakeEmpty ( ) { length = 0; }? ? //置空隊列
int IsEmpty ( ) const { return length == 0; }? //判隊列空否
int IsFull ( ) const { return length == maxSize; }? //判隊列滿否
private:
int rear, length;? ? ? //隊尾指針和隊列長度
Type *elements;? ? ? //存放隊列元素的數組
int maxSize;? ? ? //隊列最大可容納元素個數
}
template
Queue:: Queue ( int sz ) : rear (maxSize-1), length (0), maxSize (sz) {
//建立一個最大具有maxSize個元素的空隊列。
elements = new Type[maxSize];? //創建隊列空間
assert ( elements != 0 );? ? //斷言: 動態存儲分配成功與否
}
template
void Queue :: EnQueue ( Type &item ) {
assert ( ! IsFull ( ) );? ? //判隊列是否不滿,滿則出錯處理
length++;? ? ? //長度加1
rear = ( rear +1) % maxSize;? //隊尾位置進1
elements[rear] = item;? ? //進隊列
}
template
Type Queue :: DeQueue ( ) {
assert ( ! IsEmpty ( ) );? ? //判斷隊列是否不空,空則出錯處理
length--;? ? ? //隊列長度減1
return elements[(rear-length+maxSize) % maxSize];? //返回原隊頭元素值
}
讀取隊頭元素值函數
template
Type Queue :: GetFront ( ) {
assert ( ! IsEmpty ( ) );
return elements[(rear-length+1+maxSize) % maxSize];? //返回隊頭元素值
}
96.已知A[n]為整數數組,試寫出實現下列算法的遞歸算法:
(1) 求數組 A 中的最大整數。
(2) 求 n 個整數的和。
(3) 求 n 個整數的平均值。
#include
class RecurveArray? //數組類聲明
{
private:
int *Elements; //數組指針
int ArraySize; //數組尺寸
int CurrentSize; //當前已有數組元素個數
public :
RecurveArray (int MaxSize =10 ) : ArraySize ( MaxSize ), Elements ( new int[MaxSize] ) { }
~RecurveArray ( )
{
delete [ ] Elements;
}
void InputArray(); //輸入數組的內容
int MaxKey ( int n ); //求最大值
int Sum ( int n ); //求數組元素之和
float Average ( int n ); //求數組元素的平均值
};
void RecurveArray :: InputArray ( )? //輸入數組的內容
{
cout << "Input the number of Array: \n";
for ( int i = 0; i < ArraySize; i++ )
cin >> Elements[i];
}
int RecurveArray :: MaxKey ( int n )? //遞歸求最大值
{
if ( n == 1 ) return Elements[0];
int temp = MaxKey ( n - 1 );
if ( Elements[n-1] > temp )
return Elements[n-1];
else return temp;
}
int RecurveArray :: Sum ( int n )
{
//遞歸求數組之和
if ( n == 1) return Elements[0];
else return Elements[n-1] + Sum (n-1);
}
float RecurveArray :: Average ( int n )
{
//遞歸求數組的平均值
if ( n == 1) return (float) Elements[0];
else return ( (float) Elements[n-1] + ( n - 1) * Average ( n - 1 ) ) / n;
}
int main ( int argc, char* argv [ ] )
{
int size = -1;
cout << "No. of the Elements : ";
while ( size < 1 ) cin >> size;
RecurveArray ra ( size );
ra.InputArray();
cout<< "\nThe max is: " << ra.MaxKey ( ra.MaxSize ) << endl;
cout<< "\nThe sum is: " << ra.Sum ( ra.MaxSize ) << endl;
cout<< "\nthe avr is: " << ra.Average ( ra.MaxSize ) << endl;
return 0;
}
97.已知f為單鏈表的表頭指針,鏈表中存儲的都是整型數據,試寫出實現下列運算的遞歸算法:
#include //定義在頭文件中
class List;
class ListNode? //鏈表結點類
{
friend class List;
private:
int data; //結點數據
ListNode *link; //結點指針
ListNode ( const int item ) : data(item), link(NULL) { } //構造函數
};
class List? //鏈表類
{
private:
ListNode *first, current;
int Max ( ListNode *f );
int Num ( ListNode *f );
float Avg ( ListNode *f, int& n );
public:
List ( ) : first(NULL), current (NULL) { } //構造函數
~List ( ) { } //析構函數
ListNode* NewNode ( const int item ); //創建鏈表結點, 其值為
item void NewList ( const int retvalue ); //建立鏈表, 以輸入 retvalue 結束
void PrintList ( ); //輸出鏈表所有結點數據
int GetMax ( )
{
return Max ( first );? ? //求鏈表所有數據的最大值
}
int GetNum ( )
{
return Num ( first );? ? //求鏈表中數據個數
}
float GetAvg ( )
{
return Avg ( first );? ? //求鏈表所有數據的平均值
}
};
ListNode* List :: NewNode ( const int item )? //創建新鏈表結點
{
ListNode *newnode = new ListNode (item);
return newnode;
}
void List :: NewList ( const int retvalue )? //建立鏈表, 以輸入 retvalue 結束
{
first = NULL;
int value;
ListNode *q;
cout <<"Input your data:\n"; //提示
cin >>value; //輸入
while ( value != retvalue )? //輸入有效
{
q = NewNode ( value ); //建立包含 value 的新結點
if ( first == NULL ) first = current = q; //空表時, 新結點成為鏈表第一個結點
else
{
current-> link = q; //非空表時, 新結點鏈入鏈尾
current = q;
}
cin >>value; //再輸入
}
current->link = NULL; //鏈尾封閉
}
void List :: PrintList ( )? //輸出鏈表
{
cout<< "\nThe List is :\n";
ListNode *p = first;
while ( p != NULL )
{
cout <data << ' ';
p = p->link;
}
cout <<'\n';
}
int List :: Max ( ListNode *f )? //遞歸算法 : 求鏈表中的最大值
if ( f -> link == NULL ) return f -> data; //遞歸結束條件
int temp = Max ( f -> link ); //在當前結點的后繼鏈表中求最大值
if ( f -> data > temp ) return f ->data; //如果當前結點的值還要大, 返回當前檢點值
else return temp; //否則返回后繼鏈表中的最大值
} int List :: Num ( ListNode *f )? //遞歸算法 : 求鏈表中結點個數
{
if ( f == NULL ) return 0; //空表, 返回 0
return 1+ Num ( f -> link ); //否則, 返回后繼鏈表結點個數加 1
}
float List :: Avg ( ListNode *f , int& n )? //遞歸算法 : 求鏈表中所有元素的平均值
{
if ( f -> link == NULL ) //鏈表中只有一個結點, 遞歸結束條件
{
n = 1;
return ( float ) (f -> data );
}
else
{
float Sum = Avg ( f -> link, n ) * n;
n++;
return ( f -> data + Sum ) / n;
}
}
#include "RecurveList.h" //定義在主文件中
int main ( int argc, char* argv[ ] )
{
List test;
int finished;
cout <<"輸入建表結束標志數據 : ";
cin >> finished; //輸入建表結束標志數據
{
test.NewList ( finished ); //建立鏈表
test.PrintList ( ); //打印鏈表
cout <<"\nThe Max is :"<
cout <<"\nThe Num is :"<
cout <<"\nThe Ave is :"<
printf ( "Hello World!\n" );
return 0;
}
}
98.字符串的替換操作replace (String &s, String &t, String &v)是指:
若t是s的子串,則用串v替換串t在串s中的所有出現;若t不是s的子串,則串s不變。例如,若串s為“aabbabcbaabaaacbab”,串t為“bab”,串v為“abdc”,則執行replace操作后,串s中的結果為“aababdccbaabaaacabdc”。試利用字符串的基本運算實現這個替換操作。
String & String :: Replace ( String & t, String &v)
{
if ( ( int id = Find ( t ) ) == -1 ) //沒有找到,當前字符串不改,返回
{
cout << "The (replace) operation failed." << endl;
return *this;
}
String temp( ch ); //用當前串建立一個空的臨時字符串
ch[0] = '\0';
curLen = 0; //當前串作為結果串,初始為空
int j, k = 0, l; //存放結果串的指針
while ( id != -1 )
{
for ( j = 0; j < id; j++) ch[k++] = temp.ch[j];
curLen += id + v.curLen; //修改結果串連接后的長度
if ( curLen <= maxLen ) l = v.curLen; //確定替換串v傳送字符數l
else
{
l = curLen - maxLen;
curLen = maxLen;
}
for ( j = 0; j < l; j++ ) ch[k++] = v.ch[j]; //連接替換串v到結果串ch后面
if ( curLen == maxLen ) break; //字符串超出范圍
for ( j = id + t.curLen; j < temp.curLen; j++ )
temp.ch[j- id - t.curLen] = temp.ch[j]; //刪改原來的字符串
temp.curLen -= ( id + t.curLen );
id = temp.Find ( t );
}
return *this;
}
99.試編寫一個求解Josephus問題的函數。用整數序列1, 2, 3, ……, n表示順序圍坐在圓桌周圍的人,并采用數組表示作為求解過程中使用的數據結構。然后使用n = 9, s = 1, m = 5,以及n = 9, s = 1, m = 0,或者n = 9, s = 1, m = 10作為輸入數據,檢查你的程序的正確性和健壯性。
void Josephus( int A[ ], int n, s, m )
{
int i, j, k, tmp;
if ( m == 0 )
{
cout << "m = 0是無效的參數!" << endl;
return;
}
for ( i = 0; i < n; i++ ) A[i] = i + 1; /*初始化,執行n次*/
i = s - 1; /*報名起始位置*/
for ( k = n; k > 1; i-- ){/*逐個出局,執行n-1次*/
if ( i == k ) i = 0;
i = ( i + m - 1 ) % k; /*尋找出局位置*/
if ( i != k-1 )
{
tmp = A[i]; /*出局者交換到第k-1位置*/
for ( j = i; j < k-1; j++ ) A[j] = A[j+1];
A[k-1] = tmp;
}
}
for ( k = 0; k < n / 2; k++ ){/*全部逆置, 得到出局序列*/
tmp = A[k];
A[k] = A[n-k+1];
A[n-k+1] = tmp;
}
}
100.class String
{
public:
String(const char *str = NULL); // 普通構造函數
String(const String &other); // 拷貝構造函數
~ String(void); // 析構函數
String & operate =(const String &other); // 賦值函數
private:
char *m_data; // 用于保存字符串
};
請編寫String的上述4個函數。
// String 的析構函數
String::~String(void)
{
delete [] m_data;
// 由于m_data 是內部數據類型,也可以寫成 delete m_data;
}
// String 的普通構造函數
String::String(const char *str)
{
if(str==NULL)
{
m_data = new char[1]; // 若能加 NULL 判斷則更好
*m_data = ‘\0’;
}
else
{
int length = strlen(str);
m_data = new char[length+1]; // 若能加 NULL 判斷則更好
strcpy(m_data, str);
}
}
// 拷貝構造函數
String::String(const String &other)
{
int length = strlen(other.m_data);
m_data = new char[length+1]; // 若能加 NULL 判斷則更好
strcpy(m_data, other.m_data);
}
// 賦值函數
String & String::operate =(const String &other)
{
// (1) 檢查自賦值
if(this == &other)
return *this;
// (2) 釋放原有的內存資源
delete [] m_data;
// (3)分配新的內存資源,并復制內容
int length = strlen(other.m_data);
m_data = new char[length+1]; // 若能加 NULL 判斷則更好
strcpy(m_data, other.m_data);
// (4)返回本對象的引用
return *this;
}