C字元陣列的賦值
strcmp函式是比較兩個字串的大小,返回比較的結果。一般形式是:
i=strcmp(字串,字串);
其中,字串1、字串2均可為字串常量或變數;i 是用於存放比較結果的整型變數。比較結果是這樣規定的:
①字串1小於字串2,strcmp函式返回一個負值;
②字串1等於字串2,strcmp函式返回零;
③字串1大於字串2,strcmp函式返回一個正值;那麼,字元中的大小是如何比較的呢?來看一個例子。
實際上,字串的比較是比較字串中各對字元的ASCII碼。首先比較兩個串的第一個字元,若不相等,則停止比較並得出大於或小於的結果;如果相等就接著 比較第二個字元然後第三個字元等等。如果兩上字串前面的字元一直相等,像"disk"和"disks" 那樣, 前四個字元都一樣, 然後比較第 五個字元, 前一個字串"disk"只剩下結束符'/0',後一個字串"disks"剩下's','/0'的ASCII碼小於's'的ASCII 碼,所以得出了結果。因此無論兩個字串是什麼樣,strcmp函式最多比較到其中一個字串遇到結束符'/0'為止,就能得出結果。
注意:字串是陣列型別而非簡單型別,不能用關係運算進行大小比較。
if("ABC">"DEF") /*錯誤的字串比較*/
if(strcmp("ABC","DEF") /*正確的字串比較*/
(二)strcpy函式
strcpy函式用於實現兩個字串的拷貝。一般形式是:
strcpy(字元中1,字串2)
其中,字串1必須是字串變數,而不能是字串常量。strcpy函式把字串2的內容完全複製到字串1中,而不管字串1中原先存放的是什麼。複製後,字串2保持不變。
例:
注意,由於字串是陣列型別,所以兩個字串複製不通過賦值運算進行。
t=s; /*錯誤的字串複製*/
strcpy(t,s); /*正確的字串複製*/
昨天在用結構體指標給結構體賦初值的時候,犯了一個錯誤(main函式中被註釋掉的那一句話)。而應該採用strcpy的方式把一個字串放入字元陣列中去,對此我將沿著我探討這個問題根源的思路做一個分享
#include <stdio.h>
#include <string.h>
#include <malloc.h>
typedef struct student_info
{
int number;
char name[32];
}stu, *p_student;
int main()
{
stu a; //注意要定義一個結構體出來
p_student p = NULL;
p = &a;
p->number = 1;
//p->name = “aa”; //錯誤
strcpy(p->name, “aa”); //正確
printf("%d:%s\n", p->number, a.name);
return 0;
}
在發現這個問題之後,我進行了如下的幾個嘗試:指標對這個陣列成員不能賦值,那直接用結構體變數是否可以?(不行);採用普通方式,對結構體變數a在定義的時候初始化,是否可行?(可行)
那麼最終問題在於陣列初始化和賦值的方面,對此進一步採用了幾個程式,對該知識點進行了深入的理解,程式如下
#include <stdio.h>
#include <string.h>
int main()
{
char a[] = "abcdef";
char *p = "abcdef";
char *p_a = NULL;
//p_a = a;
//fun(&p_a);
//a[0] = 'z';
//a = "z";
//a = 'z';
strcpy(a, "zf");
//p = "z";
*p = 'z';
printf("%s\n", a);
printf("%s\n", p);
//printf("%s\n", p_a);
return 0;
}
int fun(char **ar)
{
//char **p_a = &ar;
*ar = "zef";
//ar[0] = 'z';
// strcpy(ar, "z");
return 1;
}
以上是我在做知識點歸納時用的源程式,比較混亂,敬請了解。一下我將解釋一下,我到底做了那幾個方面的工作和討論
由於關係到字元陣列的賦值問題,我想到了這個例子,實驗了一下區別
把兩個相同的字串分別賦給一個字元陣列,和字元型指標。結果:均可以打印出來
那麼它們能否再被賦值修改呢?
對於字元陣列而已只能通過a[0] = 'z';或者strcpy(a, "zf");這樣的方式對其進行修改,總結的時候再歸納原因
對於字元型指標,p = "z";可以,但是注意這裡的實質卻並沒有對p字串進行修改。而*p = 'z';是不可行的
歸納總結一:
參考網路知識和《c和指標》中關於字元陣列的初始化部分
(注意:需要提前搞清楚,什麼是賦值,什麼是初始化,什麼是定義。相關知識可以參考網路資料,eg:int a;(定義),int a = 10;(初始化),a = 10;(賦值))
1對於字元陣列:
char a[15] = “abcdef”;
但不能做如下操作
char a[15];
a[15] = “abcdef”;
特別注意:第一種初始化的方式,看似左值是個字串,其實不然,它其實是個初始化列表。最後列表包含\0
因此,字元陣列是不能將字串賦給它的!
所以在後續的賦值裡必須對陣列元素進行賦值
2對於字串
char *p = “abcdef”;
注意這裡不是把一個字串賦給了一個字元型的指標,而是把一個字元型的指標指向了字串的首地址。
所以上面p = "z"只是把指標指向了另一個地方而已
3對於陣列與字串在機器中的儲存
陣列:
陣列在機器中,當被定義時eg:char a[10];就已經分配好了記憶體空間,放在了資料段中,其中的數值是可以進行修改的
字串:
字串在記憶體中也被存放在了資料段中,但是字串又稱為字串常量,是編譯器“釘死”無法修改的,所以*p = 'z';想改變字串的值是不被允許的
之後我又進行了一些嘗試,那就是將陣列作為一個函式的引數進行傳遞,看變換,這個知識點,我不做操作上的過多複述。
歸納總結二:
在此之前,我們首先得理解,陣列名。陣列名錶示著這個陣列的入口地址,這一點與函式名,結構體標識等類似。
eg:char a[10];那麼a表示的是這個陣列第一個元素的地址,即&a[0];
而&a;表示的是這個陣列的首地址。
估計不少人這個時候糊塗了,這兩個有區別嗎?數值不一樣麼?
它們兩個的數值是一樣的,因為地址只有一個,陣列的一個元素的地址的值就是這個陣列的地址的值,那麼為什麼還要分這麼細緻呢?下面舉個例子
eg:
char a[10];
char *p = NULL;
char (*p_a)[10] = NULL;
p = a;
p_a = &a;
如上面這個例子,a只能賦給一個char型的指標,而&a只能賦給一個指向一個數組的指標(注意這裡的這個陣列要與你定義的那個a陣列同大小)
藉助指標,我們不難理解,其實他們所代表的一個指標的型別是截然不同的(如果不能理解請參考c相關教程中指標的概念)
進入正文,所以當一個數組被傳遞如函式的時候可以把陣列名傳進去,也就是把這個陣列的第一個元素的首地址傳進去
作為指標被傳進去的陣列名這時和指標是完全一致的,可以作為指標使用,當然為直觀化,可以用做陣列
eg:
char a[10];
int fun(char *a)
{
a[0] = ‘A’;
}