Re: [問題] 大家好 關於字串反轉
※ 引述《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
≡≡≡≡║ ╚╝ ║║ ╚╝ ║║║║ ║║ ╞╣║ ║║ ║║ ║≡≡≡≡
≡≡≡≡║ ═╣║ ╥ ║║║║ ║ ║║ ═ ║║ ╚╝ ║║ ║ ║≡≡≡≡
≡高佑麗╚═╩═╝╚═╩═╝╚╝╚═╚═╝╚═══╝╚═══╝╚═╩═╝鄭允慧≡
≡≡≡≡≡趙賢榮≡≡≡金智淑≡≡≡RAINBOW≡≡≡盧 乙≡≡≡吳勝雅≡ψmocki
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.121.221.215
※ 編輯: loveme00835 來自: 140.121.221.215 (02/20 03:58)
討論串 (同標題文章)