在之前的學(xué)習(xí)中简识,我們?cè)?jīng)使用過printf函數(shù)對(duì)字符串進(jìn)行輸出。那么感猛,如果我們希望輸入一個(gè)字符串到變量七扰,我們可以怎么做呢?
第一種:scanf
陪白。
希望接收一個(gè)字符串到string
這個(gè)變量戳寸。可以使用scanf("%s", string);
這里寫的并不是&string
而是string
拷泽。因?yàn)樵?C 語言中,數(shù)組名直接可以被當(dāng)做數(shù)組所在內(nèi)存的地址使用袖瞻。輸出的時(shí)候可以使用printf("%s\n");
來輸出
對(duì)于如下代碼:
#include <stdio.h>
int main() {
char string[10];
// 請(qǐng)?jiān)谶@里使用 scanf
scanf("%s", string);
printf("%s\n",string);
return 0;
}
點(diǎn)擊 運(yùn)行 測(cè)試一下程序司致,看看如果你輸入hello world
、itisverylongforittostore
分別會(huì)有怎樣的結(jié)果聋迎?
當(dāng)輸入hello world
時(shí)脂矫,被輸出的只有hello
。這是因?yàn)?code>scanf在遇到空格時(shí)就已經(jīng)終止讀入了霉晕。
當(dāng)輸入一個(gè)很長的字符串時(shí)庭再,就出現(xiàn)了 Segmentation Fault(段錯(cuò)誤)
。因?yàn)槁暶鞯淖址麛?shù)組長度只有 10
牺堰,我們已經(jīng)在程序運(yùn)行時(shí)拄轻,讓它寫入了“不屬于它”的內(nèi)存空間。
來看看第二種:
嵌入占位符
#include <stdio.h>
int main() {
char information[100];
char *name = "Li, Lei";
char *gender = "male";
int age = 14;
float height = 187.5f;
// 在這里使用 sprintf
sprintf(information, "%s is a %s. He is %d-year-old and %fcm tall.", name, gender, age, height);
printf("%s", information);
}
輸出為
Li, Lei is a male. He is 14-year-old and 187.500000cm tall.
sprintf
在information
這一字符串中寫入了一個(gè)格式化輸出的結(jié)果伟葫,依照字符串格式描述恨搓,一系列int
、float
等類型的數(shù)據(jù)被“嵌入”到了格式字符串的占位符位置,并最終寫入到了information
中斧抱。
即將一系列的變量按照指定格式寫入到一個(gè)字符串中常拓。
sprintf
可用于各種數(shù)據(jù)的格式化:
- 第一個(gè)參數(shù)是被寫入的字符串;
- 第二個(gè)參數(shù)是寫入的格式;
- 之后的參數(shù)是依次會(huì)被寫入的數(shù)據(jù)。
在這里要提醒一下辉浦,我們一定要注意用于第一個(gè)參數(shù)的字符串聲明時(shí)的長度弄抬,如果它所對(duì)應(yīng)的內(nèi)存空間不足,我們現(xiàn)在的這種用法就可能會(huì)觸發(fā)段錯(cuò)誤宪郊。
字符串長度
頭文件#include <string.h>
使用方法:
strlen(字符串字面量或者變量) //返回得到的是其長度(不帶末位\0)
復(fù)制字符串
strcpy(copy, string); //第二個(gè)參數(shù)是被復(fù)制的字符串掂恕,第一個(gè)參數(shù)是需要復(fù)制到的目標(biāo)字符串變量位置
在程序中通過strcpy
完成了復(fù)制的過程后,copy
中就和string
中的字符串是一致的了废膘。
要注意一下竹海,在使用strcpy
時(shí)要確保目標(biāo)字符串的聲明長度可以裝得下,否則程序運(yùn)行時(shí)則可能會(huì)出現(xiàn)段錯(cuò)誤丐黄。
為避免此問題斋配,在工程中更多的鼓勵(lì)使用增加了第三個(gè)“復(fù)制長度”參數(shù)的strncpy
函數(shù)。即只把前n
個(gè)字符復(fù)制上去灌闺。
字符串的字典序(比較)
在數(shù)學(xué)中諸如 10 < 20
這樣數(shù)字的大小關(guān)系是天然定義的艰争,可是對(duì)于字符、字符串來說桂对,他們有“大小”關(guān)系嗎甩卓?
當(dāng)我們把"China"和"America"放在一起的時(shí)候,我們可以說它們這兩個(gè)字符串其中有一個(gè)大于另外一個(gè)么蕉斜?這個(gè)問題的回答是——“有”逾柿。
C 語言中對(duì)于字符的比較依賴的是字符的編碼,C 語言中默認(rèn)使用了 ASCII(American Standard Code for Information Interchange宅此,美國標(biāo)準(zhǔn)信息交換碼)作為編碼標(biāo)準(zhǔn)机错,每一個(gè)字符都對(duì)應(yīng)了一個(gè)整數(shù)值。常見的一些字符和他們對(duì)應(yīng)的編碼值如下:
通過參考列出的 ASCII 碼參考表(局部)父腕,在 C 語言中弱匪,字符直接進(jìn)行大小的比較時(shí),會(huì)對(duì)它們的編碼值進(jìn)行比較璧亮。因此萧诫,'A'小于'B','A'小于'a'枝嘶。
C 語言中帘饶,通常遵循一種特殊定義——字典序(lexicographical order)。
說白了就是后面的比前面的大群扶,有比沒有大尖奔。
"abc" < "bbc"
- 對(duì)于字符串
"abc"
和"bbc"
的大小關(guān)系——
我們首先會(huì)對(duì)它們的第一個(gè)字符進(jìn)行比較,
我們發(fā)現(xiàn)第一個(gè)字符'a'
<'b'
時(shí),
我們就可以明確"abc"
<"bbc"
的結(jié)論提茁。
"abc" < "abd"
- 對(duì)于字符串
"abc"
和"abd"
的大小關(guān)系——
我們首先會(huì)對(duì)它們的第一個(gè)字符進(jìn)行比較淹禾,
如果第一個(gè)字符相同,則會(huì)接下來比較第二個(gè)字符茴扁;
如果第二個(gè)字符相同铃岔,則會(huì)接下來比較第三個(gè)字符,
當(dāng)我們發(fā)現(xiàn)第三個(gè)字符'c'
<'d'
時(shí)峭火,我們就得到了"abc"
<"abd"
的結(jié)論毁习。
"ab" < "abc"
- 對(duì)于字符串
"abc"
和"ab"
的大小關(guān)系——
我們首先會(huì)對(duì)它們的第一個(gè)字符進(jìn)行比較,
如果第一個(gè)字符相同卖丸,則會(huì)接下來比較第二個(gè)字符纺且;
如果第二個(gè)字符相同,則會(huì)接下來比較第三個(gè)字符稍浆,
當(dāng)我們發(fā)現(xiàn)"ab"沒有第三個(gè)字符時(shí)载碌,我們就得到了"ab"
<"abc"
的結(jié)論嵌牺。
總結(jié):
- 字典序遵循 逐字符比較的方式胸哥,越靠左的字符越會(huì)被先比較策精。
- 逐字符比較過程中腰耙,一旦發(fā)現(xiàn)某一對(duì)被比較的字符之間不相等時(shí),這一對(duì)字符的大小關(guān)系即為這一對(duì)字符串的大小關(guān)系艇潭。
- 逐字符比較過程中侣诺,一旦出現(xiàn)某一個(gè)字符串的所有字符都已經(jīng)經(jīng)過比較拳锚,而另一字符串還存在未被比較的字符時(shí)益楼,較短的字符串更小猾漫。
- 如果所有字符串內(nèi)的字符都被發(fā)現(xiàn)相等,則這兩個(gè)字符串相等感凤。
因此悯周,字符串"China"大于"America"。
比較的語句 strcmp(input, string);
input
小于string
時(shí)返回了負(fù)數(shù)俊扭,當(dāng)input
等于string
時(shí)返回了 0
,當(dāng)input
大于string
時(shí)返回正數(shù)呢坠陈?
我們可以通過在if
的條件中寫:
strcmp(input, string) == 0
來判斷兩個(gè)字符串是否相同萨惑。也可以將等號(hào)改為大于號(hào)、小于號(hào)來判斷字符串的大小關(guān)系仇矾。
問題:
輸入 10行不含有空格的字符串庸蔼,對(duì)應(yīng)十個(gè)學(xué)生姓名(長度大于 0 小于 20)。
輸出為 101行贮匕,為排序后的 10 個(gè)學(xué)生姓名姐仅,每個(gè)學(xué)生姓名單獨(dú)占一行。
樣例輸入
Alice
Bob
Gary
Harry
Ivn
Julia
Danis
Fone
Candy
Evan
樣例輸出
Alice
Bob
Candy
Danis
Evan
Fone
Gary
Harry
Ivn
Julia
代碼
#include <stdio.h>
#include <string.h>
void swap(char a[20], char b[20]){
char c[20];
strcpy(c, a);
strcpy(a, b);
strcpy(b, c);
}
int main() {
char arr[10][20];
int i,j;
for (i = 0; i < 10; i++){
scanf("%s",arr[i]);
}
for (i = 0; i < 10; i++ ){
for (j = 0; j < 9; j++){
if (strcmp(arr[j],arr[j+1])>0){
swap(arr[j],arr[j+1]);
}
}
}
for (i = 0; i < 10; i++){
printf("%s\n",arr[i]);
}
}
字符串拼接
strcat(A, B);
會(huì)把參數(shù)的第二個(gè)字符串(含\0
)加在第一個(gè)字符串的/0位置
strcat函數(shù)將第二個(gè)參數(shù)的字符串(含\0
)拷貝到第一個(gè)參數(shù)的字符串\0所在內(nèi)存位置及之后。所以掏膏,我們通過
strcat(hello, world);
就會(huì)改變hello
的值劳翰,讓"hello "
之后多出了"world"
這段字符串
(假設(shè)char hello[100] = "hello "; char world[100] = "world";
)。
類似于strcpy
函數(shù)馒疹,在使用strcat
函數(shù)時(shí)佳簸,也要注意內(nèi)存安全問題。如果被連接上新內(nèi)容的目標(biāo)字符串的聲明長度不夠長颖变,程序就可能出錯(cuò)生均。相應(yīng)工程中也更鼓勵(lì)使用增加了第三個(gè)“追加長度”參數(shù)的strncat
函數(shù),即只把前n
個(gè)字符拼上去腥刹。大家可以通過搜索引擎具體了解一下马胧。