自己在CODING过程中遇到的问题以及解决(C/VC)
自己對(duì)于寫程序還處于菜鳥階段,很多用法尚未涉及或者還不清晰??偸窍胫让總€(gè)程序?qū)懲暝賮砜偨Y(jié),卻發(fā)現(xiàn)早已無從下手。于是想到了這個(gè)方法,每次遇到問題并解決之后第一時(shí)間到這個(gè)日志上記錄下來。于是有了此文。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ivandark ? 處于邊緣的菜的不能再菜的程序猴子一年半
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?——2012.11.10
1.聲明空間并初始化內(nèi)存
聲明空間: 一維:int *a; ? a = (int*)malloc(sizeof(int)*size); ?//size為數(shù)組大小
? ? ? ? ? ? ? ? ? ? 二維:int **a; ?a=(int**)malloc(sizeof(int*)*row); ?//
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?for(int i=0;i<col;i++)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?a[i] = (int*)malloc(sizeof(int)*col);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
初始化內(nèi)存:因?yàn)椴怀跏蓟?#xff0c;動(dòng)態(tài)聲明的數(shù)組賦值不正常
? ? ? ? ? ? ? ? ? ? ? ?一維和二維的初始化是不一樣的。
? ? ? ? ? ? ? ? ? ? ? ?一維:memset(a,0,sizeof(a));
? ? ? ? ? ? ? ? ? ? ? 二維:邊分配內(nèi)存邊初始化:? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?int **a; ?a=(int**)malloc(sizeof(int*)*row); ?//
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?for(int i=0;i<col;i++)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?a[i] = (int*)malloc(sizeof(int)*col);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?memset(a[i],0,sizeof(int)*col); // 貌似只能這么寫 不可以效仿一維的格式
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
刪除: ?free(a); //一維和二維的一樣
? ? ? ? ? ? ?如果你像上面對(duì)a分配剛好的夠用的內(nèi)存并對(duì)其賦值運(yùn)算,再釋放會(huì)出現(xiàn)錯(cuò)誤after normal block(#207) at ?。
? ? ? ? ? 經(jīng)過查找發(fā)現(xiàn)不少人曾經(jīng)出現(xiàn)過此問題。
? ? ? ? ? 原因描述(引用網(wǎng)絡(luò)):這是典型的內(nèi)存溢出錯(cuò)誤,常在內(nèi)存的delete處發(fā)生,而且一般在debug版本中可能出現(xiàn),release版本中可能并不報(bào)錯(cuò).出現(xiàn)這個(gè)錯(cuò)誤的原因一般都是malloc/new申請(qǐng)的內(nèi)存溢出.因?yàn)樵赾++中,如果用new分配一段內(nèi)存,操作的時(shí)候改變了該部分的大小,在delete時(shí)就會(huì)出錯(cuò).
因?yàn)樯暾?qǐng)了一個(gè)size為5的內(nèi)存,但是strcpy過去了一個(gè)size為6的字符串,因此破壞了這個(gè)指針,運(yùn)行debug版本的時(shí)候就 會(huì)出現(xiàn)先前的錯(cuò)誤,但是在release版本中,溢出一個(gè)字節(jié)的內(nèi)存很有可能是沒有錯(cuò)誤的,然后潛在的隱患是肯定存在的,因此,我們?cè)赿ebug遇到這樣 的錯(cuò)誤時(shí)候一定要仔細(xì)檢查對(duì)new/malloc出的指針的操作.?
? ? ? ? ? ? 解決方案:我是為a數(shù)組多分配了一個(gè)(int**)內(nèi)存 程序運(yùn)行正常
2.C語言讀取txt文本
txt格式是我們利用編程語言處理數(shù)據(jù)時(shí),數(shù)據(jù)常用的存儲(chǔ)格式。
下面介紹常用的用于讀寫的函數(shù):
打開:FILE *fp;? ? ?if((fp=fopen("E:\\test.txt","rt"))==NULL) ? //" "里面的是文件路徑 ?"rt"表示讀取方式? ? ?{printf("cannot open file\n");return;? ? ?}
關(guān)閉:fclose(fp);
讀取:這里分為很多函數(shù):
? ? ? ? ? fscanf();這個(gè)是個(gè)人感覺比較好用的。從一個(gè)流中執(zhí)行格式化輸入,fscanf遇到空格和換行時(shí)結(jié)束,注意空格時(shí)也結(jié)束。這與fgets有區(qū)別,fgets遇到空格不結(jié)束。比如我們想把fp中的數(shù)據(jù)存到二維數(shù)組a中 ("%f"表示以浮點(diǎn)形式讀取)
? ? ? ? ? ? ? ?for(i=0;i<M;i++){for(j=0;j<N;j++)fscanf(fp,"%f",&a[i][j]);}
? ? ? ? ? ?? fread(); ? ??fread( void *buffer, size_t size, size_tcount, FILE *stream);根據(jù)msdn中的說明不難使用,這里不贅述。
寫入:
? ? ? ? ? ?fwrite(); ?:fwrite(buffer,size,count,fp); (1)buffer:是一個(gè)指針,對(duì)fwrite來說,是要輸出數(shù)據(jù)的地址?! ?#xff08;2)size:要寫入的字節(jié)數(shù); (3)count:要進(jìn)行寫入size字節(jié)的數(shù)據(jù)項(xiàng)的個(gè)數(shù); (4)fp:目標(biāo)文件指針。
3.VC讀取txt文本
對(duì)話框形式打開:
void COpenDataDlg::OnBtnOpendata() {// TODO: Add your control notification handler code herestatic char BASED_CODE file[] = "TXT Files (*.TXT)|*.txt|所有文件(*.*)|*.*||"; //文件類型說明字符串CFileDialog SelectFile (TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,file,NULL); //文件對(duì)話框初始化(點(diǎn)擊瀏覽時(shí)候的對(duì)話框) 第一個(gè)TRUE表示以打開方式;false是以保存的方式;file表示打開的是什么文件其他參數(shù) 顯示對(duì)話框 隱藏只讀,SelectFile.DoModal(); //彈出對(duì)話框CString FileName; FileName=SelectFile.GetPathName();//得到所選文件路徑m_FileName = FileName;UpdateData(FALSE);//把后臺(tái)數(shù)據(jù)刷新到前臺(tái)顯示} 讀取:跟C語言相同。好像可以用vc中的方法 CFile什么的,但是暫時(shí)沒搞懂,先放著。
輸出:跟C相同。 char str[50]; //數(shù)組大小可以根據(jù)輸出的內(nèi)容大小而定,這里為了簡(jiǎn)便聲明了靜態(tài)數(shù)組CFile file(_T("E:\\result.txt"), CFile::modeCreate | CFile::modeWrite);for(i=0; i<8; i++) //8是要輸出的字符的個(gè)數(shù) 可以根據(jù)需要變化 或者先求一個(gè)長(zhǎng)度再用長(zhǎng)度變量替換8{sprintf(str, "%d,%d\r\n",i,showID[i]); //showID里存儲(chǔ)的是要寫入數(shù)據(jù)file.Write(str, strlen(str) * sizeof(char));}file.Close();MessageBox("結(jié)果已輸出到E:\\result.txt");
4.opencv取像素灰度宏
(CV_IMAGE_ELEM(pImg1,uchar,i,j) //注意i j i代表y軸方向 j代表x軸方向 別弄反了
5.程序在調(diào)試態(tài)下正常,執(zhí)行時(shí)候mfc基礎(chǔ)類停止運(yùn)行
DAMAGE:After normal block(#****)
這種問題通常是由于動(dòng)態(tài)分配內(nèi)存導(dǎo)致的。可以檢查一下以下三種情況:
(1)數(shù)組訪問越界 int a[5]; a[5] = 3; //越界了(2)動(dòng)態(tài)分配數(shù)組越界 int *a; int lenth1 = 2; int lenth2 = 3; a = (int*)malloc(sizeof(int)*lenth1); memset(a,0,sizeof()*lenth2); free(a);這里初始化的數(shù)組長(zhǎng)度比定義的要長(zhǎng),出錯(cuò) (3)動(dòng)態(tài)聲明的空間沒有被釋放 所有動(dòng)態(tài)聲明的數(shù)組在一個(gè)函數(shù)結(jié)束之后一定一定要free掉! 但是在子函數(shù)中好像是無所謂的。只要在功能的主函數(shù)中釋放即可。
6.最近用過的Opencv 函數(shù)
(1)CvMat 創(chuàng)建并初始化矩陣
(2)cvEigenVV?
見另一篇轉(zhuǎn)載文章 ??http://blog.csdn.net/ivandark/article/details/8228029
(3)cvGetSize 得到矩陣尺寸 返回CvSize結(jié)構(gòu)體
? ? ? ?例如: CvSize size;
? ? ? ? ? ? ? ? ? ?size = cvGetSize(IplImage* img); ?//返回圖像長(zhǎng)寬
(4) cvSaveImage
保存圖像到文件
int cvSaveImage( const char* filename, const CvArr* image ); ?//filename 直接給路徑名,用字符串 ?指針用圖像的指針 比如IplImage filename 文件名。 image 要保存的圖像。 函數(shù)cvSaveImage保存圖像到指定文件。 圖像格式的的選擇依賴于filename的擴(kuò)展名,請(qǐng)參考cvLoadImage。只有8位單通道或者3通道(通道順序?yàn)?#39;BGR' )可以使用這個(gè)函數(shù)保存。如果格式,深度或者通道不符合要求,請(qǐng)先用cvCvtScale 和cvCvtColor轉(zhuǎn)換;或者使用通用的cvSave保存圖像為XML或者YAML格式。保存圖像到文件 int cvSaveImage( const char* filename, const CvArr* image ); filename 文件名。 image 要保存的圖像。 函數(shù)cvSaveImage保存圖像到指定文件。圖像格式的的選擇依賴于filename的擴(kuò)展名,請(qǐng)參考cvLoadImage。只有8位單通道或者3通道(通道順序?yàn)?#39;BGR' )可以使用這個(gè)函數(shù)保存。如果格式,深度或者通道不符合要求,請(qǐng)先用cvCvtScale 和cvCvtColor轉(zhuǎn)換;或者使用通用的cvSave保存圖像為XML或者YAML格式。
(5)初始化 IplImage* 明確 ?IplImage* 中的灰度數(shù)據(jù)存在imageData里 IplImage* KL_Img1;CvSize size = cvGetSize(pImg1);KL_Img1 = cvCreateImage(size, 8, 1); // 創(chuàng)建8位單通道圖像memset(KL_Img1->imageData, 0.0,sizeof(KL_Img1->imageData));// 將內(nèi)存拷貝到圖像中的imageData中
7.如何重繪 所謂重繪,就是講程序中變量保存的數(shù)據(jù)源源不斷的刷新到界面上。實(shí)現(xiàn)過程大概可以分為如下幾步: (1)以繪制點(diǎn)為例,先在VIew里設(shè)置一個(gè)變量IsDraw,初始值為False。 (2)我們需要把在函數(shù)func1中繪制的點(diǎn)保存在一個(gè)數(shù)組里,我是在Doc類下新建了一個(gè)數(shù)組空間。 (3)當(dāng)自己寫的繪制函數(shù)執(zhí)行完畢后,所有要重繪的點(diǎn)數(shù)據(jù)也全部存到數(shù)組中了,這里把IsDraw賦值為TRUE (4)然后在OnDraw函數(shù)中開始重繪,重繪內(nèi)容就是func1中畫的東西,只不過這次我們要從Doc里的數(shù)組調(diào)取數(shù)據(jù)而已。因?yàn)槿绻粓?zhí)行func1,Ondraw是沒的可畫的,所以在重繪前還要加上if判斷,如果IsDraw==TRUE,則執(zhí)行重繪。
8.C語言取整問題 (1)向下取整 直接強(qiáng)制轉(zhuǎn)換。如int i = 2.5 ?, i=2 (2)向上取整 函數(shù)ceil 。 如 int i = ceil(2.5) ,i=3 ? 9.C語言txt文件讀取操作 (1)打開 ??? FILE *fp; ?? fp = fopen("E:\\.txt","r"); ? if(!fp)//容錯(cuò) ? { ??????? printf("ERROR");?? return 0; ? } (2)讀取——非循環(huán) 只讀一個(gè)數(shù)值 ? fscanf(fp,"%d",&N); (3)讀取——循環(huán) 讀一組數(shù)存入數(shù)組 for(i=0;i<N;i++) { ??????fscanf(fp."%d",&a[i]);?? //讀取浮點(diǎn)數(shù)一定要用 %lf 不要用%f 原因:http://blog.csdn.net/lutx/article/details/5072043 } ???? (4)寫文件 ? ?mkdir("E:\\STU");??????????????????????? //在硬盤新建文件夾和文件!!!
?fp2 = fopen("E:\\STU\\result.txt","w");
for(i=0;i<N;i++) { ????? fprintf(fp,"%d\t",result[i]); ? ????? if((i+1)%10 == 0) ????? { ??????????? fprintf(fp,"\n"); ????? } } (5)文件指針問題 ???? fgetc(fp); //可以使當(dāng)前文件指針向后移動(dòng)一位。在跳過空格 回車 很有用? ???? while(!feof(fp))//讀到文件末就停止 否則繼續(xù)讀 ? (6)fseek介紹 <整理并摘抄自百度百科> ? A.函數(shù)原型:int fseek(FILE *stream, long offset, int fromwhere); //負(fù)責(zé)文件指針操縱:如果執(zhí)行成功則返回0(文件stream的內(nèi)部指針以參數(shù)3為基準(zhǔn),偏移參數(shù)2的量),失敗返回-1 ? B.參數(shù)3可以有: (偏移起始位置:起始位置0(SEEK_SET),當(dāng)前位置1(SEEK_CUR),文件尾2(SEEK_END)) ? C.主要作用:移動(dòng)文件內(nèi)部指針的位置,可以用來計(jì)算文件長(zhǎng)度 ? 例子: int main() {FILE *fp;fp = fopen("E:\\a.txt","r");fseek(fp,0L,SEEK_END);//移動(dòng)文件指針到末尾int len = ftell(fp1);//順便求個(gè)長(zhǎng)度唄 經(jīng)過試驗(yàn) txt中 空格算一個(gè)長(zhǎng)度 回車算兩個(gè)//ftell用于得到文件位置指針當(dāng)前位置相對(duì)于文件首的偏移字節(jié)數(shù)fseek(fp,0L,SEEK_SET);//把文件指針再移動(dòng)到開始fseek(fp,100L,SEEK_SET); //再把文件指針移動(dòng)到離文件開頭處100字節(jié)fseek(fp,100L,SEEK_CUR); //再把文件指針移動(dòng)到離當(dāng)前位置處100字節(jié)fseek(fp,100L,SEEK_END); //再把文件指針移動(dòng)到離文件結(jié)尾處100字節(jié)fseek(fp,-100L,SEEK_SET);//再把文件指針"退回"到離文件結(jié)尾處100字節(jié)return 0; }
?(7)讀取字符串 ? A.fgetc函數(shù):從文件中讀取一個(gè)字符,讀取一個(gè)字節(jié)后,光標(biāo)位置后移一個(gè)字節(jié)。 ? 例子: while(!feof(fp1)) //從文件中讀取字符串 并計(jì)算字母字符的個(gè)數(shù){ch = fgetc(fp1); //一個(gè)一個(gè)字符的讀if(ch==EOF)//文件末端{(lán)printf("%d",count);printf("\n");}if(isalpha((int)ch))//判斷ch是否為字母 字母的ASCII碼:ASCII碼:65~90號(hào)為26個(gè)大寫英文字母,97~122號(hào)為26個(gè)小寫英文字母!!!{str[count] = ch; //存入字符串中count++;}}
? B.fputc函數(shù)————將字符ch寫到文件指針fp所指向的文件的當(dāng)前寫指針的位置。 例子: char msg[] = "Hello world"; int i = 0; //方法一while (msg[i]&&(i<strlen(msg))) { fputc(msg[i], fp1); i++; } //方法二fprintf(fp1,"%s",msg);
C.ctype.h —— 處理字符常用的頭文件 用例: //isalpha:檢查ch是否是字母 是字母則返回非0 否則返回0if(isalpha((int)ch))...//判斷ch是否為字母 char ch//isdigit:檢查ch是否為數(shù)字0-9 是則返回非0 否則返回0//islower:檢查是否為小寫字母//isupper:檢查是否為大寫字母//isalnum:檢查是否是字母或數(shù)字//ispunct:是否是標(biāo)點(diǎn)字符//isspace:是否是空格符/跳格符/控制字符/換行符ch = tolower((int)ch);//大寫字母轉(zhuǎn)成小寫字母 ; toupper小寫轉(zhuǎn)大寫
D.fgets —— 讀取字符串 char *fgets(char *s, int n, FILE *stream); fgets函數(shù)的調(diào)用形式如下:fgets(str,n,fp); 此處,fp是文件指針;str是存放在字符串的起始地址;n是一個(gè)int類型變量。 函數(shù)的功能是從fp所指文件中讀入n-1個(gè)字符放入str為起始地址的空間內(nèi); 如果在未讀滿n-1個(gè)字符之時(shí),已讀到一個(gè)換行符或一個(gè)EOF(文件結(jié)束標(biāo)志),則結(jié)束本次讀操作,讀入的字符串中最后包含讀到的換行符。 因此,確切地說,調(diào)用fgets函數(shù)時(shí),最多只能讀入n-1個(gè)字符。讀入結(jié)束后,系統(tǒng)將自動(dòng)在最后加'\0',并以str作為函數(shù)值返回。 ? 通俗的講: 比如有文件 Hello world! Hello Hello world! 代碼為: int main() {FILE *fp1;fp1 = fopen("E:\\test.txt","r");char msg1[20];char msg2[20];fgets(msg1,4,fp1); //m=4fgets(msg2,7,fp1); //n=7printf("%s\n",msg1);printf("%s\n",msg2);return 0;}
情況一:(m=4 n=7) 輸出: Hel lo wor 情況二:(m=4,n=20)如果使用fgets() 讀取文件的時(shí)候bufsize大于該行的字符總數(shù)加2(多出來的兩個(gè),一個(gè)保存文件本身的'\n'換行,一個(gè)保存字符串本身的結(jié)束標(biāo)識(shí)'\0'),文件并不會(huì)繼續(xù)讀下去,僅僅只是這一行讀取完,隨后指向文件的指針會(huì)自動(dòng)偏移至下一行。 Hel lo world! 情況三:(m=15,n=4) Hello world! Hel 情況四:(m=15,n=20) Hello world! ? Hello Hello world! (8)按行讀取數(shù)據(jù)<待續(xù)> ???? 10.C語言讀取raw ? ??//開始讀
?unsigned char *tmp = (unsigned char*)malloc(sizeof(unsigned char)*256*256);
?memset(tmp,0,sizeof(tmp));
?fread(tmp,sizeof(unsigned char),256*256,fp1); //格式轉(zhuǎn)換后再處理 int* data = (int*)malloc(sizeof(int)*256*256);
?memset(data,0,sizeof(data));
?for(i=0;i<=255*255;i++)
?{
??data[i] = (int)tmp[i];
?} //開始寫 fwrite(tmp,sizeof(unsigned char),256*256,fp2);? //tmp 為 unsigned char
?
總結(jié)
以上是生活随笔為你收集整理的自己在CODING过程中遇到的问题以及解决(C/VC)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】误差矩阵(混淆矩阵)评价法
- 下一篇: 新手必知20点VC技巧【转】