用字符數組和字符指針變量都可實現字符串的存儲和運算。但是兩者是有區別的。在使用時應注意以下幾個問題:
1.
【字符串指針變量】本身是一個變量,用於存放字符串的首地址。
而字符串本身是存放在以該首地址為首的一塊連續的內存空間中並以‘\0’作為串的結束。
【字符數組】是由於若干個數組元素組成的,它可用來存放整個字符串。
2.
對字符串指針方式
char *ps="C Language";
可以寫為:
char *ps;
ps="C Language";
而對數組方式:
char st[20]="C Language";
不能寫為:
char st[20];
st="C Language";
【編譯報錯】
error C2106: '=' : left operand must be l-value
而只能對字符數組的各元素逐個賦值。
從以上幾點可以看出字符串指針變量與字符數組在使用時的區別,同時也可看出使用指針變量更加方便。
當一個指針變量在未取得確定地址前使用是危險的,容易引起錯誤。
一個錯誤的例子,如下:
char *name;
scanf("%s",name);
printf("%s",name);
有的編譯器雖然也能通過,但這是錯誤的,因為是個指針,定義時指向不可用的地址。解決這個問題有兩種方法:用數組的方法或給字符針針分配內存空間的方法。
數組的方法:
char name[20];
scanf("%s",name);
printf("%s",name);
給字符針針分配內存空間的辦法:
char *name;
name=(char*)malloc(50); //此時name已經指向一個剛剛分配的地址空間。
scanf("%s",name);
printf("%s",name);
但是對指針變量直接賦值是可以的。因為C系統對指針變量賦值時要給以確定的地址。
3.int main(){
char str1[40]="hello world!"; //char *str1="hello world!";
str1[4]='A'; //若str1是指針型的,編譯通過,但運行是此處會段錯誤
printf("%s\n",str1);
return 0;
}
數組和指針都可以在它們的定義中用字符串常量進行初始化,盡管看上去一樣,底層的實現機制卻不相同。
定義指針時,編譯器並不為指針所指向的對象分配空間,它只是分配指針本身的空間,除非在定義的同時賦值給指針一個字符串常量進行初始化。例如:下面的定義創建了一個字符串常量(為其分配了內存):
char *p=”abcdefg”;
注意只有對字符串常量才是如此,不能指望為浮點數之類的常量分配空間,如:
Float *p=3.14; /*錯誤,無法通過編譯*/
下面結合一個實例談談初始化指針時創建的字符串常量與數組中的字符串的區別:
在ANSI C中,初始化指針時所創建的字符串常量被定義為只讀。如果試圖通過指針修改這個字符串的值,程序就會出現未定義的行為。在有些編譯器中,字符串常量被存放在只允許讀取的文本段中,以防止它被修改。
數組也可以用字符串常量進行初始化:
Char a[]=”abcdefg”;
如指針相反,由字符串常量初始化的數組是可以修改的。其中的單個字符在以後可以改變。
下面是一個在vc6中的一個例子,完成將一個字符串中的所有大寫字母全部轉換為小寫字母的功能:
#include<iostream.h>
#include<ctype.h>
int strlower(char *string) {
if(string==NULL)
return -1;
while(*string) {
if(isupper(*string))
*string=tolower(*string);
string++;
}
*string='\0';
return 0;
}
/*char *strlower(char *string) {
char *s;
if (string == NULL) {
return NULL;
}
s = string;
while (*s) {
if (isupper(*s)) {
*s = (char) tolower(*s);
}
s++;
}
*s = '\0';
return string;
}
*/
void main() {
char *test="ABCDEFGhijklmN";
strlower(test);
cout<<test<<endl;
}