C語(yǔ)言高手編程技巧資料_第1頁(yè)
C語(yǔ)言高手編程技巧資料_第2頁(yè)
C語(yǔ)言高手編程技巧資料_第3頁(yè)
C語(yǔ)言高手編程技巧資料_第4頁(yè)
C語(yǔ)言高手編程技巧資料_第5頁(yè)
已閱讀5頁(yè),還剩43頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、C語(yǔ)言技巧總結(jié)自增大總結(jié):i=(i+)+(+i)i=?-    源代碼:#include <stdio.h>int main()int i = 1, j = 1, k;i = (i+) + (+i);printf("i=%d n", i);k = (j+) + (+j);printf("j=%d, k=%dn", j, k);執(zhí)行結(jié)果:i=5j=3, k=4關(guān)鍵的匯編碼片段:movl $0x1,0xfffffff0(%ebp)movl $0x1,0xfffffff4(%ebp)addl $0x1,0xffffff

2、f0(%ebp)mov 0xfffffff0(%ebp),%eaxadd %eax,0xfffffff0(%ebp)addl $0x1,0xfffffff0(%ebp)    mov 0xfffffff0(%ebp),%eaxmov %eax,0x4(%esp)movl $0x8048500,(%esp)call 80482f8 <printfplt>addl $0x1,0xfffffff4(%ebp)mov 0xfffffff4(%ebp),%eaxadd 0xfffffff4(%ebp),%eaxmov %eax,0xfffffff8(%ebp)a

3、ddl $0x1,0xfffffff4(%ebp)mov 0xfffffff8(%ebp),%eaxmov %eax,0x8(%esp)mov 0xfffffff4(%ebp),%eaxmov %eax,0x4(%esp)movl $0x8048507,(%esp)call 80482f8 <printfplt>發(fā)現(xiàn),先執(zhí)行+i,最后執(zhí)行i+。i = (i+) + (i+),i是不是等于2(0+0,接著i兩次自加)j = (i+) + (i+),j是不是等于0 (i沒(méi)自加前把值賦給了j)int,float,double之間的關(guān)聯(lián)-    其實(shí)學(xué)習(xí)過(guò)編程

4、的同學(xué),都對(duì)這三個(gè)東西再熟悉不過(guò)了。int,又稱(chēng)作整型,在.net中特指的是Int32,為32位長(zhǎng)度的有符號(hào)整型變量。 float,單精度浮點(diǎn)數(shù),32位長(zhǎng)度,1位符號(hào)位,8位指數(shù)位與23位數(shù)據(jù)位,在.net中又稱(chēng)為Single。double,64位長(zhǎng)度的雙精度浮點(diǎn)數(shù),1位符號(hào)位,11位指數(shù)位,52位數(shù)據(jù)位。它們互相的關(guān)系就是:int可以穩(wěn)式轉(zhuǎn)換成float和double,float只能強(qiáng)制轉(zhuǎn)換成int,但是可以隱式轉(zhuǎn)換成double,double只能強(qiáng)制轉(zhuǎn)換成float和int。在說(shuō)明問(wèn)題之前,還很有必要溫習(xí)一下計(jì)算機(jī)組成原理時(shí)學(xué)習(xí)到的一些知識(shí),就是二進(jìn)制補(bǔ)碼表示以及浮點(diǎn)數(shù)表示。我想把一個(gè)十進(jìn)

5、制轉(zhuǎn)化為二進(jìn)制的方法已經(jīng)不用多費(fèi)唇舌,只不過(guò)為了計(jì)算方便以及消除正零與負(fù)零的問(wèn)題,現(xiàn)代計(jì)算機(jī)技術(shù),內(nèi)存里存的都是二進(jìn)制的補(bǔ)碼形式,當(dāng)然這個(gè)也沒(méi)什么特別的,只不過(guò)有某些離散和點(diǎn),需要特殊定義而已,比如-(231),這個(gè)數(shù)在int的補(bǔ)碼里表示成1000(31個(gè)零),這個(gè)生套補(bǔ)碼計(jì)算公式并不能得到結(jié)果(其實(shí)不考慮進(jìn)位的話(huà)還真是這個(gè)結(jié)果,但是總讓人感覺(jué)很怪)。再者,浮點(diǎn)數(shù),其實(shí)就是把任何二進(jìn)制數(shù)化成以0.1.開(kāi)頭的科學(xué)計(jì)數(shù)法表示而已。廢話(huà)說(shuō)完,這就出現(xiàn)了幾個(gè)問(wèn)題,而且是比較有意思的問(wèn)題。1 int i = Int32.MaxValue;2 float f = i;3 int j = (int)f;4

6、bool b = i = j;這里的b,是false。剛才這個(gè)操作,如果我們把float換成long,第一次進(jìn)行隱式轉(zhuǎn)換,第二次進(jìn)行強(qiáng)制轉(zhuǎn)換,結(jié)果將會(huì)是true。乍一看,float.MaxValue是比int.MaxValue大了不知道多少倍的,然而這個(gè)隱式轉(zhuǎn)換中,卻造成了數(shù)據(jù)丟失。 int.MaxValue,這個(gè)值等于231-1,寫(xiě)成二進(jìn)制補(bǔ)碼形式就是01111(31個(gè)1),這個(gè)數(shù),在表示成float計(jì)數(shù)的科學(xué)計(jì)數(shù)法的時(shí)候,將會(huì)寫(xiě)成+0.1111(23個(gè)1)*231,對(duì)于那31個(gè)1,里面的最后8個(gè),被float無(wú)情的拋棄了,因此,再將這個(gè)float強(qiáng)制轉(zhuǎn)換回 int的時(shí)候,對(duì)應(yīng)的int的二進(jìn)

7、制補(bǔ)碼表示已經(jīng)變成了0111(23個(gè)1)00000000,這個(gè)數(shù)與最初的那個(gè)int相差了255,所以造成了不相等。那么提出另一個(gè)問(wèn)題,什么樣的int變成float再變回來(lái),和從前的值相等呢?這個(gè)問(wèn)題其實(shí)完全出在那23位float的數(shù)據(jù)位上了。對(duì)于一個(gè)int,把它寫(xiě)成二進(jìn)制形式之后,成為了個(gè)一32個(gè)長(zhǎng)度的0、1的排列,對(duì)于這個(gè)排列,只要第一個(gè)1與最后一個(gè)1之前的間距,不超過(guò)23,那么它轉(zhuǎn)換成 float再轉(zhuǎn)換回來(lái),兩個(gè)值就會(huì)相等。這個(gè)問(wèn)題是與大小無(wú)關(guān)的,而且這個(gè)集合在int這個(gè)全集下并不連續(xù)。1 double d = 0.6;2 float f = (float)d;3 double d2 =

8、f;4 bool b = d = d2;這里的b,也是false。剛才這個(gè)操作,如果開(kāi)始另d等于0.5,結(jié)果就將會(huì)是true。乍一看,0.6這個(gè)數(shù)這么短,double和 float都肯定能夠表示,那么轉(zhuǎn)換過(guò)去再轉(zhuǎn)換回來(lái),結(jié)果理應(yīng)相等。其實(shí)這是因?yàn)槲覀冇檬M(jìn)制思考問(wèn)題太久了,如果我們0.6化成二進(jìn)制小數(shù),可以發(fā)現(xiàn)得到的結(jié)果是0.10011001(1001循環(huán))。這是一個(gè)無(wú)限循環(huán)小數(shù)。因此,不管float還是double,它在存儲(chǔ)0.6 的時(shí)候,都無(wú)法完全保存它精確的值(計(jì)算機(jī)不懂分?jǐn)?shù),呵呵),這樣的話(huà)由于float保存23位,而double保存52位,就造成了double轉(zhuǎn)化成 float的時(shí)候

9、,丟失掉了一定的數(shù)據(jù),非再轉(zhuǎn)換回去的時(shí)候,那些丟掉的值被補(bǔ)成了0,因此這個(gè)后來(lái)的double和從前的double值已經(jīng)不再一樣了。這樣就又產(chǎn)生了一個(gè)問(wèn)題,什么樣的double轉(zhuǎn)換成float再轉(zhuǎn)換回來(lái),兩個(gè)的值相等呢?其實(shí)這個(gè)問(wèn)題與剛才int的那個(gè)問(wèn)題驚人的相似(廢話(huà),都和float打交道,能不相似么),只不過(guò)我們還需要考慮double比f(wàn)loat多了3位的指數(shù)位,太大的數(shù)double能表示但float 不行。還有一個(gè)算是數(shù)學(xué)上的問(wèn)題,什么樣的十進(jìn)制小數(shù),表示成二進(jìn)制不是無(wú)限小數(shù)呢?這個(gè)問(wèn)題可以說(shuō)完全成為數(shù)學(xué)范疇內(nèi)的問(wèn)題了,但是比較簡(jiǎn)單,答案也很明顯,對(duì)于所有的最后一位以5結(jié)尾的十進(jìn)制有限小數(shù)

10、,都可以化成二進(jìn)制的有限小數(shù)(雖然這個(gè)小數(shù)可能長(zhǎng)到?jīng)]譜)。最后,一個(gè)有意思有問(wèn)題,剛才說(shuō)過(guò)0.6表示成為二進(jìn)制小數(shù)之后,是0.1001并且以1001為循環(huán)節(jié)的無(wú)限循環(huán)小數(shù),那么在我們將它存成浮點(diǎn)數(shù)的時(shí)候,一定會(huì)在某個(gè)位置將它截?cái)啵ū热鏵loat的23位和double的52位),那么真正存在內(nèi)存里的這個(gè)二進(jìn)制數(shù),轉(zhuǎn)化回十進(jìn)制,到底是比原先的十進(jìn)制數(shù)大呢,還是小呢?答案是It depends。人計(jì)算十進(jìn)制的時(shí)候,是四舍五入,計(jì)算機(jī)再計(jì)算二進(jìn)制小數(shù)也挺簡(jiǎn)單,就是0舍1入。對(duì)于float,要截?cái)喑蔀?3位,假如卡在24位上的是1,那么就會(huì)造成進(jìn)位,這樣的話(huà),存起來(lái)的值就比真正的十進(jìn)制值大了,如果是0,

11、就舍去,那么存起來(lái)的值就比真正的十進(jìn)制值小了。因此,這可以合理的解釋一個(gè)問(wèn)題,就是0.6d轉(zhuǎn)換成float再轉(zhuǎn)換回double,它的值是0.60000002384185791,這個(gè)值是比0.6大的,原因就是 0.6的二進(jìn)制科學(xué)計(jì)數(shù)法表示,第24位是1,造成了進(jìn)位。到了這里,仍然有一事不解,就是對(duì)于浮點(diǎn)數(shù),硬件雖然給予了計(jì)算上的支持,但是它與十進(jìn)制之間的互相轉(zhuǎn)換,到底是如何做到的呢,又是誰(shuí)做的呢(匯編器還是編譯器)。這個(gè)東西突出體現(xiàn)在存在內(nèi)存里的數(shù)明顯實(shí)際與0.6不等,但是無(wú)論哪種語(yǔ)言,都能夠在Debug以及輸入的時(shí)候,將它正確的顯示成 0.6提供給用戶(hù)(程序員),最好的例子就是double和T

12、oString方法,如果我寫(xiě)double d=0.59999999999999999999999999999,d.ToString()給我的是0.6。誠(chéng)然,對(duì)于double來(lái)說(shuō),我寫(xiě)的那個(gè)N長(zhǎng)的數(shù)與0.6在內(nèi)存里存的東西是一樣的,但是計(jì)算機(jī),又如果實(shí)現(xiàn)了將一個(gè)實(shí)際與0.6不相等的數(shù)變回0.6并顯示給我的呢?關(guān)于這個(gè)問(wèn)題,歡迎大家討論并請(qǐng)高手指教一二。從“交換兩個(gè)變量而不用臨時(shí)變量”談起-問(wèn)題:寫(xiě)一個(gè)函數(shù),實(shí)現(xiàn)交換兩個(gè)變量,但不能用臨時(shí)變量? 分析:交換兩個(gè)變量的這一功能,我們用的比較多,也可以很容易的寫(xiě)出一個(gè)出來(lái),但是題目要求的是不能用臨時(shí)變量。并且題目也沒(méi)有說(shuō)明變量是什么類(lèi)型,它是 int,

13、char,double,還是自定義的結(jié)構(gòu)體,或者是類(lèi)類(lèi)型,雖然可以用模板從某種程度上解決這一些問(wèn)題,但對(duì)于自定義的類(lèi)型,還是不是很好處理。在這里先從最簡(jiǎn)單的說(shuō)起,假設(shè)這里的變量是int型的。一般如果我們要寫(xiě)一個(gè)交換整形變量的代碼是1:  inline void Swap(int *a,int *b)2:  3:       int temp;4:       temp=*a;5:       *a

14、=*b;6:       *b=*a;7:  我們用到了臨時(shí)變量temp。思考一個(gè)問(wèn)題我們?yōu)槭裁匆玫脚R時(shí)變量呢?我們平常交換東西時(shí),是否用到了臨時(shí)的媒介呢?比方說(shuō)我手上有一個(gè)蘋(píng)果,你手上有一個(gè)桔子,我想和你交換,是如何進(jìn)行的,用到媒介沒(méi)有呢?我們好像是直接交換的,這其中似乎沒(méi)有用到什么媒介,但是仔細(xì)想想過(guò)程是用到了媒介的。交換可以歸納為兩種方法,1:將物品直接從一個(gè)人的左手放到一個(gè)人的右手2:借助其它的容器,如果盤(pán),先將物品放在果盤(pán)中,再去拿自己要的。其實(shí)這兩個(gè)也只是一個(gè)方法而已,第一個(gè)借助的“容器”是我們的身上的另一只空

15、閑的手,很容易忽略掉這個(gè)問(wèn)題,以為我們沒(méi)有用到其它媒介,要是想想我們只有一只手如何交換呢。結(jié)論1:物質(zhì)是有載體的,不管這物質(zhì)是實(shí)體的,還是虛體。一個(gè)載體在同一時(shí)間上只能承載一種物質(zhì),于是在交換兩個(gè)載體承載的物質(zhì)時(shí),是不可能同時(shí)進(jìn)行的,估都要用到其它的媒介載體?;氐接?jì)算機(jī)的問(wèn)題上,存放變量也有載體的,它是內(nèi)存,而變量可以說(shuō)是一種虛體物質(zhì)。這從直觀上解釋一般為什么我們寫(xiě)交換變量函數(shù)時(shí)要用到臨時(shí)變量,也直接反映了編程不是離生活很遠(yuǎn)的,它不是另一個(gè)世界的思維。即然如此,是不是沒(méi)有辦法了?方法只給那些勤于思考的人的。是一定要用到載體媒介嗎?不用到就不行嗎?結(jié)合程序設(shè)計(jì)特點(diǎn),可以有如下的代碼1: 

16、; inline void Swap(int *a,int *b)2:  3:      *a=*a+*b;4:      *b=*a-*b;5:      *a=*a-*b;6:  是不是很有意思,真的沒(méi)有用到其它的臨時(shí)變量啊!那我們上面的結(jié)論1是不是錯(cuò)了呢?當(dāng)然不是,為什么可以直接就可以交換了呢?還是用上面的例子來(lái)說(shuō),兩個(gè)人交換蘋(píng)果和桔子但是每人只有一個(gè)手,也不借助其它的容器,那如何進(jìn)行喲?有辦法,就只是用一個(gè)手拿兩樣?xùn)|西

17、,也就是說(shuō)先將蘋(píng)果(桔子)給另一個(gè)人用一只手拿著,再?gòu)乃稚夏媒圩樱ㄌO(píng)果)?;疽簿褪谴a的意思了。結(jié)論2:看似不可能,但卻可以的,要做的是仔細(xì)的去挖掘,多思考。那上面的代碼是不是就沒(méi)有問(wèn)題了?有。要考慮溢出的問(wèn)題,程序中有一個(gè)加法,很可能使結(jié)果超出范圍,也就是說(shuō)一只手要是拿不了一個(gè)蘋(píng)果和桔子怎樣辦?要相信有問(wèn)題是可以解決的,可以用assert等等方面處理一下,但不是最好,繼續(xù)有如下的代碼1:  inline void Swap(int *a, int *b)2:  3:     *a = *b;4:   

18、;  *b = *a;5:     *a = *b;6:  這是什么?一眼看不出是什么是嗎?不慌,我們可以慢慢的一步步的分析。對(duì)于位運(yùn)算與、或、非,我們?cè)谔幚頂?shù)據(jù)的時(shí)候是經(jīng)常要用到的。我們經(jīng)常要用到的東西也是在基礎(chǔ)的。設(shè)uBitTest為測(cè)試數(shù),值為2n,也就是第n位為1。uDate為需要處理的數(shù)據(jù)。1.將uDate的第n位置1uDate = uDate|uBitTest2.將uDate的第n位置0uDate = uDate&uBitTest3.將uDate的第n位取反uDate = uDate uBitTest掌握熟悉了這些

19、在看上面的代碼是不是要輕松多了,不是要溢出嗎?不是一只手拿不下蘋(píng)果和桔子嗎?不要緊,我們可以一部分的交換啊,把蘋(píng)果切開(kāi),桔子剝開(kāi)來(lái)去交換,這樣總可以拿下來(lái)吧。結(jié)論3:載體承載物質(zhì)是必需的,我們不能以改變,卻可以改變載體承載的性質(zhì)。載體的容量大小不能改變,但可以去改變承載物體的大小,照樣可以達(dá)到想要的目的。真的是山窮水復(fù)疑無(wú)路,柳暗花明又一村。到這里為止,對(duì)于簡(jiǎn)單的整形變量的交換的情況,已經(jīng)基本上說(shuō)清楚了,但并不是說(shuō)可以去支持任何類(lèi)型,在這里只是從最簡(jiǎn)單的例子開(kāi)始,只是起個(gè)引子的作用,是給一些思路的問(wèn)題。對(duì)于這個(gè)問(wèn)題,還可以從內(nèi)聯(lián)匯編的方面去處理,可以看看匯編的代碼是如何,從中得到一些啟發(fā);對(duì)于

20、各種不同類(lèi)型處理也有其各自的問(wèn)題需要去處理,如對(duì)于類(lèi)對(duì)象怎樣去處理拷貝。對(duì)于好的庫(kù)也可以去看看他們是怎樣去寫(xiě)swap這個(gè)函數(shù)的。如stl,boost等,從中應(yīng)該可以學(xué)到不少的。巧用C的Time函數(shù)進(jìn)行時(shí)間轉(zhuǎn)換-我們經(jīng)常要遇到時(shí)間處理的問(wèn)題,比如要開(kāi)發(fā)一個(gè)schedule的功能,或根據(jù)修改時(shí)間來(lái)過(guò)濾文件等。windows API提供了Get*Time()系列函數(shù)用于獲取當(dāng)前時(shí)間,但是沒(méi)有提供進(jìn)行時(shí)間轉(zhuǎn)換的,比如我們要得到距離當(dāng)前時(shí)間2年4個(gè)月5天的時(shí)間,我們就得自己去計(jì)算了。但是這里有個(gè)問(wèn)題,如果被減的天數(shù)大于當(dāng)前月份的天數(shù),那么天數(shù)就會(huì)變成負(fù)值。為了解決這個(gè)問(wèn)題,我們就根據(jù)不同月份的天數(shù)來(lái)計(jì)算

21、偏移,同時(shí)做月和年的變化。不過(guò)這種方法很麻煩,因?yàn)槊總€(gè)月天數(shù)是不同的還需要考慮閏年和平年的問(wèn)題。其實(shí)C的Time系列函數(shù)可以很好的解決這個(gè)問(wèn)題, 1. 首先用TM結(jié)構(gòu)進(jìn)行需要的時(shí)間偏移2. 然后利用mktime這個(gè)函數(shù)將TM結(jié)構(gòu)轉(zhuǎn)換到從1900.1.1開(kāi)始的秒數(shù)值3. 再利用localtime 把秒數(shù)轉(zhuǎn)換成TM結(jié)構(gòu)示例代碼如下:代碼#include "stdafx.h"#include <Windows.h>#include <time.h>#include <iostream>using namespace std;void Offse

22、tDateTime(const struct tm* inST, struct tm* outST,int dYears, int dMonths, int dDays,int dHours, int dMinutes, int dSeconds)if (inST != NULL && outST != NULL)/ 偏移當(dāng)前時(shí)間outST->tm_year = inST->tm_year - dYears;outST->tm_mon  = inST->tm_mon  - dMonths;outST->tm_mday = inS

23、T->tm_mday - dDays;outST->tm_hour = inST->tm_hour - dHours;outST->tm_min  = inST->tm_min  - dMinutes;outST->tm_sec  = inST->tm_sec  - dSeconds;/ 轉(zhuǎn)換到從1900.1.1開(kāi)始的總秒數(shù)time_t newRawTime = mktime(outST);/ 將秒數(shù)轉(zhuǎn)換成時(shí)間結(jié)構(gòu)體outST = localtime(&newRawTime);int _tmain(int

24、 argc, _TCHAR* argv)time_t rawtime;struct tm * st;/ 獲取本地當(dāng)前時(shí)間time(&rawtime);st = localtime(&rawtime);cout << st->tm_year << "-" << st->tm_mon << "-" << st->tm_mday << endl;/ 計(jì)算時(shí)間偏移struct tm outst;OffsetDateTime(st, &outst, 2

25、, 3, 20, 0, 0, 0);time_t newTime = mktime(&outst);cout << outst.tm_year << "-" << outst.tm_mon << "-" << outst.tm_mday << endl;cout << "rawTime: " << rawtime << endl << "newTime :" << newTim

26、e << endl;return 0;C語(yǔ)言中標(biāo)準(zhǔn)輸入流、標(biāo)準(zhǔn)輸出流、標(biāo)準(zhǔn)錯(cuò)誤輸出流-在Linux中,所有對(duì)設(shè)備和文件的操作都使用文件描述符來(lái)進(jìn)行。 Linux中一個(gè)進(jìn)程啟動(dòng)時(shí),都會(huì)打開(kāi)3個(gè)文件:標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)出錯(cuò)處理。這三個(gè)文件分別對(duì)應(yīng)文件描述符0、1、2。在C語(yǔ)言中,在程序開(kāi)始運(yùn)行時(shí),系統(tǒng)自動(dòng)打開(kāi)3個(gè)標(biāo)準(zhǔn)文件:標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)出錯(cuò)輸出。通常這3個(gè)文件都與終端相聯(lián)系。因此,以前我們所用到的從終端輸入或輸出都不需要打開(kāi)終端文件。系統(tǒng)自定義了3個(gè)文件指針 stdin、stdout、stderr,分別指向終端輸入、終端輸出和標(biāo)準(zhǔn)出錯(cuò)輸出(也從終端輸出)。標(biāo)準(zhǔn)輸入流:s

27、tdin標(biāo)準(zhǔn)輸出流:stdout標(biāo)準(zhǔn)錯(cuò)誤輸出流:stderrstdinobject<cstdio>FILE * stdin;Standard input streamThe standard input stream is the default source of data for applications. It is usually directed to the input device of the standard console (generally, a keyboard).stdin can be used as an argument for any funct

28、ion that expects an input stream as one of its parameters, like fgets or fscanf.Although it is generally safe to assume that the source of data for stdin is going to be a keyboard, bear in mind that this may not be the case even in regular console systems, since stdin can be redirected at the operat

29、ing system level. For example, many systems, among them DOS/Windows and most UNIX shells, support the following command syntax:myapplication < example.txtto use the content of the file example.txt as the primary source of data for myapplication instead of the console keyboard.It is also possible

30、to redirect stdin to some other source of data from within a program using the freopen function.stdoutobject<cstdio>FILE * stdout;Standard output streamThe standard output stream is the default destination of regular output for applications. It is usually directed to the output device of the s

31、tandard console (generally, the screen).stdout can be used as an argument for any function that expects an output stream as one of its parameters, like fputs or fprintf.Although it is generally safe to assume that the default destination for stdout is going to be the screen, bear in mind that this m

32、ay not be the case even in regular console systems, since stdout can be redirected at the operating system level. For example, many systems, among them DOS/Windows and most UNIX shells, support the following command syntax:myapplication > example.txtto redirect the output of myapplication to the

33、file example.txt instead of the screen.It is also possible to redirect stdout to some other source of data from within a program using the freopen function.stderrobject<cstdio>FILE * stderr;Standard error streamThe standard error stream is the default destination for error messages and other d

34、iagnostic warnings. Like stdout, it is usually also directed to the output device of the standard console (generally, the screen).stderr can be used as an argument for any function that expects an output stream as one of its parameters, like fputs or fprintf.Although generally both stdout and stderr

35、 are associated with the same console output, applications may differentiate between what is sent to stdout and what to stderrfor the case that one of them is redirected. For example, it is frequent to redirect the regular output of a console program (stdout) to a file while expecting the error mess

36、ages to keep appearing in the console screen.It is also possible to redirect stderr to some other destination from within a program using the freopen function.perrorfunction<cstdio>void perror ( const char * str );Print error messageInterprets the value of the global variable errno into a stri

37、ng and prints that string to stderr (standard error output stream, usually the screen), optionaly preceding it with the custom message specified in str.errno is an integral variable whose value describes the last error produced by a call to a library function. The error strings produced by perror de

38、pend on the developing platform and compiler.If the parameter str is not a null pointer, str is printed followed by a colon (:) and a space. Then, whether str was a null pointer or not, the generated error description is printed followed by a newline character (''n'').perror should b

39、e called right after the error was produced, otherwise it can be overwritten in calls to other functions.Parameters.strC string containing a custom message to be printed before the error message itself.If it is a null pointer, no preceding custom message is printed, but the error message is printed

40、anyway.By convention, the name of the application itself is generally used as parameter.獲取當(dāng)前系統(tǒng)所有進(jìn)程-#include "stdafx.h" #include <windows.h>#include <tlhelp32.h>int main(int argc, char* argv)HANDLE hSnapshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);if (!hSnapshot)print

41、f("CreateToolhelp32Snapshot ERROR!n");return 1;PROCESSENTRY32 pe32;pe32.dwSize = sizeof(PROCESSENTRY32 );if (!Process32First (hSnapshot, &pe32)printf("Process32First ERROR!n");doprintf("ProcID:%d-%sn",pe32.th32ProcessID ,pe32.szExeFile );while(Process32Next (hSnapsh

42、ot, &pe32);return 0;有趣的位運(yùn)算-今天碰到一個(gè)問(wèn)題:在不增加新的變量的情況下,交換兩個(gè)int型變量的值。題目描述很簡(jiǎn)單,但是考慮起來(lái)還是比較有難度的。這里提出一個(gè)位運(yùn)算的妙用:異或的妙用 異或是這樣一種運(yùn)算:如果兩位相同,同為1或同為0,那么異或?yàn)?,否則異或?yàn)?.同時(shí)需要說(shuō)明的是,在進(jìn)行異或運(yùn)算的是補(bǔ)碼。知道規(guī)則以后,我們可以來(lái)看這個(gè)問(wèn)題了。這個(gè)題目可以這樣做:假設(shè)兩個(gè)int型變量a,b: int a, b;a = a b;b = a b;a = a b;hoho!3次同樣的操作,完成了這樣一個(gè)神奇的運(yùn)算,位運(yùn)算大有可為。C中如何顯示*.bmp文件-1.*.bmp

43、文件結(jié)構(gòu) *.bmp文件和大多數(shù)圖形文件一樣,分為文件描述區(qū)(頭文件信息)和圖象存儲(chǔ)區(qū)(象素?cái)?shù)據(jù))兩部分。而頭文件信息中又包含了信息區(qū)和調(diào)色板區(qū)兩部分,信息區(qū)又可以細(xì)分為文件信息區(qū)和圖象信息區(qū)兩部分。這里以256色320*200的bmp圖象為例。頭文件描述區(qū)的偏移長(zhǎng)度是1078個(gè)字節(jié),也就是說(shuō)圖象存儲(chǔ)區(qū)是從文件偏移1078后開(kāi)始讀取的。在頭文件描述區(qū)中頭信息區(qū)的偏移長(zhǎng)度是54個(gè)字節(jié),也就是說(shuō)調(diào)色板數(shù)據(jù)區(qū)是從54-1078之間的1024字節(jié)。在頭信息區(qū)中文件信息區(qū)占14個(gè)字節(jié)而圖象信息區(qū)占40字節(jié)。(1) 文件信息區(qū)typedef struct BMP_fileunsigned int bfTy

44、pe; /文件類(lèi)型unsigned long bfSize; /bmp文件長(zhǎng)度unsigned int Reserved1;unsigned int Reserved2;unsigned long bfOffset; /文件描述區(qū)長(zhǎng)度,16色為118,256色為1078bitmapfile;現(xiàn)在算一下,有3個(gè)int,2個(gè)long,正好3*2+2*4=14字節(jié)(2) 圖象信息區(qū)type struct BMP_infounsigned long biSize;unsigned long biWidth;unsigned long biHeight;unsigned int biPlanes;uns

45、igned int biBitCount;unsigned long biCompression;unsigned long biSizeImage;unsigned long biXplosPerMeter;unsigned long biYplosPerMeter;unsigned long biClrUsed;unsigned long biClrImportant;bitmapinfo;現(xiàn)在算一下,2個(gè)int,9個(gè)long,正好是2+2*9*4=40字節(jié)。(3)調(diào)色板區(qū)typedef struct RGB_BMP_typunsigned char blue;unsigned char

46、green;unsigned char red;unsigned char reserved;RGB_BMP,*RGB_BMP_ptr;說(shuō)明:三原色+灰度,共4*256=1024字節(jié)。下面是bmp文件的完整的結(jié)構(gòu)定義:typedef struct bmp_picture_typbitmapfile file;bitmapinfo info;RGB_BMP palette256;char far *buffer;bmp_picture, *bmp_picture_ptr;2. bmp文件的顯示(1)圖象存儲(chǔ)區(qū)的讀取由于bmp圖象是從下至上存儲(chǔ)的,所以我們不能進(jìn)行直接順序讀取。詳細(xì)的說(shuō),bmp圖象

47、存儲(chǔ)區(qū)數(shù)據(jù)是從1078偏移字節(jié)開(kāi)始。文件內(nèi)第一個(gè)圖象點(diǎn)實(shí)際上是對(duì)應(yīng)圖象(320*200)第200行的最左邊的第一個(gè)點(diǎn),而從1078開(kāi)始的320個(gè)點(diǎn)則是圖象最下面一行對(duì)應(yīng)的點(diǎn),之后的321個(gè)點(diǎn)是圖象倒數(shù)第二行最左邊的第一個(gè)點(diǎn)。這樣,bmp文件最后一個(gè)字節(jié)對(duì)應(yīng)的點(diǎn)是第一行最后邊的點(diǎn)了。下面是實(shí)現(xiàn)bmp文件圖象存儲(chǔ)區(qū)數(shù)據(jù)讀取到內(nèi)存的代碼:for(i=info.biHeight-1;i>=0;i-)lseek(fp,1078+(long)(info.biHeight-i-1)*info.biWidth,0);read(fp,&bmp256->bufferi*info.biWidth

48、,info.biWidth);(2)調(diào)色板的讀取除了圖象存儲(chǔ)區(qū)的存放規(guī)則是倒序的以外,bmp文件調(diào)色板內(nèi)容也是以B,G,R,灰度的順序存放的。所以讀取時(shí)不要將文件中的三原色中的蘭色對(duì)應(yīng)給調(diào)色板結(jié)構(gòu)體變量中的紅色。同時(shí),由于三原色只使用64種(6位)色階,而三原色的存放空間是1字節(jié)(8位),所以要將bmp文件三原色的6位數(shù)據(jù)都放在1個(gè)字節(jié)的高位,則在讀取調(diào)色板結(jié)構(gòu)體變量的時(shí)候必須進(jìn)行右移2位。以下給出讀取文件調(diào)色板數(shù)據(jù)的代碼for(i=0;i<256;i+)read(fp,&bmp256->palette.blue,1);read(fp,&bmp256->pal

49、ette.green,1);read(fp,&bmp256->palette.red,1);read(fp,&bmp256->palette.reserved,1);bmp256->palette.blue=bmp256->palette.blue>>2;bmp256->palette.green=bmp256->palette.green>>2;bmp256->palette.red=bmp256->palette.red>>2;以下給出寫(xiě)入調(diào)色板函數(shù)void Set_BMP_Palette_

50、Register(int index,RGB_BMP_ptr color)outp(PALETTE_MASK,0XFF);outp(PALETTE_REGISTER_WR,index); /*確定調(diào)色板序號(hào)*/outp(PALETTE_DATA,color->red); /*設(shè)置該序號(hào)為紅色*/outp(PALETTE_DATA,color->green); /*設(shè)置該序號(hào)為綠色*/outp(PALETTE_DATA,color->blue); /*設(shè)置該序號(hào)為蘭色*/調(diào)用調(diào)色板的代碼:for(i=0;i<256,i+)Set_BMP_Palette_Register(

51、i,(RGB_BMP_ptr) &bmp256->palette);現(xiàn)在我們開(kāi)始進(jìn)行完整的讀取(1)申請(qǐng)內(nèi)存空間(2)檢查頭文件信息區(qū)(3)讀取調(diào)色板數(shù)據(jù)(4)讀取位圖到內(nèi)存(5)顯示圖象(6)內(nèi)存釋放(1)申請(qǐng)內(nèi)存:由于320*200是64K,而C程序允許用戶(hù)申請(qǐng)的內(nèi)存空間也只有64K,為了防止一次申請(qǐng)不到,我們可以分幾次申請(qǐng)。使用malloc()函數(shù)就可以。(2)檢查頭文件信息區(qū):A:判斷是不是bmp文件(若不是,則無(wú)法顯示)B:文件是否為壓縮格式(若是,則無(wú)法處理)C:文件是否為256色以下給出讀取頭文件信息到內(nèi)存的代碼:read(fp,&bmp256->fi

52、le,sizeof(bitmapfile);read(fp,&bmp256->info,sizeof(bitmapinfo);以下是檢測(cè)bmp文件格式的函數(shù):void Check_Bmp(bmp_picture_ptr bmp_ptr)if(bmp_ptr->file.bfType!=0x4d42) /*檢測(cè)是不是bmp文件*/printf("Not a BMP file! ");exit(1);if(bmp_ptr->info.biCompression!=0) /*檢測(cè)是不是壓縮文件,1表示壓縮,0表示沒(méi)壓縮*/printf("Can

53、 not display a compressed bmp file! ");exit(1);if(bmp_ptr->info.biBitCount!=8) /*檢測(cè)是不是256色*/printf("Not a index 256color bmp file! ");exit(1);(3)和(4)前面有介紹,這兒省略。(5)顯示圖象假設(shè)bmp文件的調(diào)色板區(qū)已寫(xiě)入計(jì)算機(jī)調(diào)色板,bmp文件圖象存儲(chǔ)區(qū)也已寫(xiě)到內(nèi)存,以下給出具體的顯示到屏幕的函數(shù)void BMP_Show_Buffer2(bmp_picture_ptr image)memcpy(char far *

54、)video_buffer,(char far *)image->buffer,(unsigned int)info->biWidth*info->biHight/2)(6)釋放內(nèi)存void BMP_Delete(bmp_picture_ptr image)free(image->buffer);好了,經(jīng)過(guò)以上幾步,基本上你的bmp文件就能在C中顯示了。當(dāng)然前提是你使用256色的圖形驅(qū)動(dòng)。也就是你的int gdrive=DETECT應(yīng)該改為int gdrive=6;如果你僅僅顯示16色的文件,就沒(méi)有必要了。用extern聲明外部變量-全局變量(外部變量)是在函數(shù)的外部定

55、義的,它的作用域?yàn)閺淖兞康亩x處開(kāi)始,到本程序文件的末尾。在此作用域內(nèi),全局變量可以為本文件中各個(gè)函數(shù)所引用。編譯時(shí)將全局變量分配在靜態(tài)存儲(chǔ)區(qū)。 有時(shí)需要用extern來(lái)聲明全局變量,以擴(kuò)展全局變量的作用域。1. 在一個(gè)文件內(nèi)聲明全局變量如果外部變量不在文件的開(kāi)頭定義,其有效的作用范圍只限于定義處到文件終了。如果在定義點(diǎn)之前的函數(shù)想引用該全局變量,則應(yīng)該在引用之前用關(guān)鍵字extern對(duì)該變量作外部變量聲明,表示該變量是一個(gè)將在下面定義的全局變量。有了此聲明,就可以從聲明處起,合法地引用該全局變量,這種聲明稱(chēng)為提前引用聲明。例4.14 用extern對(duì)外部變量作提前引用聲明,以擴(kuò)展程序文件中的作

56、用域。#include <iostream>using namespace std;int max(int,int);              /函數(shù)聲明void main( )extern int a,b;               /對(duì)全局變量a,b作提前引用聲明cout<<max(a,b)<

57、;<endl;int a=15,b=-7;                  /定義全局變量a,bint max(int x,int y)int z;z=x>y?x:y;return z;運(yùn)行結(jié)果如下:15在main后面定義了全局變量a,b,但由于全局變量定義的位置在函數(shù)main之后,因此如果沒(méi)有程序的第5行,在main函數(shù)中是不能引用全局變量a和b的?,F(xiàn)在我們?cè)趍ain函數(shù)第2行用extern對(duì)a和b作了提前引用

58、聲明,表示a和b是將在后面定義的變量。這樣在main函數(shù)中就可以合法地使用全局變量a和b了。如果不作extern聲明,編譯時(shí)會(huì)出錯(cuò),系統(tǒng)認(rèn)為a和b未經(jīng)定義。一般都把全局變量的定義放在引用它的所有函數(shù)之前,這樣可以避免在函數(shù)中多加一個(gè)extern聲明。2. 在多文件的程序中聲明外部變量如果一個(gè)程序包含兩個(gè)文件,在兩個(gè)文件中都要用到同一個(gè)外部變量num,不能分別在兩個(gè)文件中各自定義一個(gè)外部變量num。正確的做法是:在任一個(gè)文件中定義外部變量num,而在另一文件中用extern對(duì)num作外部變量聲明。即extern int num;編譯系統(tǒng)由此知道num是一個(gè)已在別處定義的外部變量,它先在本文件中找

59、有無(wú)外部變量num,如果有,則將其作用域擴(kuò)展到本行開(kāi)始(如上節(jié)所述),如果本文件中無(wú)此外部變量,則在程序連接時(shí)從其他文件中找有無(wú)外部變量num,如果有,則把在另一文件中定義的外部變量num的作用域擴(kuò)展到本文件,在本文件中可以合法地引用該外部變量num。分析下例:file1.cpp                          

60、0;                  file2.cppextern int a,b;                                 

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論