第八章 初窺天機之字符串處理

有關字符處理的話題,哲理,引用等信息。

8.1 字符串簡單處理函數

在C語言函數庫中提供了一些用來專門處理字符串的函數。幾乎所有版本的C語言編譯系統都會提供這些函數。比如與字符串鏈接相關的strcat和strncat函數,與字符串複製相關的strcpy和strncpy函數,與字符串比較相關的strcmp和strncmp函數,與字符串大小寫轉換相關的strlwr和strupr函數,與字符串轉換成數值相關的atoi、atol與atof函數,與測量字符串長度的strlen函數等等,這些都只是字符串處理函數中的一小部分,下面我們將會介紹幾種常用的字符處理函數。

8.1.1 strcat和strncat函數——字符串鏈接函數

表8.1和表8.2分別爲strcat和strncat函數的語法要點。

表8.1 strcat函數語法要點

所需頭文件

#include <string.h>

函數原型

char *strcat(char *dest, char *source);

函數傳入值

dest:目的字符串

source:源字符串

函數功能

字符串拼接,將一個字符串添加到另一個字符串的末尾。

函數返回值

返回字符串指針,它的值是由字符串source連接到dest之後形成的。

表8.2 strncat函數語法要點

所需頭文件

#include <string.h>

函數原型

char *strncat(char *dest, char *source, size_t size);

函數傳入值

dest:目的字符串

source:源字符串

size:size字符串最終的最大長度

函數功能

字符串鏈接,將一個字符串按指定長度添加到另一個字符串末尾

函數返回值

返回一個字符串指針,它的值是由指定長度的字符串source鏈接到目的字符串末尾後形成的。

 

在表8.2 strncat函數語法要點中,函數原型爲:

char *strncat(char *dest, char *source, size_t size);

在該函數原型中出現了一個新類型爲:size_t。爲了增強程序的可移植性,便有了size_t。不同系統上,定義size_t可能不一樣。實際上,在32系統中size_t是4個字節,在64位系統中size_t是8字節,因此增加了程序的移植性。

根據命名定義我們知道size_t爲類型重定義。

原型:typedef unsigned int size_t;

由定義就可以看出,size_t是一個無符號的整型類型。用法和int,double等類似。

 

例8.1】strcat函數的使用。

解題思路:根據strcat函數的語法要點,首先定義兩個字符串,一個作爲目的字符串,一個作爲源字符串。注意目的字符串要開闢足夠大的存儲空間,這樣才能夠放下整個鏈接後的完整字符串。

程序編寫:

#include <stdio.h>
#include <string.h>//strcat函數的頭文件
int main()
{
	char dest[25] = "字符串";//目的字符串
	char source[5] = "鏈接";//源字符串
	strcat(dest, source);//字符串的鏈接,實現把source連接到dest末尾
	printf("%s\n", dest);//輸出鏈接後的字符串
	return 0;
}

運行結果:

字符串鏈接

Press any key to continue

 

程序分析:該程序程序實現了字符串的鏈接功能。不過需要注意的是在定義目的字符串dest時,需要提前申請足夠大的存儲空間,至少能夠存儲鏈接後的字符串長度。strcat函數的頭文件是string.h,所以在使用時我們需要先引用,如第二行所示:#include <string.h>。

 

例8.2】strncat函數的使用。

解題思路:根據strncat函數的語法要點,首先定義兩個字符串,一個作爲目的字符串,一個作爲源字符串。然後定義要複製源字符串到目的字符串的長度n。注意目的字符串要開闢足夠大的存儲空間,這樣才能夠放下整個鏈接後的完整字符串。

編寫程序:

#include <stdio.h>
#include <string.h>
int main()
{
	char dest[24]="\0";
	char source[] = "Hello C program!";
	size_t size = 7;//定義長度爲7
	printf("%s\n", source);//鏈接前的結果
	//複製source中size長度的字符串到dest中
	strncat(dest, source, size);//鏈接後的結果
	printf("%s\n", dest);
	return 0;
}

運行結果:

Hello C program!

Hello C

Press any key to continue

 

程序分析:由於size爲7,所以從字符串source中取出7個字符放到字符串dest中。這7個字符分別是:‘H’,‘e’,‘l’,‘l’,‘o’,‘ ’(空格),‘C’。目的字符串初始化爲“\0”,就是爲了避免出現亂碼!大家可以去掉“\0”,感受一下亂碼的肆虐···。

 

8.1.2 strcpy和strncpy函數——字符串複製函數

表8.3和表8.4分別爲strcpy函數和strncpy函數的語法要點。

表8.3 strcpy函數語法要點

所需頭文件

#include <string.h>

函數原型

char *strcpy(char *dest, char *source);

函數傳入值

dest:目的字符串

source:源字符串

函數功能

複製字符串

函數返回值

返回字符串指針,它的值是由字符串source複製到dest之後形成的。

表8.4 strncpy函數語法要點

所需頭文件

#include <string.h>

函數原型

char *strncpy(char *dest, char *source, int n);

函數傳入值

dest:目的字符串

source:源字符串

函數功能

字符串複製,將一串中指定數目的字符複製到另一個字符串中。

函數返回值

返回字符串指針,它的值是由指定長度的字符串source複製到dest之後形成的。

例8.3】trcpy函數的使用。

解題思路:根據trcpy函數的語法要點,首先定義兩個字符串,一個作爲目的字符串,一個作爲源字符串。然後把源字符串中的數據複製到目的字符串中。最後輸出結果。

編寫程序:

#include <stdio.h>
#include <string.h>
int main()
{
	char dest[25];//目的字符串
	char source[] = "你好,C語言。";//源字符串
	strcpy(dest, source);//strcpy函數實現源字符串複製到目的字符串中
	printf("%s\n", dest);
	return 0;
}

運行結果:

你好,C語言。

Press any key to continue

 

程序分析:注意目的字符串要開闢的存儲空間要大於等於源字符串這樣才能保證目的字符串完全存放下源字符串。

 

例8.4】strncpy函數的使用。

解題思路:根據trncpy函數的語法要點,首先定義兩個字符串,一個作爲目的字符串,一個作爲源字符串。然後把源字符串中的n個數據複製到目的字符串中。最後輸出結果。

編寫程序:

#include <stdio.h>
#include <string.h>
int main()
{
	char dest[25]="\0";//目的字符串
	char source[] = "你好,C語言。";//源字符串
	strncpy(dest, source, 7);//strcpy函數實現源字符串複製到目的字符串中
	printf("%s\n", dest);
	return 0;
}

運行結果:

你好,C

Press any key to continue

 

程序分析:在該程序中會發現第5行定義目的字符串時,用“\0”進行了初始化。這是因爲把source中的部分數據存放到dest中,而dest剩餘空間的存儲內容未知,如果不用“\0”初始化,程序輸出時會出現亂碼。第6行明明覆制了source串中的7個字符到dest串中,爲什麼結果只輸出“你好,C”呢?此處需要注意每個漢字佔兩字節,一個字符佔一個字節。所以“你好”和“C”共佔六個字節,“,”佔一個字節,加起來共佔7個字節了。所以輸出如上結果。

 

8.1.3 strcmp和strncmp函數——字符比較函數

表8.5和表8.6分別爲strcmp和strncmp函數的語法要點。

表8. 5strcmp函數的語法要點

所需頭文件

#include <string.h>

函數原型

int strcmp(char *str1, char *str2);

函數傳入值

str1:欲比較兩個字符串中第一個字符串

str2:欲比較兩個字符串中第二個字符串

函數功能

比較兩個字符串的大小。

函數返回值

返回0:字符串str1和str2相同

返回負數:字符串str1小於str2

返回正數:字符串str1大於str2

表8.6 strncmp函數的語法要點

所需頭文件

#include <string.h>

函數原型

int strcmp(char *str1, char *str2, size_t size);

函數傳入值

str1:欲比較兩個字符串中第一個字符串

str2:欲比較兩個字符串中第二個字符串

size:欲比較字符的個數

函數功能

將一個字符串的一部分與另一個字符串的一部分進行比較

函數返回值

返回0:指定長度的字符串str1和str2相同

返回負數:指定長度的字符串str1小於str2

返回正數:指定長度的字符串str1大於str2

例8.5】strcmp函數的使用。

解題思路:定義兩個要比較的字符串。字符串的具體數據我們採用用戶輸入的方式。

編寫程序:

#include <stdio.h>
#include <string.h>
int main()
{
	char str1[25];//第一個字符串
	char str2[25];//第二個字符串
	int result;//接受比較之後的結果
	scanf("%s", str1);
	scanf("%s", str2);
	result = strcmp(str1, str2);//strcmp函數實現兩個字符串的比較
	printf("%s %c %s\n", str1, result>=0?(result>0?'>':'='):'<', str2);
	return 0;
}

第一次運行結果:

computer

compare

computer > compare

Press any key to continue

 

第二次運行結果:

DOG

cat

DOG < cat

Press any key to continue

 

第三次運行結果:

China

China

China = China

Press any key to continue

 

程序分析:該程序採用輸入字符串的形式進行比較。觀察第一次的運行結果,發現“computer > compare”。爲什麼呢?strcmp函數的比較方式是首先取兩個字符串中的第一個字符進行比較,然後是第二字符進行比較,依次第三個,第四個···。觀察發現“computer”中的“c”和“compare”中的“c”ASCII碼值相同,則繼續進行比較。直到“u”和“a”的ASCII碼不同,“u”ASCII碼爲117(詳情參考附錄C中的ASCII碼錶),“a”的ASCII碼爲97。所以“u”大於“a”。如果兩個字符串中有一個字符串是另一個字符串的前部分,則較長的字符串較大。比如:bin < binary。第11行中存在兩個嵌套的三目運算:“result>=0?(result>0?'>':'='):'<'”。首先判斷是否“result>=0”,如果不是輸出“<”。如果是又存在一個三目運算符:“result>0?'>':'='”。接着判斷是否“result > 0”,如果不是,則說明result等於0,輸出“=”。如果是,則輸出“>”。

 

例8.6】strncmp函數的使用。

解題思路:定義兩個要比較的字符串。讓這兩個字符串前幾個字符相同,後幾個字符不同。

編寫程序:

#include <stdio.h>
#include <string.h>
int main()
{
	char str1[] = "computer";//第一個字符串
	char str2[] = "compare";//第二個字符串
	int result;//接受比較之後的結果
	result = strncmp(str1, str2, 4);//strncmp函數實現兩個字符串指定長度的比較
	printf("%s %c %s\n", str1, result>=0?(result>0?'>':'='):'<', str2);
	result = strncmp(str1, str2, 5);//strncmp函數實現兩個字符串指定長度的比較
	printf("%s %c %s\n", str1, result>=0?(result>0?'>':'='):'<', str2);
	return 0;
}

運行結果:

computer = compare

computer > compare

Press any key to continue

 

程序分析:程序第8行,指定字符串str1和str2的前四個字符進行比較,由於這兩個字符串前四個字符系統,所以輸出結果爲“computer = compare”。第10行指定這兩個字符串中的前五個字符進行比較,由於前四個相同,第五個不同,且“u”大於“a”,所以輸出結果爲“computer > compare”。

 

8.1.4 strlwr和strupr函數——轉換小寫大寫函數

表8.7和表8.8分別爲strlwr和strupr函數的語法要點。

表8.7 strlwr函數的語法要點

所需頭文件

#include <string.h>

函數原型

char *strlwr(char *s);

函數傳入值

s:待轉換的字符串

函數功能

將字符串轉換成小寫的形式。

函數返回值

返回指向轉換後的字符串的指針

表8.8 strupr函數的語法要點

所需頭文件

#include <string.h>

函數原型

char *strupr(char *s);

函數傳入值

s:待轉換的字符串

函數功能

將字符串轉換成小寫的形式。

函數返回值

返回指向轉換後的字符串的指針

例8.7】strlwr和strupr函數的使用。

解題思路:首先初始化一個含有大寫和小寫的字符串,然後用trlwr和strupr函數進行相應的轉換。

編寫程序:

#include <stdio.h>
#include <string.h>
int main()
{
	char s[] = "Hello C Program.";
	printf("%s\n", s);
	strlwr(s);//字符串轉換成小寫
	printf("%s\n", s);
	strupr(s);//字符串轉換成大寫
	printf("%s\n", s);
	return 0;
}

運行結果:

Hello C Program.

hello c program.

HELLO C PROGRAM.

Press any key to continue

 

程序分析:第7行實現把字符轉換成小寫。使用該函數時,如果字符本身就是小寫,則不轉換。如果字符是大寫,則轉換成小寫。第9行實現把字符轉換成大寫。使用該函數時,如果字符本身就是大寫,則不轉換。如果字符是小寫,則轉換成大寫。

 

8.1.5 atoi和atol和atof函數——轉換字符類型爲整型,長整型,浮點數

小夥伴們假如給你一個數字類型的字符串,要求你轉換成對應的數值,比如:字符串“54321”,讓你轉換成整數54321時,你會怎麼辦呢?聰明的你一定會想到一個一個字符的轉換,乘以相應的倍數,然後再相加。數據小還好,如果多了呢?嗚嗚,太麻煩了!那麼接下來這三個函數可以幫你大忙!

它們分別是:atoi函數、atol函數以及atof函數。

atoi:ASCII to int。

atol:ASCII to long

atof:ASCII to float

這三個函數的具體使用請看錶8.9,表8.10以及表8.11。

表8.9 atoi函數的語法要點

所需頭文件

#include <stdlib.h>

函數原型

int *atoi(const char *nptr);

函數傳入值

nptr:待轉換的字符串

函數功能

將字符串轉換成整型數據。

函數返回值

成功:返回字符串的整數值

失敗:返回0

接下來是atol函數的說明。

表8.10 atol函數的語法要點

所需頭文件

#include <stdlib.h>

函數原型

long *atoi(const char *nptr);

函數傳入值

nptr:待轉換的字符串

函數功能

將字符串轉換成長整型數值。

函數返回值

成功:返回字符串的長整數值

失敗:返回0

接着是atof函數的說明。

表8.11 atol函數的語法要點

所需頭文件

#include <stdlib.h>或#include <math.h>

函數原型

double *atol(const char *nptr);

函數傳入值

nptr:待轉換的字符串

函數功能

將字符串轉換成浮點數值。

函數返回值

成功:返回字符串的雙精度浮點數值

失敗:返回0

經過上面三個函數原型的講解,是不是對如何使用這三個函數充滿了期待呢?下面讓我們用一個實際的事例來對這三個函數進行詳細的講解。

例8.8】atoi函數,atol函數,atof函數的使用。

解題思路:我們定義兩個數字字符串,其中一個完全是數字組成,另一個是有一個小數點和數字組成。再定義一個整型變量,一個長整形變量,還有一個浮點數變量。最後按照上面三個表中的相應格式寫出對應代碼。

編寫程序:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	char s1[] = "1234567.89";
	char s2[] = "1234567890";
	int n1;
	long n2;
	double n3;
	n1 = atoi(s1);//把s1轉換成整數n1,會自動去掉小數點及其後的數值
	printf("s1=%s, n=%d\n", s1, n1);
	n3 = atof(s1);//把s1轉換成浮點數n2
	printf("s1=%s, n=%lf\n", s1, n3);
	n2 = atol(s2);//把s2轉換成長整數n1
	printf("s1=%s, n=%ld\n", s2, n2);
	return 0;
}

運行結果:

s1=1234567.89, n=1234567

s1=1234567.89, n=1234567.890000

s1=1234567890, n=1234567890

Press any key to continue

 

程序分析:第10行中,是把浮點數轉換成整數,由於浮點數中含有小數點,程序會自動把小數點之後的數據捨去,所以顯示的結果爲1234567。第12行會把s1轉換成浮點數,轉換後的結果保存到n3中。第14行類似。

當然還有從數值轉換成字符串的函數,比如itoa()函數把整數轉換成字符串,ftoa函數把浮點數轉換成字符串,具體的使用,我就不再此處說了。大家可以在使用的時候再去詳細的瞭解。

 

8.1.6 strlen函數——測字符串長度

在很多時候我們需要知道一個未知字符串的長度,所以strlen函數就隆重登場了。表8.12位strlen函數的使用說明。

表8.12 strlen函數的語法要點

所需頭文件

#include <string.h>

函數原型

size_t *strlen(const char *str);

函數傳入值

str:要獲取長度的字符串

函數功能

獲取字符串的長度。

函數返回值

返回字符串的長度

一看理論我也頭大了,好,直接上例題。

例8.9】strlen函數的使用。

解題思路:只需要初始化一個指定長度的字符串,然後調用strlen函數計算長度即可。

編寫程序:

#include <stdio.h>
#include <string.h>
int main()
{
	char str[] = "hello, my friend.";//要測量的字符串
	int n;//存放測量的長度
	n = strlen(str);//測量字符串str的長度
	printf("%d\n", n);
	return 0;
}

運行結果:

17

Press any key to continue

 

程序分析:第7行,表示測量字符串str的長度,然後保存到n變量中。

 

有關字符串處理的函數還有好多好多。如果大家想要深入瞭解請查閱相關資料,不過我在此推薦一本主要講C語言相關的各種函數的書,叫《C語言全能速查寶典》。此書講解了更多了,且常用的C語言相關的函數。

 

8.2 自己的字符串處理函數

經過上面的學習恭喜大家已經初步掌握了一些與字符串操作相關的函數。太好了,那就接着讓我們去探索自己的C語言函數吧!對,你沒有聽錯,你也可以寫自己的函數。那麼我們就先拿一個簡單的字符串處理函數開開胃。

8.2.1 自己實現strlen函數功能

如何實現自己的strlen函數呢?我們可以每輸入一個字符,就使輸入的個數增加1。最後統計出總個數。還有需要注意的是一個字符一個字符的接受數據時,還需要接受一個字符串結束標誌‘\0’。這樣可以在以字符串輸出時不會出現亂碼,當然我們也可以初始化時就賦值字符串結束標誌。下面讓我們看看自己的計算的字符串長度吧!

 

例8.10】自己實現strlen函數獲取字符串長度。

解題思路:我們可以定義一個整數變量i用來統計字符個數,每輸入一個字符,就使i增加1。直到遇到回車符字符串的輸入結束。

編寫程序:

#include <stdio.h>
#include <string.h>
int main()
{
	char str[100];
	int i=-1;
	printf("請輸入一個字符串:");
	do 
	{
		i++;
		scanf("%c", &str[i]);
	} while (str[i] != '\n');//字符串接受以回車結束
	str[i] = '\0';//需要增加一個結束符'\0'
	printf("字符串長度: %d\n字符串: %s\n", i, str);
	return 0;
}

運行結果:

請輸入一個字符串:ds .,w/e;'][=-097123`\324kfi

字符串長度: 28

字符串: ds .,w/e;'][=-097123`\324kfi

Press any key to continue

 

程序分析:我們用do-while循環來依次獲取字符,當接收到回車符‘\n’時,就結束循環。第13行在字符串末尾賦值爲‘\0’,是爲了以字符串輸出時,避免出現亂碼。

 

8.2.2 自己實現字符串翻轉函數

上一節我們只是簡單的計算了字符串的長度,這一節我們將會繼續深入的封裝自己的函數,形成自己的函數庫。那麼我們將會以字符翻轉爲例進行說明。

什麼是字符串翻轉?

就是把一個正序的字符串逆序輸出就是字符串的翻轉。比如源字符串“ABC123”,翻轉之後的字符串是“321CBA”。是不是很簡單啊?

我們還需要了解函數書寫和調用,這樣就會距離我們自己的函數只有一步之遙了。下面是一段函數調用有關的代碼。

#include <stdio.h>
void myRecv(char source[],char dest[], int n);
int main()
{
	char source[100], dest[100];
	int n;
	//輸入源字符串
	...
	myRecv(source, dest, n);
	return 0;
}
void myRecv(char source[],char dest[], int n)
{
	//函數翻轉的處理過程
	...
}

第1行是程序的頭文件,不多講。第2行與12~16行對應,在寫函數時,需要先聲明(第2行),然後再定義函數的功能等信息(12~16行)。其實第2行和第12行是完全一樣的,就是多了一個分號而已。聲明是爲了告訴程序我有這樣一個函數,到這個函數時,你就可以執行它。程序執行順序還是先執行mian函數(第3行),因爲這個程序的入口,然後執行到自己寫的函數myRecv(source, dest, n),在執行前查看我們是否聲明,如果聲明,就跳到該函數的入口處(第12行)執行該函數。我們往後寫程序按照這樣格式寫就行了。很簡單。下面我們以一個字符串翻轉的實例進行說明。

例8.11】寫自己的字符串翻轉函數。

解題思路:首先聲明字符串翻轉函數,然後定義字符串翻轉函數功能。最後在main函數中調用自己寫的函數。

編寫程序:

#include <stdio.h>
void myStrrev(char source[], char dest[], int n);
int main()
{
	char source[100]="\0", dest[100]="\0";
	int i=-1;
	printf("請輸入一個字符串:");
	do 
	{
		i++;
		scanf("%c", &source[i]);
	} while (source[i] != '\n');//字符串接受以回車結束
	source[i]='\0';//去掉多接受的回車符
	myStrrev(source, dest, i);
	printf("源字符串: %s\n翻轉後字符串: %s\n", source, dest);
	return 0;
}
void myStrrev(char source[], char dest[], int n)
{
	int i;
	for (i=0; i<n; i++)
	{
		dest[i] = source[n-i-1];
	}
}

運行結果:

請輸入一個字符串:asdfghjkl

源字符串: asdfghjkl

翻轉後字符串: lkjhgfdsa

Press any key to continue

 

程序分析:我們如果寫自己的函數,首先需要聲明,然後才能定義使用。當然我們可以不用聲明,直接把函數處理過程放到main函數之前也是完全可以的。比如:

#include <stdio.h>
void myStrrev(char source[], char dest[], int n)
{
	int i;
	for (i=0; i<n; i++)
	{
		dest[i] = source[n-i-1];
	}
}
int main()
{
	char source[100]="\0", dest[100]="\0";
	int i=-1;
	printf("請輸入一個字符串:");
	do 
	{
		i++;
		scanf("%c", &source[i]);
	} while (source[i] != '\n');//字符串接受以回車結束
	source[i]='\0';//去掉多接受的回車符
	myStrrev(source, dest, i);
	printf("源字符串: %s\n翻轉後字符串: %s\n", source, dest);
	return 0;
}

這個程序和前面的那一個程序功能是完全一致的。和函數相關的知識,我們將會在下一章進行詳細講解。當然我們的C語言也有相應的處理字符串翻轉的函數——strrev函數。表8.13爲strrev函數的語法要點。

表8.13 strrev函數語法要點

所需頭文件

#include <string.h>

函數原型

char *strlen(char *str);

函數傳入值

str:要轉換的字符串

函數功能

將一個順序字符串逆序。

函數返回值

返回逆序後的字符串

表8.13包含了strrev函數的詳細信息。下面我們也就相應的給出一個簡單的實例代碼,使大家更容易理解函數的使用和功能。

 

例8.12】strrev函數的使用。

解題思路:輸入一個字符串,使用strrev函數進行翻轉,然後輸出翻轉後的結果。

編寫程序:

#include <stdio.h>
#include <string.h>
int main()
{
	char str[100]="\0";
	printf("請輸入一個字符串:");
	scanf("%s", str);
	strrev(str);
	printf("翻轉後的字符串: %s\n", str);
	return 0;
}

運行結果:

請輸入一個字符串:abcde

翻轉後的字符串: edcba

Press any key to continue

 

8.3 再次探索字符串處理函數

由於字符串操作在程序設計中扮演着重要的角色,所以字符串操作也是C語言中一個重要的知識點。這也是爲什麼我們要再次探索字符串處理的原因。無論我們的控制檯操作,還是Linux下的終端操作,亦或是我們的界面操作,接受的都是字符串,然後再準換成我們需要的數據類型,那麼字符串與其他類型的轉換就顯得極其重要了。

 

//添加   哲理

 

8.3.1 isalnum、isalpha和isdigit函數——字母、數字判斷

C語言中很多情況下我們需要判斷一個字符串是不是數字或者是字母。比如QQ號,驗證手機時的手機號,都需要整數數值。你的郵箱或者淘寶密碼是數字和字母的組合。而你的姓名拼音則完全是字母了。接下來我們就會講解一下有關字母和數字相關的字符串處理函數。

首先奉上isalnum函數,該函數就是判斷你輸入的數據是不是字母或數字。詳細功能請看錶8.14,爲isalnum函數的語法要點。

表8.14 isalnum函數語法要點

所需頭文件

#include <ctype.h>

函數原型

int isalnum(int c);

函數傳入值

c:待分類的值

函數功能

用於字母和數字的字符分類,即判斷是否屬於字母和數字。

函數返回值

若參數c爲一個A~Z的大寫字母或a~z的小寫字母或0~9的數字時,返回一個非零值;否則返回0。

接下來是一個isalnum函數使用的具體實例。

例8.13】isalnum函數的使用。

解題思路:美輸入一個字符就判斷一下是否是數字或者字母,如果是輸出提示,如果不是也輸出提示。

編寫程序:

#include <stdio.h>
#include <ctype.h>
#include <conio.h>
int main()
{
	int c;
	do 
	{
		c = getch();
		if (isalnum(c))
		{
			printf("%c是字母或數字。\n", c);
		}
		else
		{
			printf("%c不是字母或數字。\n", c);
		}
	} while (1);
	return 0;
}

運行結果:

d是字母或數字。

5是字母或數字。

/不是字母或數字。

 

程序分析:第6行我們定義了一個int型的變量c,因爲整型也是可以看做對應的ASCII碼十進制所對應的數值。第9行的getch函數第三章我們都已經進行了講解。就是直接輸出輸入的數據,不需要接受回車符輸出結果至屏幕。

經過isalnum這個函數我們就可以知道接受的數據是否只是數字或字母,而不是其他的非法字符了。但是問題有來了?如果我們只要求接受的是數字呢?或者我們要求接受的只是字母呢?這可怎麼辦?顯然isalnum函數不能滿足我們的需求,因此以下兩個函數因你的需求,應運而生啊!他們就是isalpha和isdigit函數。isalpha函數功能就是判斷輸入的字符是否是字母。而isdigit函數功能是判斷輸入的字符是否是數字。詳細信息請看錶8.15和8.16分別爲isalpha函數和isdigit函數的詳細介紹。

表8.15 isalpha函數語法要點

所需頭文件

#include <ctype.h>

函數原型

int isalpha(int c);

函數傳入值

c:待分類的值

函數功能

用於字母的字符分類,判斷是否屬於字母。

函數返回值

若參數c爲一個A~Z的大寫字母或a~z的小寫字母時,返回一個非零值;否則返回0。

表8.16 isdigit函數語法要點

所需頭文件

#include <ctype.h>

函數原型

int isdigit(int c);

函數傳入值

c:待分類的值

函數功能

用於數字的字符分類,判斷是否屬於數字。

函數返回值

若參數c爲一個0~9的數字時,返回一個非零值;否則返回0。

經過枯燥的講解,下面讓我們來看一看具體的代碼吧!

例8.14】isalpha和isdigit函數的使用。

解題思路:我們使用一個do-while循環,每次輸入一個字符分別用isalpha和isdigit函數進行判斷,根據不同的輸入字符輸出相應的結果信息。

編寫程序:

#include <stdio.h>
#include <ctype.h>
#include <conio.h>
int main()
{
	int c;
	do 
	{
		c =getch();
		if (isalpha(c))
		{
			printf("%c是字母。\n", c);
		} 
		else if (isdigit(c))
		{
			printf("%c是數字。\n", c);
		}
		else
		{
			printf("%c即不是字母也不是數字。\n", c);
		}
	} while (1);
	return 0;
}

運行結果:

a是字母。

6是數字。

.即不是字母也不是數字。

 

程序分析:程序中我們使用if-elseif-else組成的條件語句,進行判斷輸入的字符到底是字母、數字或者是其他字符。當輸入的a是字母時,經過函數isalpha就能判斷出它是字母。當輸入的6時數字時,首先經過isalpha函數判斷他不是字母,然後經過isdigit函數判斷是數字。當輸入“.”時經過分別經過isalpha函數和isdigit函數的判斷,既不是字母也不是數字。

 

8.3.2 進一步理解isalpha和isdigit函數

經過上面對isalpha和isdigit這兩個函數參數和使用的簡單講解,可以基本上掌握這兩個函數的使用,但是爲了進一步加深大家對這兩個函數的理解,我們此處以一個實際應用的例子通過編碼進行更加詳細的說明。

8.15】判斷字符串中是否存在數字或者字母及其所在位置

解題思路:下面這段代碼用以判斷字符串中是否存在數字、字母或者其他字符,並統計對應類型的個數。

編寫程序:

#include <stdio.h>
#include <ctype.h>
#include <stdint.h>
int main()
{
	char ch[] = "h1ell2o w3orl4d!";
	size_t len = strlen(ch);
	size_t i = 0, digit_cnt = 0, alpha_num = 0, others_num = 0;
	for (i=0; i<len; i++)
	{
		if (isalpha(ch[i]))
		{
			alpha_num++;
			printf("%c是字母,位置在第%u。\n", ch[i], i+1);
		} 
		else if (isdigit(ch[i]))
		{
			digit_cnt++;
			printf("%c是數字,位置在第%u。\n", ch[i], i+1);
		}
		else
		{
			others_num++;
			printf("%c即不是字母也不是數字,位置在第%u。\n", ch[i], i+1);
		}
	} 
	printf("共有%d個字母,%d個數字以及%d個其他字符。\n", alpha_num, digit_cnt, others_num);
	return 0;
}

運行結果:

h是字母,位置在第1。

1是數字,位置在第2。

e是字母,位置在第3。

l是字母,位置在第4。

l是字母,位置在第5。

2是數字,位置在第6。

o是字母,位置在第7。

 即不是字母也不是數字,位置在第8。

w是字母,位置在第9。

3是數字,位置在第10。

o是字母,位置在第11。

r是字母,位置在第12。

l是字母,位置在第13。

4是數字,位置在第14。

d是字母,位置在第15。

!即不是字母也不是數字,位置在第16。

共有10個字母,4個數字以及2個其他字符。

 

程序分析:之前的size_t類型是我們自己定義的,但實際上在C語言的頭文件stdint.h中就定義了這種類型,爲無符號的整型類型。

 

 

8.4 字符串查找函數

上面的函數,通過循環可以查找某個字母、數字或者其他什麼字符的位置,那麼存不存在C語言已經給我們寫好的字符串函數讓我們直接使用呢?當然存在,它就是strchr函數,這個函數就是字符串中查找某個字符。

有了這個字符查找函數,大家會不會想,如何從一個字符串中找到一個子字符串呢?當然,你有猜對了。這個函數就是strstr函數。下面讓我們具體講解一下這兩個函數。

表8.17 strchr函數語法要點

所需頭文件

#include <string.h>

函數原型

char *strchr(const char *str, int c);

函數傳入值

str:待檢索的字符串

c:在str中要搜索的字符

函數功能

在字符串str所指的字符串中搜索第一次出現字符c的位置。

函數返回值

函數返回在字符串中第一次出現字符c的位置,如果沒有找到則返回NULL。

表8.18 strstr函數語法要點

所需頭文件

#include <string.h>

函數原型

char *strstr(char *str, const char *substr);

函數傳入值

str:待檢索的字符串

substr:要查找的對象字符串

函數功能

在字符串str所指的字符串中搜索第一次出現字符串substr的位置。

函數返回值

函數返回在字符串中第一次出現字符串substr的位置,如果沒有找到則返回NULL。

下面將會對這兩個函數通過代碼講解具體的使用。

【例8.16】字符串中查找字符和子串

解題思路:

編寫程序:

#include <stdio.h>
#include <string.h>
int main()
{
	const char str[] = "hello world, hello world!";
	const char c = 'l';
	const char substr[] = "world";
	const char *p_c=NULL, *p_str=NULL;
	p_c = strchr(str, c);
	printf("字符%c第一次出現的位置在第%d個。\n", c, (p_c - str)+1);
	
	p_str = strstr(str, substr);
	printf("字符串%s第一次出現的位置在第%d個。\n", substr, (p_str - str)+1);
	
	p_c = str;
	printf("字符\"%c\"出現的位置分別在:\n", c);
	while(1){
		p_c = strchr(p_c, c);
		if(p_c != NULL){
			p_c++;
			printf("%d\t", (p_c - str));
		}
		else
			break;
	}
	
	p_str = str;
	printf("\n字符串\"%s\"出現的位置分別在:\n", substr);
	while(1){
		p_str = strstr(p_str, substr);
		if(p_str != NULL){
			p_str++;
			printf("%d\t", (p_str - str));
		}
		else
			break;
	}
	printf("\n");
	
	return 0;
}

運行結果:

字符l第一次出現的位置在第3個。

字符串world第一次出現的位置在第7個。

字符"l"出現的位置分別在:

3       4       10      16      17      23

字符串"world"出現的位置分別在:

7       20

 

程序分析:程序第9行和第12行表示這兩個函數的簡單使用,如果字符串中找到某個字符或子串,很簡單是吧。如果我們找到所有要查找的某個字符或者字符串呢?那麼下面二十幾行代碼就顯得很必要了。在程序17~25行,我們使用是一個無限循環來查找字符‘l’,利用找到返回字符地址,找不到返回NULL的特性來查找字符‘l’,因爲每次返回時的當前找到字符的地址,所以進行下次查找時才需要把指針地址後移一位,如20行所示。同樣,strstr函數在29~31行也是如此。

 

沙場點兵之,,,

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章