iT邦幫忙

DAY 15
2

emacs的30天學習筆記系列 第 33

懷舊C語言:1988 The C Programming Language 2nd Edition(PART IV)

  • 分享至 

  • xImage
  •  

陣列和指標的精神不容易掌握,此外,注意一些使用上的細節,了解差異處,並正確使用,需要花一些理解體會。

筆者以往的經驗,很快能夠模仿現有程式,修改成新的,所以沒有物件導向的觀念,沒有一些深刻的程式基礎。

舉例:

char *h="Hello";
char *w="OR NG";

如果想在h 字串後接4個char的w.
這樣寫,

strncat(h,w,4);

然後就記憶體存取問題。

以下的寫法

char *h="Hello";
char h[]="Hello";
char h[12]="Hello";

剛好可以用strncat來深刻體驗。

第一句,就只分配"Hello"這樣數量的記憶體給你,後面接字元,抱歉不行,
第二句,分配一個超長的記憶體給你(char h[] 沒指定大小),程式會跑一下子。
因為分配一個超長的記憶體給你,所以後面接字元,基本上,畫面有限,接不出來,因為
strncat是在字尾後加上字元。這樣寫,結尾處斷不出來。
所以第三句宣告是對的。

同理,如果你要複製個字串,或複製部分字串,
如果寫

char r*;
strncpy (r,t,n );

又掛掉,如圖,

掛了多次後,traceN次,終於體會到,gcc 並不會對
**char r*;**分配記憶體,
就像字面上的意思,給它一個位址(數字),不給空間,讓他指向某處。

所以上面要改成

char r[10];
strncpy (r,t,n );

可能會認為10不夠,給char r[];
結果又給太多了。但比較了解其背後的意思。

所以,筆者十多年後回頭用C語言,才發現COPY PASTE的功力,幾乎是沒有程度(從0開始)。
唯一有用的過去經驗,就是從gdb trace的過程中,推論錯誤的發生。

本書題目的重點,是練習指標的寫法,對筆者反而簡單,正確傳對字串參數,反而花更多時間。

用char的角度來思考字串,以前覺得匪夷所思的字串處理功能,經過大師們圖文並陳的說明,
反而知道一個一個char,原來並不困難。覺得1988年並不精美的圖,還有種親切感。

曾經有一個念頭,就是從一些指令列工具(所謂bin utility),或standard library來學系統程式C 語言。gnu就有這個好處,從核心開始,處處都看得到源碼。
類似的概念,沒想到1988年,這本經典就是這樣的取材角度,真是相見恨晚。
題目5-4

Exercise 5-4. Write the function strend(s,t), which returns 1 if the string t occurs
at the end of the string s,
and zero otherwise.

大意是說,寫個函數 strend(s,t), 如果字串t出現在s字串的結尾(end),就回傳1,不然回傳0。
筆者的想法,是字串t的長度求出來,然後從字串s減去字串t的長度的位置,開始比較。
當然解法很多。筆者只提自己會的一種。

筆者先寫了strend

int strend(char *s, char *t) /*t出現在s的結尾,所以s的長度大於t */
{
char *r;
int i, j,k;
i = j =k= 0;
i=strlen(s);
j=strlen(t);
if (i< j )
	return 0;

for (k=0 ;k<=j; k++)
    *(r+k)=*(s+i-j+k);
	
int n = strcmp(r,t);
if (n==0)
	return 1;
else 
	return 0;
}

裏面呼叫了strlen

/* strlen: return length of string s */
int strlen(char *s)
{
int n;
for (n = 0; *s != '\0'; s++)
n++;
return n;
}

strcmp

/* strcmp: return <0 if s<t, 0 if s==t, >0 if s>t */
int strcmp(char *s, char *t)
{
for ( ; *s == *t; s++, t++)
if (*s == '\0')
return 0;
return *s - *t;
}

雖然沒幾個字,但至少要從陣列版改成指標版,所以ab**[]換成***

題目5-5

Exercise 5-5. Write versions of the library functions strncpy, strncat, and strncmp,
which operate on at most the first n characters of their argument strings. For
example, strncpy(s,t,n) copies at most n characters of t to s. Full descriptions are in Appendix B.

寫三個庫函數strncpy, strncat, and strncmp,
至多的 前面的n個字元,做操作動作。

就像vb,delphi,用久了,都有他們的文化,strncpy有點像是像左copy幾個字元,
別的語言,可能是用left(t, n) 傳回處理的字串s,C的習慣,傳回void(不傳回值),
不同的撰寫風格。

vb 在台灣的強者也是很多。不少高手把vb用得出神入化,升級到.net的vb,vb.net還是vb嗎?

linux 上,好像不太流行VM, 虛擬機的概念,所以GCJ的實作,也是直接支援java, 原生支援,還是gcc本身算是VM, 不可能吧?

筆者試回答如下:

void strncpy(char *s, char *t,int n )
{
int i;
i  = 0;
for (i=0 ;i<=(n-1); i++)
    *(s+i) = *(t+i);
*(s+i+1)= '\0'	;
}
void strncat(char *s, char *t,int n)
{
int i, j;
i = j = 0;
while (*(s+i) != '\0') /* find end of s */
{
i++;
}
for (j=0 ;j<=(n-1); j++)
    *(s+i+j) = *(t+j);
}
int strncmp(char *s, char *t ,int n)
{
char r[10];
strncpy (r,t,n );
return  strcmp(s,r);

}

如果從程式的長度來講,應該可能是答案的候選人,因為蠻短的,且有用***
strncmp可能是錯的,因為沒有用
***,只是call現成的函式。
*(s+i+1)= '\0' ;
,這段,筆者試了好久,覺得還是要這段。

有興趣的邦友們,可以試試。

小結:
太座的統計期末考又到了,就像數學類的考試,多年經驗告訴我們,就是算題目,
就算不懂,算,一直算就對了,算久了,就會懂。不會算,除了考試沒有分數,
同時浪費時間。
一直用gcc,配合著gdb,一直用,愈能發現C的不同處。


上一篇
懷舊C語言:1988 The C Programming Language 2nd Edition(PART III)
下一篇
Web Service 之外:微軟 的ISA Proxy server
系列文
emacs的30天學習筆記38
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言