文章程式碼顯示

2018年2月12日 星期一

《筆記》C語言 - 07_3:使用指標將字串依字元列印、指標與 const 、 char* sPtr 、 const char* sPtr

char* sPtr
使用指標將字串依字元列印(帶 Size)

#include "stdio.h"

void printStrByChar( char* sPtr, int Size);

int main(void) {

 char string[] = "Hello world";
 printf("%s\n", string);

 int size = sizeof(string); //含結束字元'\0' 共 12 個 byte

 printStrByChar( string, size );

 printf("end");

}

void printStrByChar( char* sPtr, int Size){
 for(int i = 0; i < Size -1  ; i++)
  printf("%c\n", *(sPtr + i) );
}


我們宣告一個函式 printStrByChar 並且兩個引數指定為 char* 以及 int 型別的 Size

char* 型別就等同於告知使用者輸入的參數應該要是一個指標(或稱位址),而如前一章所述,陣列名稱就是該陣列第一個元素的位址,字元陣列(字串)也不例外,就會是第一個字元的位址。

使用指標將字串依字元列印(使用 while)

#include "stdio.h"

void printStrByChar( char* sPtr );

int main(void) {

 char string[] = "Hello world";
 printf("%s\n", string);

 printStrByChar( string );

 printf("end");

}

void printStrByChar( char* sPtr ){

 while( *sPtr != '\0'){
  printf("%c", *sPtr);
  sPtr++;
 }

}



使用 while 搭配判斷式可以利用字串的特性「最末端必定為結束(空白)字元 '\0')」來省去 size 的輸入引數

使用指標將字串依字元列印(使用更簡潔的 for)

#include "stdio.h"

void printStrByChar( char* sPtr );

int main(void) {

 char string[] = "Hello world";
 printf("%s\n", string);

 printStrByChar( string );

 printf("end");

}

void printStrByChar( char* sPtr ){
 for(; *sPtr != '\0'; *sPtr++)
  printf( "%c", *sPtr);
}


同樣的,這裡是使用 for 搭配判斷式來省去 size 的輸入引數

更改字串的第一個元素(字元)

#include "stdio.h"

void changeFirstChar( char* sPtr );

int main(void) {

 char string[] = "Hello world";
 printf("%s\n", string);

 changeFirstChar( string );
 printf("%s\n", string);
 printf("end");

}

void changeFirstChar(  char* sPtr ){
 *sPtr = 'B';
}


const char* sPtr
嘗試更改第一個字元

#include "stdio.h"

void changeFirstChar( const char* Str );

int main(void) {

 char string[] = "Hello world";
 printf("%s\n", string);

 changeFirstChar( string );
 printf("%s\n", string);
 printf("end");

}

void changeFirstChar( const char* Str ){
 *Str = 'B';
}



我們會發現編譯器會報錯

其原因在於這樣的宣告方法表示 所指向的資料為常數資料,也就是不得使用 *(米字號) 進行値的修改。

此宣告方法主要用於如果某個函式只取用傳入陣列的元素,並不會去更動到元素的數値,則我們便可以用這種指標來為此函式接收陣列參數。

第二個應用方法必須等待學到 結構(struct) 的時候才會明瞭。當我們必須將結構的資料傳給函式時,可以使用這種指向常數資料的指標,若使用普通的傳値呼叫讓一個結構當作引數,則它傳遞的會是整個結構的副本。這會增加執行時的負擔,可能是記憶體空間之類的。

使用指向常數的指標一方面可以獲得傳參參考呼叫的效率性,另一方面也可以如傳値呼叫般保護結構裡面的資料。

效率性是什麼意思呢?

當傳遞一個指向結構的指標時,你只需要複製一份該結構所存放的 "位址" 即可。也就是說我們只需要傳遞"位址(4bytes)"的資料,而不是數百或數千個 byte 的資料(亦即整個結構可能的大小)

使用指標來進行一個字串的宣告

#include "stdio.h"

int main(void) {

 char string1[] = "HELLO Array";
 char *string2 = "HELLO Pointer";

 printf("%s\n", string1);
 printf("%s\n", string2);

 printf("Sizeof string1 = %d\n", sizeof(string1));
 printf("Sizeof string2 = %d", sizeof(string2));

}



我們可以用指標的方式直接宣告一個字串(如 string2 ) ,其效果與我們前面使用的宣告方式相當( string1 )

printf 函數搭配 %s 會不斷的列印字元直到遇到 '/0' 為止

但值得注意的是若我們要使用 sizeof 來判斷這個字串的長度時則會有問題出現

仔細看 string1 的長度顯示為 12 個 bytes (加上結束字元);而 string2 卻是 4

其原因在於對 string2 使用 sizeof 時,它判斷的是 sizeof(char*) ,也就是說它回傳一個指標變數的長度

如前面章節所述,無論我們宣告 int* 或是 char* 甚至 double* ,指標變數的長度恆為 4 bytes



↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引