1.在C++ 程式中調用被C 編譯器編譯後的函數,為什麼要加extern “C”?
答:首先,extern是C/C++語言中表明函數和全域變數作用範圍的關鍵字,該關鍵字告訴編譯器,其聲明的函數和變數可以在本模組或其它模組中使用。
通常,在模組的標頭檔中對本模組提供給其它模組引用的函數和全域變數以關鍵字extern聲明。extern "C"是串連申明(linkage declaration),被extern "C"修飾的變數和函數是按照C語言方式編譯和串連的。作為一種物件導向的語言,C++支援函數重載,而過程式語言C則不支援。函數被C++編譯後在符號庫中的名字與C語言的不同。例如,假設某個函數的原型為:void foo( int x, int y );該函數被C編譯器編譯後在符號庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字。這樣的名字包含了函數名、函數參數數量及類型資訊,C++就是靠這種機制來實現函數重載的。
所以,可以用一句話概括extern “C”這個聲明的真實目的:解決名字匹配問題,實現C++與C的混合編程。
2.標頭檔中的ifndef/define/endif有什麼作用?
答:這是C++先行編譯標頭檔保護符,保證即使檔案被多次包含,標頭檔也只定義一次。
3. #include<file.h> 與 #include "file.h"的區別?
答:前者是從標準庫路徑尋找和引用file.h,而後者是從當前工作路徑搜尋並引用file.h。
4.評價一下C/C++各自的特點
答:C語言是一種結構化語言,面向過程,基於演算法和資料結構,所考慮的是如何通過一個過程或者函數從輸入得到輸出;
C++是物件導向,基於類、對象和繼承,所考慮的是如何構造一個物件模型,讓這個模型能夠契合與之對應的問題,通過擷取對象的狀態資訊得到輸出或實現過程式控制制。
5.const 有什麼用途?
答:在C/C++中,(1)可以定義const常量,(2)修飾函數的傳回值和形參;
在C++中,還可以修飾函數的定義體,定義類的const成員函數。被const修飾的東西受到強制保護,可以預防意外的變動,提高了程式的健壯性。
6.const和#define有什麼區別?
答:(1)const和#define都可以定義常量,但是const用途更廣。
(2)const 常量有資料類型,而宏常量沒有資料類型。編譯器可以對前者進行型別安全檢查。而對後者只進行字元替換,沒有型別安全檢查,並且在字元替換可能會產生意料不到的錯誤。
(3) 有些整合化的調試工具可以對const 常量進行調試,但是不能對宏常量進行調試。
7.關於sizeof小結的。
答:sizeof計算的是在棧中分配的記憶體大小。
(1) sizeof不計算static變數佔得記憶體;
(2) 指標的大小一定是4個位元組,而不管是什麼類型的指標;
(3) char型佔1個位元組,int佔4個位元組,short int佔2個位元組
long int佔4個位元組,float佔4位元組,double佔48位元組,string佔4位元組
一個空類佔1個位元組,單一繼承的空類佔1個位元組,虛繼承涉及到虛指標所以佔4個位元組
(4) 數組的長度:
若指定了數組長度,則不看元素個數,總位元組數=數組長度*sizeof(元素類型)
若沒有指定長度,則按實際元素個數類確定
Ps:若是字元數組,則應考慮末尾的Null 字元。
(5) 結構體對象的長度
在預設情況下,為方便對結構體內元素的訪問和管理,當結構體內元素長度小於處理器位元的時候,便以結構體內最長的資料元素的長度為對齊單位,即為其整數倍。若結構體內元素長度大於處理器位元則以處理器位元為單位對齊。
(6) unsigned影響的只是最高位的意義,資料長度不會改變,所以sizeof(unsigned int)=4
(7) 自訂類型的sizeof取值等於它的類型原型取sizeof
(8) 對函數使用sizeof,在編譯階段會被函數的傳回值的類型代替
(9) sizeof後如果是類型名則必須加括弧,如果是變數名可以不加括弧,這是因為sizeof是運算子
(10) 當使用結構類型或者變數時,sizeof返回實際的大小。當使用靜態數組時返回數組的全部大小,sizeof不能返回動態數組或者外部數組的尺寸
8.sizeof與strlen的區別?
答: (1)sizeof的傳回值類型為size_t(unsigned int);
(2)sizeof是運算子,而strlen是函數;
(3)sizeof可以用類型做參數,其參數可以是任意類型的或者是變數、函數,而strlen只能用char*做參數,且必須是以’\0’結尾;
(4)數組作sizeof的參數時不會退化為指標,而傳遞給strlen是就退化為指標;
(5)sizeo是編譯時間的常量,而strlen要到運行時才會計算出來,且是字串中字元的個數而不是記憶體大小;
9.指標和引用的區別?
答:指標和引用都提供了間接操作對象的功能。
(1) 指標定義時可以不初始化,而引用在定義時就要初始化,和一個對象綁定,而且一經綁定,只要引用存在,就會一直保持和該對象的綁定;
(2) 賦值行為的差異:指標賦值是將指標重新指向另外一個對象,而引用賦值則是修改對象本身;
(3) 指標之間存在類型轉換,而引用分const引用和非const應用,非const引用只能和同類型的對象綁定,const引用可以綁定到不同但相互關聯類型的對象或者右值
10.數組和指標的區別?
答:(1)數組要麼在全域資料區被建立,要麼在棧上被建立;指標可以隨時指向任意類型的記憶體塊;
(2)修改內容上的差別:
char a[] = “hello”;
a[0] = ‘X’;
char *p = “world”; // 注意p 指向常量字串
p[0] = ‘X’; // 編譯器不能發現該錯誤,執行階段錯誤
(3)用運算子sizeof 可以計算出數組的容量(位元組數)。sizeof(p),p 為指標得到的是一個指標變數的位元組數,而不是p 所指的記憶體容量。C++/C 語言沒有辦法知道指標所指的記憶體容量,除非在申請記憶體時記住它。注意當數組作為函數的參數進行傳遞時,該數組自動退化為同類型的指標。
11.null 指標和懸垂指標的區別?
答:null 指標是指被賦值為NULL的指標;delete指向動態指派至的指標將會產生懸垂指標。
(1) null 指標可以被多次delete,而懸垂指標再次刪除時程式會變得非常不穩定;
(2) 使用null 指標和懸垂指標都是非法的,而且有可能造成程式崩潰,如果指標是null 指標,儘管同樣是崩潰,但和懸垂指標相比是一種可預料的崩潰。
12.C++中有malloc/free,為什麼還有new/delete?
答:malloc/free是C/C++標準庫函數,new/delete是C++運算子。他們都可以用於動態申請和釋放記憶體。
對於內建類型資料而言,二者沒有多大區別。malloc申請記憶體的時候要制定分配記憶體的位元組數,而且不會做初始化;new申請的時候有預設的初始化,同時可以指定初始化;
對於類類型的對象而言,用malloc/free無法滿足要求的。對象在建立的時候要自動執行建構函式,消亡之前要調用解構函式。由於malloc/free是庫函數而不是運算子,不在編譯器控制之內,不能把執行建構函式和解構函式的任務強加給它,因此,C++還需要new/delete。
13.什麼是智能指標?
答:當類中有指標成員時,一般有兩種方式來管理指標成員:一是採用值型的方式管理,每個類對象都保留一份指標指向的對象的拷貝;另一種更優雅的方式是使用智能指標,從而實現指標指向的對象的共用。
智能指標的一種通用實現技術是使用引用計數。智能指標類將一個計數器與類指向的對象相關聯,引用計數跟蹤該類有多少個對象共用同一指標。
每次建立類的新對象時,初始化指標並將引用計數置為1;當對象作為另一對象的副本而建立時,拷貝建構函式拷貝指標並增加與之相應的引用計數;對一個對象進行賦值時,賦值操作符減少左運算元所指對象的引用計數(如果引用計數為減至0,則刪除對象),並增加右運算元所指對象的引用計數;調用解構函式時,建構函式減少引用計數(如果引用計數減至0,則刪除基礎對象)。
14.物件導向技術的基本概念是什麼,三個基本特徵是什嗎?
答:基本概念:類、對象、繼承; 基本特徵:封裝、繼承、多態。
封裝:將低層次的元素組合起來形成新的、更高實體的技術;
繼承:廣義的繼承有三種實現形式:實現繼承、可視繼承、介面繼承。
多態:允許將子類類型的指標賦值給父類類型的指標
15.C++空類預設有哪些成員函數?
答:預設建構函式、解構函式、複製建構函式、賦值函數
16.哪一種成員變數可以在一個類的執行個體之間共用?
答:static靜態成員變數
17.繼承層次中,為什麼基類解構函式是虛函數?
答:編譯器總是根據類型來調用類成員函數。但是一個衍生類別的指標可以安全地轉化為一個基類的指標。這樣刪除一個基類的指標的時候,C++不管這個指標指向一個基類對象還是一個衍生類別的對象,調用的都是基類的解構函式而不是衍生類別的。如果你依賴於衍生類別的解構函式的代碼來釋放資源,而沒有重載解構函式,那麼會有資源泄漏。
18.為什麼建構函式不能為虛函數?
答:虛函數採用一種虛調用的方法。需調用是一種可以在只有部分資訊的情況下工作的機制。如果建立一個對象,則需要知道對象的準確類型,因此建構函式不能為虛函數。
19.如果虛函數是有效,那為什麼不把所有函數設為虛函數?
答:不行。首先,虛函數是有代價的,由於每個虛函數的對象都要維護一個虛函數表,因此在使用虛函數的時候都會產生一定的系統開銷,這是沒有必要的。
20.建構函式可以是內嵌函式
21.什麼是多態?多態有什麼作用?
答:多態就是將基類類型的指標或者引用指向衍生類別型的對象。多態通過虛函數機制實現。
多態的作用是介面重用。
22.重載和覆蓋有什麼區別?
答:虛函數是基類希望衍生類別重新定義的函數,衍生類別重新定義基類虛函數的做法叫做覆蓋;
重載就在允許在相同範圍中存在多個同名的函數,這些函數的參數表不同。重載的概念不屬於物件導向編程,編譯器根據函數不同的形參表對同名函數的名稱做修飾,然後這些同名函數就成了不同的函數。
重載的確定是在編譯時間確定,是靜態;虛函數則是在運行時動態確定。
23.公有繼承、受保護繼承、私人繼承
答:(1)公有繼承時,衍生類別對象可以訪問基類中的公有成員,衍生類別的成員函數可以訪問基類中的公有和受保護的成員;
(2)私人繼承時,基類的成員只能被直接衍生類別的成員訪問,無法再往下繼承;
(3)受保護繼承時,基類的成員也只被直接衍生類別的成員訪問,無法再往下繼承。
24.公有繼承時基類受保護的成員,可以通過衍生類別對象訪問但不能修改。
25.有哪幾種情況只能用建構函式初始化列表而不能用賦值初始化?
答:const成員,引用成員
26.什麼是虛指標?
答:虛指標或虛函數指標是虛函數的實現細節。帶有虛函數的每一個對象都有一個虛指標指向該類的虛函數表。
27.C++如何阻止一個類被執行個體化?一般在什麼時候將建構函式聲明為private?
答:(1)將類定義為抽象基類或者將建構函式聲明為private;
(2)不允許類外部建立類對象,只能在類內部建立對象
28.main函數執行之前會執行什嗎?執行之後還能執行代碼嗎?
答:(1)全域對象的建構函式會在main函數之前執行;
(2)可以,可以用_onexit 註冊一個函數,它會在main 之後執行;
如果你需要加入一段在main退出後執行的代碼,可以使用atexit()函數,註冊一個函數。
文法:
#include <stdlib.h>
#include <stdio.h>
int atexit(void (*function")(void));
void fn1( void ), fn2( void ), fn3( void );
int main( void )
{
atexit(fn1);
atexit( fn2 );
printf( "This is executed first.\n" );
}
void fn1()
{
printf( " This is\n" );
}
void fn2()
{
printf( " executed next." );
}
結果:
This is executed first.
This is executed next.
29.請描述進程和線程的區別?
答:(1)進程是程式的一次執行,線程是進程中的執行單元;
(2)進程間是獨立的,這表現在記憶體空間、上下文環境上,線程運行在進程中;
(3)一般來講,進程無法突破進程邊界存取其他進程內的儲存空間;而同一進程所產生的線程共用記憶體空間;
(4)同一進程中的兩段代碼不能同時執行,除非引入多線程。
30.進程間如何通訊?
答:訊號、訊號量、訊息佇列、共用記憶體
31.在網路編程中涉及並發伺服器,使用多進程與多線程的區別?
答:(1)線程執行開銷小,但不利於資源管理和保護;進程則相反,進程可跨越機器遷移。
(2)多進程時每個進程都有自己的記憶體空間,而多線程間共用記憶體空間;
(3)線程產生的速度快,線程間通訊快、切換快;
(4)線程的資源使用率比較好;
(5)線程使用公開變數或者資源時需要同步機制。
32.說一下TCP 3次握手、4次揮手的全過程。
33.TCP和UDP有什麼區別。
答:
TCP——傳輸控制通訊協定,提供的是連線導向、可靠的位元組流服務。
當客戶和伺服器彼此交換資料前,必須先在雙方之間建立一個TCP串連,之後才能傳輸資料。TCP提供逾時重發,丟棄重複資料,檢驗資料,流量控制等功能,保證資料能從一端傳到另一端。
UDP——使用者資料包通訊協定,是一個簡單的面向資料報的傳輸層協議。UDP不提供可靠性,它只是把應用程式傳給IP層的資料報發送出去,但是並不能保證它們能到達目的地。由於UDP在傳輸資料報前不用在客戶和伺服器之間建立一個串連,且沒有逾時重發等機制,故而傳輸速度很快.
TCP協議和UDP協議的一些特性區別如下:
1.TCP協議在傳送資料區段的時候要給段標號;UDP 協議不需要。
2.TCP協議可靠;UDP協議不可靠。
3.TCP協議是連線導向;UDP協議採用無串連。
4.TCP協議負載較高,採用虛電路;UDP協議低負載。
5.TCP協議的發送方要確認接受方是否收到資料區段(3次握手協議)。
6.TCP協議採用視窗技術和流量控制。
34.如何編寫通訊端?
35.調用函數時要進行參數壓棧,一般情況下順序是從最右邊參數往左壓棧。
36.經常要操作的記憶體分為那幾個類別?
答:(1)棧區:由編譯器自動分配和釋放,存放函數的參數值、局部變數的值等;
(2)堆:一般由程式員分配和釋放,存放動態分配的變數;
(3)全域區(靜態區):全域變數和靜態變數存放在這一塊,初始化的和未初始化的分開放;
(4)文字常量區:常量字串就放在這裡,程式結束自動釋放;
(5)程式碼區:參訪函數體的二進位代碼。
37.請講述堆和棧的區別。
答:(1)申請方式不同。棧上有系統自動分配和釋放;堆上有程式員自己申請並指明大小;
(2)棧是向低地址擴充的資料結構,大小很有限;堆是向高地址擴充,是不連續的記憶體地區,空間相對大且靈活;
(3)棧由系統分配和釋放速度快;堆由程式員控制,一般較慢,且容易產生片段;
38.全域變數放在資料區段,內部變數static int count;放在資料區段,內部變數char *p=“AAA”,p的位置在堆棧上,指向的空間的位置資料段,內部變數char
*p=new char;p的位置堆,指向的空間的位置資料段
39.字元數組與字串的比較:最明顯的區別是字串會在末尾自動添加Null 字元。
40.函數指標相關概念(C++學習筆記)
41.類使用static成員的優點,如何訪問?
答:優點:
(1)static 成員的名字是在類的範圍中,因此可以避免與其他類的成員或全域對象名字衝突;
(2)可以實施封裝。static 成員可以是私人成員,而全域對象不可以;
(3) static 成員是與特定類關聯的,可清晰地顯示程式員的意圖。
static 資料成員必須在類定義體的外部定義(正好一次),static 關鍵字只能用於類定義體內部的聲明中,定義不能標示為static. 不像普通資料成員,static成員不是通過類建構函式進行初始化,也不能在類的聲明中初始化,而是應該在定義時進行初始化.保證對象正好定義一次的最好辦法,就是將static 資料成員的定義放在包含類非內聯成員函數定義的檔案中。
待用資料成員初始化的格式為:
<資料類型><類名>::<待用資料成員名>=<值>
類的待用資料成員有兩種訪問形式:
<類對象名>.<待用資料成員名> 或 <類類型名>::<待用資料成員名>
42. static資料成員和static成員函數
答:(1)static資料成員:
static資料成員獨立於該類的任意對象而存在;每個static資料成員是與類關聯的對象,並不與該類的對象相關聯。Static資料成員(const static資料成員除外)必須在類定義體的外部定義。不像普通資料成員,static成員不是通過類的建構函式進行初始化,而是應該在定義時進行初始化。
(2)static成員函數:
Static成員函數沒有this形參,它可以直接存取所屬類的static成員,不能直接使用非static成員。因為static成員不是任何對象的組成部分,所以static成員不能被聲明為const。同時,static成員函數也不能被聲明為虛函數。
43.static成員變數定義放在cpp檔案中,不能放在初始化列表中。Const static成員可就地初始化。
44.如何引用一個已經定義過的全域變數?
答:可以用引用標頭檔的方式,也可以用extern關鍵字,如果用引用標頭檔方式來引用某個在標頭檔中聲明的全域變數,假定你將那個變數寫錯了,那麼在編譯期間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,那麼在編譯期間不會報錯,而在串連期間報錯。
44.static關鍵字的作用。
答:static總是使得變數或對象的儲存形式變成靜態儲存,串連方式變成內部串連,對於局部變數(已經是內部串連了),它僅改變其儲存方式;對於全域變數(已經是靜態儲存了),它僅改變其連線類型。
45.奈奎斯特定理
46.香農定理
47.多態類中的虛函數表是 Compile-Time,還是 Run-Time時建立的?
答案:虛擬函數表是在編譯期就建立了,各個虛擬函數這時被組織成了一個虛擬函數的入口地址的數組。而對象的隱藏成員--虛擬函數表指標是在運行期--也就是建構函式被調用時進行初始化的,這是實現多態的關鍵。
48. 一個父類寫了一個 virtual 函數,如果子類覆蓋它的函數不加 virtual ,也能實現多態?
在子類的空間裡,有沒有父類的這個函數,或者父類的私人變數? (華為筆試題)
答案:只要基類在定義成員函數時已經聲明了 virtue關鍵字,在衍生類別實現的時候覆蓋該函數時,virtue關鍵字可加可不加,不影響多態的實現。子類的空間裡有父類的所有變數(static除外)。
49. 完成字串拷貝可以使用 sprintf、strcpy 及 memcpy 函數,請問這些函數有什麼區別
,你喜歡使用哪個,為什嗎?
答案:這些函數的區別在於 實現功能以及操作對象不同。
(1)strcpy 函數操作的對象是字串,完成從源字串到目的字串的拷貝功能。
(2)sprintf 函數操作的對象不限於字串:雖然目的對象是字串,但是來源物件可以是字串、也可以是任意基本類型的資料。這個函數主要用來實現(字串或基礎資料型別 (Elementary Data Type))向字串的轉換功能。如果來源物件是字串,並且指定 %s 格式符,也可實現字串拷貝功能。
(3)memcpy 函數顧名思義就是記憶體拷貝,實現將一個記憶體塊的內容複寫到另一個記憶體塊這一功能。記憶體塊由其首地址以及長度確定。程式中出現的實體物件,不論是什麼類型,其最終表現就是在記憶體中佔據一席之地(一個記憶體區間或塊)。因此,memcpy 的操作對象不局限於某一類資料類型,或者說可適用於任意資料類型,只要能給出對象的起始地址和記憶體長度資訊、並且對象具有可操作性即可。鑒於memcpy 函數等長拷貝的特點以及資料類型代表的物理意義,memcpy 函數通常限於同種類型資料或對象之間的拷貝,其中當然也包括字串拷貝以及基礎資料型別 (Elementary Data Type)的拷貝。
對於字串拷貝來說,用上述三個函數都可以實現,但是其實現的效率和使用的方便程度不同:
• strcpy 無疑是最合適的選擇:效率高且調用方便。
• sprintf 要額外指定格式符並且進行格式轉化,麻煩且效率不高。
• memcpy 雖然高效,但是需要額外提供拷貝的記憶體長度這一參數,易錯且使用不便;並且如果長度指定過大的話(最優長度是源字串長度 + 1),還會帶來效能的下降。其實 strcpy 函數一般是在內部調用 memcpy 函數或者用彙編直接實現的,以達到高效的目的。因此,使用 memcpy 和 strcpy 拷貝字串在效能上應該沒有什麼大的差別。
對於非字串類型的資料的複製來說,strcpy 和 snprintf 一般就無能為力了,可是對 memcpy 卻沒有什麼影響。但是,對於基礎資料型別 (Elementary Data Type)來說,儘管可以用 memcpy 進行拷貝,由於有賦值運算子可以方便且高效地進行同種或相容類型的資料之間的拷貝,所以這種情況下 memcpy 幾乎不被使用 。memcpy 的長處是用來實現(通常是內部實現居多)對結構或者數組的拷貝,其目的是或者高效,或者使用方便,甚或兩者兼有。
50. 應用程式在運行時的記憶體包括代碼區和資料區,其中資料區又包括哪些部分?
答:對於一個進程的記憶體空間而言,可以在邏輯上分成 3個部份:代碼區,待用資料區和動態資料區。
動態資料區一般就是“堆棧”。 棧是一種線性結構,堆是一種鏈式結構。進程的每個線程都有私人的“棧”。
全域變數和靜態變數分配在待用資料區,本地變數分配在動態資料區,即堆棧中。程式通過堆棧的基地址和位移量來訪問本地變數。
51. C++函數中值的傳遞方式有哪幾種?
答:三種傳遞方式為:值傳遞、指標傳遞和引用傳遞。
52. C++裡面是不是所有的動作都是main()引起的?如果不是,請舉例.
比如全域變數的初始化,就不是由main函數引起的
舉例: class A{};
A a; //a的建構函式限執行
int main() {}
53. 下列哪兩個是等同的
int b;
A const int* a = &b;
B const* int a = &b;
C const int* const a = &b;
D int const* const a = &b;
54. 內嵌函式在編譯時間是否做參數類型檢查?
答:內嵌函式要做參數類型檢查, 這是內嵌函式跟宏相比的優勢。
55. 全域變數和局部變數有什麼區別?實怎麼實現的?作業系統和編譯器是怎麼知道的?
(1)生命週期不同:
全域變數隨主程式建立和建立,隨主程式銷毀而銷毀
局部變數在局部函數內部,甚至局部迴圈體等內部存在,退出就不存在; 記憶體中
分配在全域資料區
(2)使用方式不同:通過聲明後全域變數程式的各個部分都可以用到;局部變數只能在局部使用,分配在棧區
作業系統和編譯器通過記憶體配置的位置來知道的,全域變數分配在全域資料段並且在程式開始啟動並執行時候被載入。局部變數則分配在堆棧裡面 。
56. 有 A 、 B 、 C 、 D 四個人,要在夜裡過一座橋。他們通過這座橋分別需要耗時 1 、 2 、 5 、 10 分鐘,只有一支手電,並且同時最多隻能兩個人一起過橋。請問,如何安排,能夠在 17 分鐘內這四個人都過橋?
Solution:關鍵是時間最長的兩個人必須同時過橋
The First Time : A(1) 和 B(2) 過橋, A(1) 返回 Cost : 1+2
The Second Time : C(5) 和 D(10) 過橋, B(2) 返回 Cost : 10+2
The Third Time A(1) 和 B(2) 過橋 Cost : 2
Total Time Cost : (1+2)+(10+2)+2=17 minutes
57. static全域變數與普通的全域變數有什麼區別?static局部變數和普通局部變數有什麼區別?static函數與普通函數有什麼區別?
答:static全域變數與普通全域變數區別:static全域變數只初使化一次,防止在其他檔案單元中被引用;
static局部變數和普通局部變數區別:static局部變數只被初始化一次,下一次依據上一次結果值;
static函數與普通函數區別:static函數在記憶體中只有一份,普通函數在每個被調用中維持一份拷貝。
58. 程式的局部變數存在於(堆棧)中,全域變數存在於(靜態區 )中,動態申請資料存在於( 堆)中。
59. 對於一個頻繁使用的短小函數,在C語言中應用什麼實現,在C++中應用什麼實現?
c用宏定義,c++用inline
60. 有1,2,....一直到n的無序數組,求排序演算法,並且要求時間複雜度為O(n),空間複雜度O(1),使用交換,而且一次只能交換兩個數。
#include<iostream.h>
Using namespace std;
int main(){
int a[] = {10,6,9,5,2,8,4,7,1,3};
int len = sizeof(a) / sizeof(int);
int temp;
for(int i = 0; i < len; )
{
temp = a[a[i] - 1];
a[a[i] - 1] = a[i];
a[i] = temp;
if ( a[i] == i + 1)
i++;
}
for (int j = 0; j < len; j++)
cout<<a[j]<<",";
return 0;
}