冷知識,盲點,錯誤。會續更。
1、最簡單的隨機數生成法,線性同餘法。
c的標準庫(cstdlib)提供了個用於生產隨機數的函數。
rand()隨機函數,返回-32767的隨機值,該函數沒有參數
srand(number)種子函數,要求一個無符號整形參數置隨機數生成器的啓動值
爲了使種子值(number)可變,通草用系統時間作爲srand函數的參數,替麼函數在ctime文件中定義。
time()時間函數,用作爲參數時,返回用整形數表示的系統當前時間。
2、C語言中exiexit(0)與exit(1)有什麼區別??
exit好象在stdio.h裏面,所以要有包含頭文件
return是返回函數調用,如果返回的是main函數,則爲退出程序
exit是在調用處強行退出程序,運行一次程序就結束
-------------------------------------------------------------------
return 是返回 函數返回
而exit是退出
-------------------------------------------------------------------
exit(1)表示異常退出.這個1是返回給操作系統的不過在DOS好像不需要這個返回值
exit(0)表示正常退出
-------------------------------------------------------------------
無論寫在那裏,都是程序推出,dos和windows中沒有什麼不一樣,最多是系統處理的不一樣。
數字0,1,-1會被寫入環境變量ERRORLEVEL,其它程序可以由此判斷程序結束狀態。
一般0爲正常推出,其它數字爲異常,其對應的錯誤可以自己指定。
-------------------------------------------------------------------
返回給操作系統的,0是正常退出,其他值是異常退出,在退出前可以給出一些提示信息,或在調試程序中察看出錯原因.。
都是轉交執行權給操作系統,不同的是執行後一個返回0給操作系統,另一個返回1,並且可以通過對返回值的檢查獲知程序是否正常結束。
區別就在於告訴系統程序是正常退出還是非正常退出,但都是退出沒什麼大關係。
利用退出程序後,系統收到的是1或0,決定下一步的操作。
3、C++中的explicit
C++中, 一個參數的構造函數(或者除了第一個參數外其餘參數都有默認值的多參構造函數), 承擔了兩個角色。 1 是個構造器 ,2 是個默認且隱含的類型轉換操作符。
所以, 有時候在我們寫下如 AAA = XXX, 這樣的代碼, 且恰好XXX的類型正好是AAA單參數構造器的參數類型, 這時候編譯器就自動調用這個構造器, 創建一個AAA的對象。
這樣看起來好象很酷, 很方便。 但在某些情況下(見下面權威的例子), 卻違背了我們(程序員)的本意。 這時候就要在這個構造器前面加上explicit修飾, 指定這個構造器只能被明確的調用/使用, 不能作爲類型轉換操作符被隱含的使用。
explicit構造函數的作用
解析:
explicit構造函數是用來防止隱式轉換的。請看下面的代碼:
class Test1
{
public:
Test1(int n)
{
num=n;
}//普通構造函數
private:
int num;
};
class Test2
{
public:
explicit Test2(int n)
{
num=n;
}//explicit(顯式)構造函數
private:
int num;
};
int main()
{
Test1 t1=12;//隱式調用其構造函數,成功
Test2 t2=12;//編譯錯誤,不能隱式調用其構造函數
Test2 t2(12);//顯式調用成功
return 0;
}
Test1的構造函數帶一個int型的參數,代碼23行會隱式轉換成調用Test1的這個構造函數。而Test2的構造函數被聲明爲explicit(顯式),這表示不能通過隱式轉換來調用這個構造函數,因此代碼24行會出現編譯錯誤。
普通構造函數能夠被隱式調用。而explicit構造函數只能被顯式調用。
4、#include”* .h“ 在查找預編譯頭使用時跳過
出現這種狀況的主要原因是沒有在cpp文件最前一行添加沒有添加 #include "stdafx.h"
#include "stdafx.h" 一定要添加到cpp文件的第一行,不能放在如”#include <iostream>“行等的後面,否則還是會出現類似錯誤!
每個cpp文件的最前一行添加語句:#include "stdafx.h"
再次編譯運行,即可解決此類錯誤。
5、MFC把一個工程中的對話框複製到另一個工程中 (出現IDD未聲明的標識符的錯誤)
1、把需要複製對話框工程中的.rc裏的相關內容,複製到另一個工程中,1)IDDxxx Dialog BEGIN...END 2)DESIGNINFO BEGIN...END 3)Dialog Info BEGIN...END
2、把resource.h中的相關的#define ID_XXX複製到令一個工程中的相同文件中(可通過不斷地調式來查找,相關的ID_XXX
3、爲對話框建立類,同時在對話框的頭文件中包含#include "Resource.h"
同時直接將對應的頭文件和源文件複製到工程目錄下
6、打開資源視圖時-提示在另一個編輯器中打開
關閉打開的Resource.h,雙擊資源視圖中的.rc(可能需要進行兩次雙擊)就可以了
或者關閉解決方案,再重新打開。(已經試過,成功)
退出程序,然後把*.ncb,*.opt,*.clw刪掉,再開 。(未試過)
00001.
7、關於C語言中return的一些總結
return是C++預定義的語句,它提供了種植函數執行的一種放大。當return語句提供了一個值時,這個值就成爲函數的返回值.
說到return,有必要提及主函數的定義,下面是從網絡上找到的資料,好好消化吧,對了解主函數中返回值的理解有很大的幫助.
很多人甚至市面上的一些書籍,都使用了void main( ) ,其實這是錯誤的。C/C++ 中從來沒有定義過void main( ) 。C++ 之父 Bjarne Stroustrup 在他的主頁上的 FAQ 中明確地寫着 The definition void main( ) { /* ... */ } is not and never has been C++, nor has it even been C.( void main( ) 從來就不存在於 C++ 或者 C )。下面我分別說一下 C 和 C++ 標準中對 main 函數的定義。
1. C
在 C89 中,main( ) 是可以接受的。Brian W. Kernighan 和 Dennis M. Ritchie 的經典鉅著 The C programming Language 2e(《C 程序設計語言第二版》)用的就是 main( )。不過在最新的 C99 標準中,只有以下兩種定義方式是正確的:
int main( void )
int main( int argc, char *argv[] )
(參考資料:ISO/IEC 9899:1999 (E) Programming languages — C 5.1.2.2.1 Program startup)
當然,我們也可以做一點小小的改動。例如:char *argv[] 可以寫成 char **argv;argv 和 argc 可以改成別的變量名(如 intval 和 charval),不過一定要符合變量的命名規則。
如果不需要從命令行中獲取參數,請用int main(void) ;否則請用int main( int argc, char *argv[] ) 。
main 函數的返回值類型必須是 int ,這樣返回值才能傳遞給程序的激活者(如操作系統)。
如果 main 函數的最後沒有寫 return 語句的話,C99 規定編譯器要自動在生成的目標文件中(如 exe 文件)加入return 0; ,表示程序正常退出。不過,我還是建議你最好在main函數的最後加上return 語句,雖然沒有這個必要,但這是一個好的習慣。注意,vc6不會在目標文件中加入return 0; ,大概是因爲 vc6 是 98 年的產品,所以纔不支持這個特性。現在明白我爲什麼建議你最好加上 return 語句了吧!不過,gcc3.2(Linux 下的 C 編譯器)會在生成的目標文件中加入 return 0; 。
2. C++
C++98 中定義瞭如下兩種 main 函數的定義方式:
int main( )
int main( int argc, char *argv[] )
(參考資料:ISO/IEC 14882(1998-9-01)Programming languages — C++ 3.6 Start and termination)
int main( ) 等同於 C99 中的 int main( void ) ;int main( int argc, char *argv[] ) 的用法也和 C99 中定義的一樣。同樣,main 函數的返回值類型也必須是int。如果main函數的末尾沒寫return語句,C++98 規定編譯器要自動在生成的目標文件中加入 return 0; 。同樣,vc6 也不支持這個特性,但是 g++3.2(Linux 下的 C++ 編譯器)支持。
3. 關於 void main
在 C 和 C++ 中,不接收任何參數也不返回任何信息的函數原型爲“void foo(void);”。可能正是因爲這個,所以很多人都誤認爲如果不需要程序返回值時可以把main函數定義成void main(void) 。然而這是錯誤的!main 函數的返回值應該定義爲 int 類型,C 和 C++ 標準中都是這樣規定的。雖然在一些編譯器中,void main 可以通過編譯(如 vc6),但並非所有編譯器都支持 void main ,因爲標準中從來沒有定義過 void main 。g++3.2 中如果 main 函數的返回值不是 int 類型,就根本通不過編譯。而 gcc3.2 則會發出警告。所以,如果你想你的程序擁有很好的可移植性,請一定要用 int main 。
4. 返回值的作用
main 函數的返回值用於說明程序的退出狀態。如果返回 0,則代表程序正常退出,否則代表程序異常退出。下面我們在 winxp 環境下做一個小實驗。首先編譯下面的程序:
int main( void )
{
return 0;
}
然後打開附件裏的“命令提示符”,在命令行裏運行剛纔編譯好的可執行文件,然後輸入“echo %ERRORLEVEL%”,回車,就可以看到程序的返回值爲 0 。假設剛纔編譯好的文件是 a.exe ,如果輸入“a && dir”,則會列出當前目錄下的文件夾和文件。但是如果改成“return -1”,或者別的非 0 值,重新編譯後輸入“a && dir”,則 dir 不會執行。因爲 && 的含義是:如果 && 前面的程序正常退出,則繼續執行 && 後面的程序,否則不執行。也就是說,利用程序的返回值,我們可以控制要不要執行下一個程序。這就是 int main 的好處。如果你有興趣,也可以把 main 函數的返回值類型改成非 int 類型(如 float),重新編譯後執行“a && dir”,看看會出現什麼情況,想想爲什麼會出現那樣的情況。順便提一下,如果輸入 a || dir 的話,則表示如果 a 異常退出,則執行 dir 。
5. 那麼 intmain(intargc,char*argv[],char*envp[])呢?
這當然也不是標準 C 裏面定義的東西!char*envp[] 是某些編譯器提供的擴展功能,用於獲取系統的環境變量。因爲不是標準,所以並非所有編譯器都支持,故而移植性差,不推薦使用。
到了這裏,你應該瞭解爲什麼主函數定義爲 int返回類型,而且函數體裏面有return 0;這個語句了吧.
下面具體說說我對return的應用的理解。
只要一個函數的返回值是數字型的,那麼就可以返回0(即return 0),其實你返回多少都沒問題。一般情況下,C++做出來的函數都要求返回一個值,當函數執行正常,且達到了一般情況下的目的,那麼就返回0表示正確的調用了該函數,這個0就是返回給主調函數以通知沒有出錯的;如果函數調用中出錯,或者沒有按照一般情況執行,那麼就返回1,以告知主調函數採取響應策略;如果你在某個函數所在類的定義所在的頭文件中定義了一組狀態值(一般都是負整數),那麼函數就可以返回不同的值以告之主調函數具體發生了什麼異常或錯誤,這種情況一般用於函數功能獨立性較差的的情況。所以一般不鼓勵把函數返回類型定義爲void,至少返回應該是int,而在函數的最後加上return 0.語句:
int func(參數列表)
{
……
……
……
Return 0;
}
在函數中,如果碰到return 語句,那麼程序就會返回調用該函數的下一條語句執行,也就是說跳出函數的執行,回到原來的地方繼續執行下去。但是如果是在主函數中碰到return語句,那麼整個程序就會停止,退出程序的執行。
如果你定義一個函數有返回類型,可以想下面那樣調用:
int func()
{
int value;
……
……
……
return value;
}
int main()
{
int intvalue;
intvalue=func();
……
……
teturn 0;
}
return語句後面具體是什麼內容,這就要具體情況具體分析了:
(1) 在返回類型是char的函數中,return後應該是char類型的值;
(2) 在返回類型是int的函數中,如果是要停止函數的調用,最好應該爲0;其他的按照你的目的而定,只要是int 類型就行了
(3) 在返回類型是結構類型的函數中,return後應該是結構的一個實例對象。
總之,函數定義爲什麼樣的返回類型,該函數中return後就應該是相應類型的值。
8、錯排公式
基本形式:d[1]=0; d[2]=1
遞歸式:d[n]= (n-1)*( d[n-1] + d[n-2])
9、struct與class
結構是數據的封裝,類是數據和操作的封裝。可以把結構看成是類的特例。結構和類都可以用關鍵字struct或class定義。區別是,struct定義的結構或類的全部成員不做特殊說明的情況下都是公有的,用class定義的結構或類不做聲明的成員是私有的。
Struct與clss的轉化,書上的思考題說,class轉化爲struct,要把所有成員換位public,但是在vs2013的情況下,我沒有轉化成員屬性,直接把class換爲struct編譯並沒有出現任何錯誤。
10、不帶參數的構造函數就是默認構造函數。如果你寫了一個構造函數,編譯器就不給你提供默認構造函數了。如果你又想用默認的構造函數,必須顯式寫一個不帶參數的,或者直接寫成 類名提示編譯器使用編譯器提供的默認構造函數。
11、VC6.0調試
F10
單步調試程序
F5 按照斷點停頓,也就是說只有在有斷點的時候才停,你可以用F5運行到有斷點的地方,然後按F10單步調試
F11進入函數,ALT+F11跳出函數
12、迭代和遞歸
遞歸和迭代都是循環的一種。
簡單地說,遞歸是重複調用函數自身實現循環。迭代是函數內某段代碼實現循環,而迭代與普通循環的區別是:循環代碼中參與運算的變量同時是保存結果的變量,當前保存的結果作爲下一次循環計算的初始值。
遞歸循環中,遇到滿足終止條件的情況時逐層返回來結束。迭代則使用計數器結束循環。當然很多情況都是多種循環混合採用,這要根據具體需求。
遞歸的例子,比如給定一個整數數組,採用折半查詢返回指定值在數組中的索引,假設數組已排序,爲方便描述,假設元素都爲正數,數組長度爲2的整數倍。
折半查詢是查詢的一種,比遍歷所有元素要快很多。
int Find(int *ary,int index,int len,int value)
{
if(len==1)//最後一個元素
{
if (ary[index]==value)return index;//成功查詢返回索引
return -1;//失敗,返回-1
}
//如果長度大於1,進行折半遞歸查詢
int half=len/2;
//檢查被查值是否大於上半部分最後一個值,如果是則遞歸查詢後半部分
if(value>ary[index+half-1])
return Find(ary,index+half,half,value);
//否則遞歸查詢上半部分
return Find(ary,index,half,value);
}
迭代經典例子就是實數的累加,比如計算1-100所有實數的和。
int v=1;
for(i=2;i<=100;i++)
{
v=v+i;
}