天天看點

學習資料結構中一些C語言問題集錦2

最近重新檢視資料結構,發現許多以前不懂,不清楚的問題。更加的意識到,以前學的C語言很基礎,許多細節書本上都沒講解,看來下次得找本C語言進階的書觀摩了。

1.在輸入字元串時,遇到輸入字元串有空格時會出現空格後面字元串接收不到的問題,如:

char str1[20],str2[20];  

scanf("%s",str1);  
scanf("%s",str2);  
printf("%s,%s",str1,str2);
           

若想輸入"Holo is a wolf."給str1,"Super Sonic is beautiful."給str2,則隻會輸出"Holo,is",查閱MSDN知"Thescanf function reads data from the standard input streamstdin",scanf從stdin(以前學c是譚浩強的書,上面沒講)中讀取資料,應該是以空格或者回車來當作接收的斷點。想要接收包含空格的字元串,最好使用gets函數。代碼如下:

char str1[20],str2[20];  
gets(str1);  
gets(str2);  
printf("%s,%s",str1,str2);  
           

但是gets函數一般不建議使用,它容易造成緩沖區溢出,經搜查,一般建議使用fgets函數。常用fgets(char *str,int n,stdin);來擷取。如下:

char str1[5],str2[5];               /*記憶體較小,用啦測試會不會産生溢出*/  
fgets(str1,(sizeof(str1)-1),stdin);/*sizeof(str1)-1,fgets函數會自動在末尾添加一個'\0',是以一般記憶體建議設足夠大。*/  
fflush(stdin);                     /*如果沒有此句,如果輸入超過數組記憶體,會直接指派給下一個輸入函數。造成錯誤。*/  
fgets(str2,(sizeof(str1)-1),stdin);/*當讀滿n-1個字元或者換行符時候,fgets函數會傳回。應該添加一個去回車的函數.此處暫不考慮*/  
fflush(stdin);  
printf("%s%s",str1,str2);          /*輸出會有換行符*/
           

關于前面提到的fflush函數,由于有時候輸入資料長于緩存時,後面的輸入會直接從流讀入而不再接收使用者輸入經查找,需要用到此函數:

fflush(stdin)重新整理标準輸入緩沖區,把輸入緩沖區裡的東西丢棄 。

fflush(stdout)重新整理标準輸出緩沖區,把輸出緩沖區裡的東西列印到标準輸出裝置上。

一般在檔案操作中建議使用fflush(stdout),flush即清空緩沖,在慢速裝置上使用緩存是一種提升資料處理效率的手段,flush的作用是将記憶體中緩沖的内容實際寫入外存媒介。fflush不應該在讀取檔案的時候用,而應該在寫入檔案的時候用。fflush會清空緩沖區,fclose在關閉檔案之前也會清空緩沖區。如果使用exit函數退出程式,或者main函數傳回,則所有打開後沒有關閉的檔案會自動關閉,關閉時也會清空緩沖區。

2.strcmp(a,b)要include <string.h>頭檔案,當兩兩字元串相等時傳回0,a>b即從做往右a有大于b的AssicⅡ時,傳回1,反之傳回0.要小心使用

if(!strcmp(a,b))func();,對于一個數字a,它的非值為0.這個表示如果a,b相等,則執行func(),不等則不執行.對于在字元串數組中找某字元串有如下代碼:

int i=0;
while(0!=strcmp(v,G.vexs[i]))i++;/*G.vexs表示圖的頂點,在vexs裡面找v,*/
if(i<G.vexnum)			 /*while隻是用來确定所在位置。像這種确定字元串位置的*/
	return i;		 /*一般用這種方法較好,先用循環确定位置i*/
else{printf("Cannot find data %s!\n",v);exit(0);}
           

3.i++和++i,在需要他們傳回數值的時候才有差別,i++是先傳回i的值,再将i加1,++i則是先将i加1,再傳回i的值,此用法在循環中我了解出錯了,如循環

for(int i=0;i<5;++i);我認為第一次執行時是先将i+1,即等價于for(int i=1;i=<5;i++);其實不然,經彙編分析,括号内的是從左到右執行。其實在循環中,沒有

用到i++或++i的傳回值,此處他們等價。關于他們效率的問題,在編譯器優化前,++i不需要零時變量效率高,但經編譯器優化Release版本,實質是一樣的。

參考網文,在有疊代器的時候,++i效率高些。關于疊代器暫時還未看,不過書中一般循環中用++i。反彙編代碼自尋。

4.關于switch語句中遇見enum類型。在switch中有個規定,隻能針對基本資料類型使用switch,這些類型包括int、char等。而在union輸入enum時接收的是

字元串類型,需要将其化為enum類型。有時也需要将enum類型傳回字元串類型。其代碼如下

void strToenum(MGraph &G)/*将字元串轉換成enum type   kind定義typedef enum{DG,DN}Kind; Kind kind;*/
{
	char str[10];
	scanf("%s",str);
	if(!strcmp(str,"DG"))G.kind=DG;
	else if(!strcmp(str,"DN"))G.kind=DN;
	else {printf("Error Typed!\n");exit(0);}
}
           

将枚舉轉換成字元串

typedef enum{Mon,Tus,Wen,Thr,Fri,Sta,Sun}Week;
char temp[7][4]={"Mon","Tus","Wen","Thr","Fri","Sta","Sun"};
printf("\n%s",temp[Mon]);/*用數組法就直接得出結果來了*/
           

5.關于編譯器給存儲在棧上變量配置設定存儲空間時,誰在前面聲明,就先給誰開辟空間。如:

char p[4],q[4];
36:       scanf("%s",p);
0040D418   lea         eax,[ebp-4]
0040D41B   push        eax
0040D41C   push        offset string "%s" (004223f4)
0040D421   call        scanf (0040f8f0)
0040D426   add         esp,8

39:       scanf("%s",q);
0040D43A   lea         edx,[ebp-8]
0040D43D   push        edx
0040D43E   push        offset string "%s" (004223f4)
0040D443   call        scanf (0040f8f0)
0040D448   add         esp,8
	char p[4],q[4];
	scanf("%s",p);
	scanf("%s",q);
	printf("%d,%d",p[0],q[0]);
           

(圖中數字為10進制)堆棧在系統上如下圖1:

學習資料結構中一些C語言問題集錦2

圖1   

學習資料結構中一些C語言問題集錦2

  圖2  

學習資料結構中一些C語言問題集錦2

圖3     

學習資料結構中一些C語言問題集錦2

  圖4

對于下面代碼,如果輸入"aaaa","bbbb",則會輸出0,98本來是想輸出p和q的第一個的AssicⅡ碼,結果卻不盡人意,原本要成為圖2的,但是分析是scanf函數獲得字元串會在後面預設加個‘\0’來表示字元串的末尾,本來q隻申請了四個空間,此時會将'\0'填充到下面p的首部,便成了如上圖3。在一個變量内,其值一般是按照從小位存低位,大位存高位(RISC架構)如上圖4,1234存儲方式。

char p[4],q[4];
	a=3;
	b=4;
	scanf("%s",p);
	scanf("%s",q);
	printf("%d,%d",p[0],q[0]);
           

小注意:會發現如果上面的p[4]變成p[2]或者p[1]時,p的位址依然是ebp-4,q的位址是ebp-8說明對于數組大小小于4位元組時預設配置設定4位元組,當大與4位元組時按具體大小配置設定。(可能一個指針占4位元組是以預設配置設定4位元組)。同時注意到如果隻是定義一個char a;它也會配置設定4個位元組的空間,難道是為了位元組對齊?本機機器字長為32位4位元組,一次能處理32位,則一位元組申請32位空間嗎?大概。ebp為本段程式的基址,一般隻對它進行減法操作,來取得變量位址,是為了保護不是本段程式的變量嗎,也大概。得參考深入的C語言書籍了。

其他一些後續問題還會添加,現在才覺得以前學的C語言根本不夠用啊,好像學C語言不僅要從底層彙編了解,還要從編譯器方向來考慮,有些還涉及到CPU的處理,如以前遇到的浮點數要初始化浮點數寄存器問題,是該找本好書系統學習了,求推薦orz

繼續閱讀