Re: [問題] 大家好 關於字串反轉

看板C_and_CPP作者 (高髮箍)時間12年前 (2013/02/19 19:54), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串4/4 (看更多)
※ 引述《tobashi ()》之銘言: : : String create_string( size_t max_length ) { : : String ret = (String)malloc(max_length+1); : : return ret[ 0 ] = '\0', ret; : : } : 試了一下發現將string size設5 : 也就是String ret=(String)malloc(5) : 居然也能成功?? : : void release_string( String target ) { : : free( target ); : : } : 想請問 return ret[0]='\0' 這邊是將ret字串的開頭設為結尾?? 在 C 語言中的字串定義是: [n1256 §7.1.1/1] A string is a contiguous sequence of characters terminated by and including the first null character. [n1256 §5.2.1/1] ... A byte with all bits set to 0, called the null character ... 一堆字元連續的擺在一起, 它們合起來就叫做字串, 不過字串這樣 設計是有原因的, 既然是連續的字元, 我就可以把它們存放在陣列 裡: char chars[ 5 ] = { '1', '2', '3', '4', '5' }; size_t length = 5; // 印出字串 for( size_t i = 0; i < length; ++i ) printf( "%c", chars[i] ); 如上面程式碼所述, 因為字元是連續地擺放在一起, 所以尋訪時可 以很容易地用迴圈達成. 但是如何決定迴圈執行次數? 最直覺的方 式就是用一個變數先紀錄起來(如length). 多一個變數代表需要額 外的記憶體空間, 甚至當函式引數傳遞時也不方便: strcat( str1, len1, str2, len2 ); 所以就有了另外一個解決方案: 在連續的字元中加入 sentinel 值 做為迴圈的終止條件, 這也就是 '\0' 為什麼會出現的原因. 跳脫 字元 '\' 後面如果接上數字都是以八進位來解讀, '\0' 數值就是 整數 0, 這就是[n1256 §5.2.1/1]的要求, 後來這個 null char 也變成了字串的一部分. 再來我們看一下 string literal 的定義: [n1256 §6.4.5/5] In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals. ... 意思是雖然 string literal 寫成 "12345", 但是它內存的值和 下面的陣列是相同的(null char之前): char chars[ 6 ] = { '1', '2', '3', '4', '5', 0 }; 所以你問為什麼我把第一個字元值設成 null char? 因為讓它早一 點出現在連續記憶體中的話, 後面那些未初始化垃圾值都不會被解 讀成是字元(字串中的一部分). 使得下面呼叫是安全的: String str = create_string( 100 ); printf( "str is: %s", str ); 再來就跟前面說到的一樣: null char也是字串的一部分. 你問為什 麼 malloc() 引數改成 5 依然會對? 那跟問下面這段程式碼合法性 是差不多的: char chars[ 5 ] = { '1', '2', '3', '4', '5' }; chars[ 5 ] = '\0'; 沒人敢保證你越界寫入的記憶體值是不是會影響程式的運作, 因為 執行的情形可能有很多種, 但這絕對是錯的! (發文前請先詳閱置底 十三誡) : : main() 經改寫變成這樣: : : int main() : : { : : String str = create_string( 5 ); : : strcpy( str, "12345" ); : 如此一來的話 : 將12345 copy到 str中 str的分配是如何呢? : 是 \0 1 2 3 4 5? 字串拷貝是從給定的記憶體位址開始寫入, 就像我所說最後 str 的內容是 '1' '2' '3' '4' '5' '\0', 至少需要六個字元的空間. : : reverse( str ); : : puts( str ); : : release_string( str ); : : return 0; : : } : : 這裡是 reverse() 的程式碼: : : void reverse( String str ) : : { : : size_t left = 0, right = strlen(str)-1; : : for ( ; left < right; ++left, --right ) { : : char temp = str[left]; : : str[left] = str[right]; : : str[right] = temp; : : } : : } : 非常感謝願意花時間指導 你還是先好好看書吧! 發一篇文只能解決一個小疑惑, 看完一章你 可能連 <string.h> 裡的函式都能自己實作出來了. -- ╔═══╗╔═══╗ ╔═╗═╗╔═══╗╔═══╗╔╦═╦╗ 金栽經║ ╔╗ ║║ ╔╗ ║╔╗║ ║ ║║ ═ ║║ ╔╗ ║║║ ║║RAINNOUS ≡≡║ ╚╝ ║║ ╚╝ ║║║║ ║║ ╞╣║ ║║ ║║ ║ ═╣║ ╥ ║║║║ ║ ║║ ═ ║║ ╚╝ ║║ ║ ║ 高佑麗╚═╩═╝╚═╩═╝╚╝╚═╚═╝╚═══╝╚═══╝╚═╩═╝鄭允慧 趙賢榮金智淑盧 乙吳勝雅ψmocki -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.121.221.215 ※ 編輯: loveme00835 來自: 140.121.221.215 (02/20 03:58)
文章代碼(AID): #1H8zYBmk (C_and_CPP)
討論串 (同標題文章)
文章代碼(AID): #1H8zYBmk (C_and_CPP)