本文目錄一覽:
c語言問題
一、 演算法設計及流程
1. 點
不管什麼樣的圖形歸根結底到屏幕,都是由一些顏色不一的象素點組成,為提高圖形的顯示效率,沒有用到系統的畫點函數,而採用了640*480*16模式下的直接寫屏技術畫點,該模式下的直接寫屏比320*200*256的直接寫屏要複雜的多,後者的視頻緩衝區是線性編址的,一個位元組對應屏幕上一點的顏色,而前者的視頻緩衝區被分成四個位面,屏幕上一點的顏色由每個位面上的一位組成的四位二進位數決定,由於四位二進位數的最大表示範圍是16,所以在這種模式下最多可同時顯示16種顏色。
在對視頻緩衝區的讀寫時,是一個位元組一個位元組寫的,只需要其中某一位時,就要用到位掩碼屏蔽掉其他的位,位掩碼就在圖形控制寄存器的位屏蔽寄存器里設置。先通過向埠號為0x3ce的索引寄存器寫入位屏蔽寄存器的索引號8,然後向埠號為0x3cf的寄存器寫入位掩碼值。設置好位掩碼後,直接向視頻緩衝區相應位置寫入顏色即為畫點函數。
取屏幕上一點顏色其實也就是畫點的反操作,畫點是將一個四位的二進位顏色值分配到四個位面,而取一點的顏色是將四個位面的顏色組合成一個四位二進位數。
2. 線
線其實就是由點組成的,通過連續的改變點的坐標,也就可以得到一條線。所以畫線的函數歸根結底也就是如何改變畫點的坐標。
畫線通常有DDA演算法,BRESENHAM演算法,這裡採用的是BRESENHAM演算法。這種演算法從根本上講,是通過橫線與豎線的倍數關係來實現的。每次循環畫點後x、y中位移大的坐標變化一個單位,而當循環次數是兩者倍數關係時,x、y中位移小的坐標變化一個單位。為了使畫線函數能在八個方向都能畫,將增量為負的都轉化正的增量。
畫圖程序經常要用到moveto、lineto等函數,用於把點移動到某點或從當前點畫線到某點,為了模擬這些函數,設置了SX,SY兩個全局變數用來作為Moveto()的目的地和Drawlineto()的起始坐標。
3. 矩形及填充矩形
矩形是通過兩點確定的對角線來畫的,直接連上各點的坐標就可以了。填充矩形是通過一條線一條線畫的。這種演算法速度比較慢,較好的方法是用Fillscreen()裡面用到的方法,那是一個位元組一個位元組處理的。就因為畫矩形並不一定是整位元組開始整位元組結束的,開始處和結尾處就有了問題。我也把它們單獨拿出來處理,但還是沒做好,等有時間了再改吧。
4. 圓及弧
畫圓採用的是參數方程的方法。為了提高速度,角度的sin、cos值建立了一個表,要用時直接查表。這是因為在用BRESENHAM演算法畫橢圓時,效果不是很好,畫的橢圓不但厚薄不一,而且不閉合。估計是程序哪裡出問題了,乾脆都用參數方程的方法,又簡單,又省事。我這人通常是比較懶的。
弧主要是用來畫圓角矩形的,且只能畫圓弧。這也是用參數方程來畫的,跟畫圓不同的只是有了角度的限制。
5. 貝塞爾曲線
貝塞爾曲線其實主要也就是一個公式,跟參數方程畫圓是一回事,只是要傳入的參數要多一些。在用滑鼠控制時,因為有四個點,而用滑鼠對多點的採集有點不好做,於是先就初始化了一個四點的數組,用不按鍵、按左鍵、按右鍵分別控制三個點,左右鍵同時按時,確定下一條曲線。
其實用滑鼠畫貝塞爾曲線因該把一次、二次、三次的處理函數都寫出來,在按下左鍵時,標記下這點,再一次按下左鍵時,用畫一次貝塞爾曲線的函數畫,按下第三次時,用畫二次曲線的函數畫,按下第四次時才用畫三次曲線的函數畫。這樣就不用為每個點分配一個滑鼠按鍵了。
6. 填充
填充也是採用的種子填充法,不過不是直接從種子開始填色,而是先從種子出發,找到種子沿x最小的邊界,然後填上一點,判斷這一點的上邊一點和下邊一點,如果不為邊界並且未被填色,則壓入棧中,然後x增1後判斷是否到達這一行x的最大值(既邊界),如不是,則循環處理這一行,直到到達邊界,再彈出一個點繼續循環處理。由於是一個點一個點處理,所以速度比較慢。
為了對一個圖形的不同顏色邊界也能填充,填色時沒有傳入圖形的邊界顏色,而是採用先取出種子的顏色,在填充下一個點時,把下一點的顏色和種子顏色比較,如果相同則填色,不同則作為邊界。
7. 漢字及字元
圖形模式下顯示漢字其實是一件比較麻煩的事,一般要用到漢字字型檔,生成的可執行文件也得在有字型檔的環境下運行。我這裡採用了漢字無字型檔技術,生成的文件不依賴任何其他文件。
無字型檔技術是通過從字型檔文件提取需要的中文點陣字模建立一個類似字型檔的字型檔數組。它可以大大提高漢字的顯示速度。在建立字型檔數組時,將字模數組進行了排序,所以在顯示漢字時
文章來自: 好喜愛學習網() 網址:
求51單片機模擬程序c語言的
用51單片機設計多路競賽搶答器,這種題目,在百度上真是泛濫成災了,隨便一搜就能搜到一大堆,有模擬圖和程序全部資料的。或者百度文庫里也同樣可以搜索到,還是畢業論文,更是詳細。
下圖是一個8路搶答器的模擬圖。
請大家幫忙用C語言換種方法表達下面單片機的編程,但其單片機模擬的結果要與原來完全一樣。
假定原語句和標點符號是對的,例如 while(S2==0); 帶分號。– 不給你修改。
把變數改用數組:
#includereg52.h
#define uint unsigned int
#define uchar unsigned char
sbit S[4];
sbit LAMP[4];
void main()
{
int i;
for (i=0;i4;i++) {
S[i]=P1^i;
LAMP[i]=P2^i;
}
for (i=0;i4;i++){
if (S[i]==0){
while(S[i]==0);
LAMP[i]=~LAMP[i];
};
}
C語言類型強制轉換的注意事項
1.類型說明符和表達式都必須加括弧(單個變數可以不加括弧),如把(int)(x+y)寫成(int)x+y則成了把x轉換成int型之後再與y相加了。
2.無論是強制轉換或是自動轉換,都只是為了本次運算的需要而對變數的數據長度進行的臨時性轉換,而不改變數據說明時對該變數定義的類型。
例1:
main()
{
float f=5.75;
printf(f=%d,f=%f\n,(int)f,f);
}
f=5,f=5.750000
將float f強制轉換成int f float f=5.75;printf((int)f=%d,f=%f\n,(int)f,f); 本例表明,f雖強制轉為int型,但只在運算中起作用, 是臨時的,而f本身的類型並不改變。因此,(int)f的值為 5(刪去了小數)而f的值仍為5.75。
例2:
比如我們可以(int)’A’,這樣轉換後的結果為A的ASCII碼數值,因為那塊內存本來就存的那個數,只是換個形式使用而已。 知道上面的原則,我們可以對任何數據類型進行轉換,但是轉換的結果可能不是你想像的結果,舉例(int)’9’的結果為多少?不是9而是0x39。來個高深點的printf(%d,『12』);的輸出是什麼?正確答案是12594,因為printf(%d,’12’),列印的是存儲12的內存地址上的內容,即ASCII碼值2存儲在低位,1儲在高位地址,0x32就是2的ASCII碼,0x31就是1的ASCII碼,所以是0x3132,轉換成10進位就是12594!
● 字元型變數的值實質上是一個8位的整數值,因此取值範圍一般是-128~127,char型變數也可以加修飾符unsigned,則unsigned char 型變數的取值範圍是0~255(有些機器把char型當做unsighed char型對待, 取值範圍總是0~255)。
● 如果一個運算符兩邊的運算數類型不同,先要將其轉換為相同的類型,即較低類型轉換為較高類型,然後再參加運算,轉換規則如下圖所示。
double ←── float 高
↑
long
↑
unsigned
↑
int ←── char,short 低
● 圖中橫向箭頭表示必須的轉換,如兩個float型數參加運算,雖然它們類型相同,但仍要先轉成double型再進行運算,結果亦為double型。 縱向箭頭表示當運算符兩邊的運算數為不同類型時的轉換,如一個long 型數據與一個int型數據一起運算,需要先將int型數據轉換為long型, 然後兩者再進行運算,結果為long型。所有這些轉換都是由系統自動進行的, 使用時你只需從中了解結果的類型即可。這些轉換可以說是自動的,當然,C語言也提供了以顯式的形式強制轉換類型的機制。
● 當較低類型的數據轉換為較高類型時,一般只是形式上有所改變, 而不影響數據的實質內容, 而較高類型的數據轉換為較低類型時則可能有些數據丟失。
賦值中的類型轉換
當賦值運算符兩邊的運算對象類型不同時,將要發生類型轉換, 轉換的規則是:把賦值運算符右側表達式的類型轉換為左側變數的類型。具體的轉換如下:
(1) 浮點型與整型
● 將浮點數(單雙精度)轉換為整數時,將捨棄浮點數的小數部分, 只保留整數部分。將整型值賦給浮點型變數,數值不變,只將形式改為浮點形式, 即小數點後帶若干個0。注意:賦值時的類型轉換實際上是強制的。
(2) 單、雙精度浮點型
● 由於C語言中的浮點值總是用雙精度表示的,所以float 型數據只是在尾部加0延長為double型數據參加運算,然後直接賦值。double型數據轉換為float型時,通過截尾數來實現,截斷前要進行四捨五入操作。
(3) char型與int型
● int型數值賦給char型變數時,只保留其最低8位,高位部分捨棄。
● char型數值賦給int型變數時, 一些編譯程序不管其值大小都作正數處理,而另一些編譯程序在轉換時,若char型數據值大於127,就作為負數處理。對於使用者來講,如果原來char型數據取正值,轉換後仍為正值;如果原來char型值可正可負,則轉換後也仍然保持原值, 只是數據的內部表示形式有所不同。
(4) int型與long型
● long型數據賦給int型變數時,將低16位值送給int型變數,而將高16 位截斷捨棄。(這裡假定int型佔兩個位元組)。 將int型數據送給long型變數時,其外部值保持不變,而內部形式有所改變。
(5) 無符號整數
● 將一個unsigned型數據賦給一個佔據同樣長度存儲單元的整型變數時(如:unsigned→int、unsigned long→long,unsigned short→short) ,原值照賦,內部的存儲方式不變,但外部值卻可能改變。
● 將一個非unsigned整型數據賦給長度相同的unsigned型變數時, 內部存儲形式不變,但外部表示時總是無符號的。
/*例:賦值運算符舉例 */
main()
{
unsigned a,b;
int i,j;
a=65535;
i=-1;
j=a;
b=i;
printf((unsigned)%u→(int)%d\n,a,j);printf((int)%d→(unsigned)%u\n,i,b);
}
運行結果為:(unsigned)65535→(int)-1(int)-1→(unsigned)65535
● 計算機中數據用補碼錶示,int型量最高位是符號位,為1時表示負值,為0時表示正值。如果一個無符號數的值小於32768則最高位為0,賦給 int型變數後、得到正值。如果無符號數大於等於32768,則最高位為1, 賦給整型變數後就得到一個負整數值。反之,當一個負整數賦給unsigned 型變數時,得到的無符號值是一個大於32768的值。
● C語言這種賦值時的類型轉換形式可能會使人感到不精密和不嚴格,因為不管表達式的值怎樣,系統都自動將其轉為賦值運算符左部變數的類型。
● 而轉變後數據可能有所不同,在不加註意時就可能帶來錯誤。 這確實是個缺點,也遭到許多人們批評。但不應忘記的是:c語言最初是為了替代彙編語言而設計的,所以類型變換比較隨意。當然, 用強制類型轉換是一個好習慣,這樣,至少從程序上可以看出想幹什麼。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/286937.html