C/C++實際編程常見問題分析<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
-----西安郵電學院計算機系 徐兆元([email protected])
[概要]本文針對C/C++實際編程經常及容易遇到的問題進行分析解答.
在學習編程和課程實習中,我們在編程上會遇到很多問題,這些問題一般都比較雜亂.下面就對這些問題進行總結.
1.const 與#define的使用疑問與異同
(1)#define用於C與C++,const用於C++
(2)#deinfe爲宏定義,你可以定義常量如#define N 100,
可以定義函數#define max(int a,int b)( a>b?a:b),可以定義格式化操作 #define out "%d %d /n"你可以自由定義你需要替換的常量,函數等,它的目的在於可以減少你在代碼中反覆的輸入一段相同但繁瑣的代碼.
(3)const用法較複雜,總結如下:
const int ArraySize=100;//修飾常量,此常量必須初始化
char char_A="C++";//char_A內容在後續程序中可以改變,重新賦值char_A="C"
const char char_B="C_C++";//字符串char_B內容不能改變
char *const ptr_A=&char_A;//常指針,指針本身不能被修改
char const *ptr_B=&char_B;//指向長量的指針,指針指向的內容不能改變const char 和char const效果是一樣的
const char const *ptr_C=&char_B;//指向常量的常指針,兩者均不能被改變
void Function1(const var_Type var);//函數參數爲值傳遞,const將保證var不被改變
void Function2(const var_Type *var)或void Function2(const varType &var)//函數參數爲地址傳遞,const將保證該地址內容不被修改
const var_Type operator*(const var_Type &A,const var_Type &B);//返回值不能被改變,保護返回值
const var_Type *Funstion()//讓函數返回指向const的指針,該地址的內容不會被修改
void Class_MemberFuntion(***) const//用於類的成員函數,表示此成員函數不能改變任何數據類型的值
(4)#define爲預處理命令,在宏建立時做是隻是文本替換,沒有類型檢查,定義函數就沒有參數壓棧、代碼生成、現場保護、現場恢復等一系列的操作,但它降低了空間和時間的開銷所以效率較高.
下面的例子就是我們經常犯的錯誤:
#define max1(a,b) ((a) > (b) ? (a) : (b))
int a = 5, b = 0;
max(++a, b);// a 的值增加了2次
max(++a, b+10); // a 的值只增加了1次
看懂了沒有,如果仔細觀察的話,你就會發現define給我們帶來了多大的麻煩!(如果想了解更多去看看《Effective C++ 》)
2. C/C++中內存分配?
(1)從堆中分配內存,在C中用malloc(calloc)和free,在C++中用new和delete
(2)分配內存的對象是指針,不能進行以下的搭配malloc/delete,new/free,這是不合法的.
int len=10;
char *p_Char;
p_Char=(char *)malloc(sizeof(char)*(len+1));//C中操作
free(p_Char);//刪除指針所指向的內容,即內存,p_Char指向NULL,以後不能在訪問它
p_Char=new char[len];//C++中的操作
delete[] p_char;//每當你在 "new" 運算式中用了 "[...]" 的話,你就必須在 "delete" 陳述中使用 "[]".這語法是必要的,因爲「指向單一元素的指標」與「指向一個陣列的指標」在語法上並無法區分開來.
(3)C++中new/free比C中的malloc/free更先進,new操作符自動確定對象的正確長度並返回正確類型的指針.而malloc需要sizeof()來手動確定對象的長度,這樣你可能需要更多的函數增加了複雜度,malloc需要用強制轉換符(var_Type *)來使返回正確的類型指針.
new在分配內存時可以初始化,malloc則不能.
p_Char=new char("C++");
更重要的是,在使用非內部數據類型對象的時,new自動調用生成的對象的構造函數,delete自動調用生成的對象的析構函數.
3.TC/BC下圖形編程問題?
(1)TC/BC將屏幕分爲兩種狀態文本窗口模式和圖形窗口模式.默認在系統處於文本模式.
(2)文本模式下將屏幕分爲80(或40)行80列,次模式下我們可以進行普通的字符編程,不過你也可以使用以下屏幕操作函數:
void window(int left, int top, int right, int bottom);//設置窗口
void textbackground(int color);//背景色
void textcolor(int color); //文字顏色
void textattr(int attr); //同時設置文本的字符和背景顏色
void clrscr(void); //清除當前窗口中的文本內容, 並把光標定位在窗口的左上角(1, 1)處
void clreol(void); //清除當前窗口中從光標位置到行尾的所有字符, 光標位置不變。
void gotoxy(x, y); //該函數很有用, 它用來定位光標在當前窗口中的位置。這裏x,y是指光標要定位處的座標(相對於窗口而言),當x,y超出了窗口的大小時,該函數就不起作用了。
int gettext(int xl,int yl,int x2,int y2,void *buffer);
int puttext(int x1,int y1,int x2,int y2,void *buffer);
int movetext(int x1, int x2, int y2, int x3, int y3);
更多的請您參閱〈〈BC庫函數〉〉
(3)要使用TC/BC的圖形模式,你需要進行以下操作:
<1>確保有你的TC/BC目錄下有顯示器圖形驅動程序*BGI,將集成開發環境options/Linker中的Graphics lib 選爲on,只有這樣才能保證正確使用圖形函數.
<2>代碼的#include中包含graphics.h頭文件
<3>初始化圖形屏幕.
在使用圖形屏幕之前我們需要用
void far initgraph(int far *gdriver, int far *gmode,char *ath);
函數初始化屏幕
其中gdriver和gmode分別表示圖形驅動器和模式,path是指圖形驅動程序所在的目錄路徑
前兩個參數有很多的選項,你可以參考相關參考書.我們一般可以用以下這個通用的函數來初始化我們學院和現在大部分微機的圖形模式.
void MyInit(void){
int gdriver=DETECT,gmode=2;//DETECT爲自動檢測顯示器
initgraph(&gdriver,&gmode,"//bgi");
}
在需要初始化的地方調用MyInit()就可以初始化屏幕了.
注意:使用完圖形窗口,最好使用closegraph()關閉圖形模式
在初始化屏幕完以後,我們就可以使用圖形操作函數了比如:
void far putpixel(int x, int y, int color);//畫點函數
void far line(int x0, int y0, int x1, int y1);//畫直線.
void far lineto(int x, int y);//畫一作從現行遊標到點(x, y)的直線
void far circle(int x, int y, int radius);//畫一個圓
void far arc(int x, int y, int stangle, int endangle,int radius);//畫一段圓弧線
void ellipse(int x, int y, int stangle, int endangle,int xradius,int yradius);//畫橢圓
void far drawpoly(int numpoints, int far *polypoints); //畫多邊形
更多的函數參見《BC庫函數》
(4)在圖形模式下對文本的操作和文本模式下的文本操作有一些不同.
在圖形模式下,只能用標準輸出函數,如printf(),puts(),putchar()函數輸出文本到屏幕
在圖形模式下系統提了專門操作文本的函數:
void far outtext(char far *textstring);//當前位置輸出
void far outtextxy(int x, int y, char far *textstring);//輸出到(x,y)處
void setcolor(int)//字符顏色
void far settexjustify(int horiz, int vert);//用於定位輸出字符串
void far settextstyle(int font, int direction,int charsize);//設置輸出字符的字形
void far setusercharsize(int mulx, int divx, int muly, int divy);//設置筆劃型字和放大係數
更多請參閱《BC庫函數》
4.VC下控制檯程序的問題
(1)初學VC的同學總是試圖將TC或BC下的程序移植到VC,但他們發現大程序並不能運行.首先TC/BC與VC出於不同的公司,不可能相互兼容.其次,在TC/BC用的頭文件在VC中不一定有或不一定相同,所以他們對同一個問題的處理函數不同或參數等都不同.在次,別指望VC++ Console Application爲你提供什麼圖形操作,除非你藉助MFC和OpenGL.
(2)到現在爲止,我對控制檯程序的高級操作只有設置文本的顏色,用以下的API函數:GetStdHandle()和SetConsoleTextAttribute(),函數原型爲
HANDLE GetStdHandle(DWORD nStdHandle);
BOOL SetConsoleTextAttribute(
HANDLE hConsoleOutput,// console 屏幕緩衝區的句柄
WORD wAttributes // 文本及背景的顏色
);
編寫以下子函數可以改變字符顏色
void SetColor(unsigned short ForeColor=4,unsigned short BackGroundColor=0)
//給參數默認值,使它可以接受0/1/2個參數
{
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); //本例以輸出爲例
SetConsoleTextAttribute(hCon,ForeColor|BackGroundColor);
};
在需要的地方調用此函數即可.
[後記]篇幅原因,只能對這幾個問題進行簡單的討論.如果你有更多的疑問,請到http://202.117.133.118/bbs的編程模塊上發表問題或E-Mail至[email protected],我會給您詳細的解答.