?? 第6章 字符串操作.txt
字號(hào):
C語(yǔ)言編程常見(jiàn)問(wèn)題解答
發(fā)表日期:2003年9月30日 已經(jīng)有2342位讀者讀過(guò)此文
第6章 字符串操作
本章集中討論字符串操作,包括拷貝字符串,拷貝字符串的一部分,比較字符串,字符串右對(duì)齊,刪去字符串前后的空格,轉(zhuǎn)換字符串,等等。C語(yǔ)言提供了許多用來(lái)處理字符串的標(biāo)準(zhǔn)庫(kù)函數(shù),本章將介紹其中的一部分函數(shù)。
在編寫C程序時(shí),經(jīng)常要用到處理字符串的技巧,本章提供的例子將幫助你快速學(xué)會(huì)一些常用函數(shù)的使用方法,其中的許多例子還能有效地幫助你節(jié)省編寫程序的時(shí)間。
6.1 串拷貝(strcpy)和內(nèi)存拷貝(memcpy)有什么不同?它們適合于在哪種情況下使用?
strcpy()函數(shù)只能拷貝字符串。strcpy()函數(shù)將源字符串的每個(gè)字節(jié)拷貝到目錄字符串中,當(dāng)遇到字符串末尾的null字符(\0)時(shí),它會(huì)刪去該字符,并結(jié)束拷貝。
memcpy()函數(shù)可以拷貝任意類型的數(shù)據(jù)。因?yàn)椴⒉皇撬械臄?shù)據(jù)都以null字符結(jié)束,所以你要為memcpy()函數(shù)指定要拷貝的字節(jié)數(shù)。
在拷貝字符串時(shí),通常都使用strcpy()函數(shù);在拷貝其它數(shù)據(jù)(例如結(jié)構(gòu))時(shí),通常都使用memcpy()函數(shù)。
以下是一個(gè)使用strcpy()函數(shù)和memcpy()函數(shù)的例子:
#include <stdio. h>
#include <string. h>
typedef struct cust-str {
int id ;
char last_name [20] ;
char first_name[l5];
} CUSTREC;
void main (void);
void main (void)
{
char * src_string = "This is the source string" ;
char dest_string[50];
CUSTREC src_cust;
CUSTREC dest_cust;
printf("Hello! I'm going to copy src_string into dest_string!\n");
/ * Copy src_ string into dest-string. Notice that the destination
string is the first argument. Notice also that the strcpy()
function returns a pointer to the destination string. * /
printf("Done! dest_string is: %s\n" ,
strcpy(dest_string, src_string)) ;
printf("Encore! Let's copy one CUSTREC to another. \n") ;
prinft("I'll copy src_cust into dest_cust. \n");
/ * First, intialize the src_cust data members. * /
src_cust. id = 1 ;
strcpy(src_cust. last_name, "Strahan");
strcpy(src_cust. first_name, "Troy");
/ * Now, Use the memcpy() function to copy the src-cust structure to
the dest_cust structure. Notice that, just as with strcpy(), the
destination comes first. * /
memcpy(&dest_cust, &src_cust, sizeof(CUSTREC));
printf("Done! I just copied customer number # %d (%s %s). " ,
dest_cust. id, dest_cust. first_name, dest_cust. last_name) ;
}
請(qǐng)參見(jiàn):
6.6怎樣拷貝字符串的一部分?
6.7怎樣打印字符串的一部分?
6. 2怎樣刪去字符串尾部的空格?。
C語(yǔ)言沒(méi)有提供可刪去字符串尾部空格的標(biāo)準(zhǔn)庫(kù)函數(shù),但是,編寫這樣的一個(gè)函數(shù)是很方便的。請(qǐng)看下例:
#include <stdio. h>
# include <string. h>
void main (void);
char * rtrim(char * );
void main(void)
{
char * trail_str = "This string has trailing spaces in it";
/ * Show the status of the string before calling the rtrim()
function. * /
printf("Before calling rtrim(), trail_str is '%s'\fi" , trail_str);
print ("and has a length of %d. \n" , strlen (trail_str));
/ * Call the rtrimO function to remove the trailing blanks. * /
rtrim(trail_str) ;
/ * Show the status of the string
after calling the rtrim() function. * /
printf("After calling rttim(), trail_ str is '%s'\n", trail _ str );
printf ("and has a length of %d. \n" , strlen(trail-str)) ;
}
/ * The rtrim() function removes trailing spaces from a string. * /.
char * rtrim(char * str)
{
int n = strlen(str)-1; / * Start at the character BEFORE
the null character (\0). * /
while (n>0) / * Make sure we don't go out of hounds. . . * /
{
if ( * (str + n) 1 =' ') / * If we find a nonspace character: * /
{
* (str+n+1) = '\0' ; / * Put the null character at one
character past our current
position. * /
break ; / * Break out of the loop. * /
}
else / * Otherwise , keep moving backward in the string. * /.
n--;
}
return str; /*Return a pointer to the string*/
}
在上例中,rtrim()是用戶編寫的一個(gè)函數(shù),它可以刪去字符串尾部的空格。函數(shù)rtrim()從字符串中位于null字符前的那個(gè)字符開(kāi)始往回檢查每個(gè)字符,當(dāng)遇到第一個(gè)不是空格的字符時(shí),就將該字符后面的字符替換為null字符。因?yàn)樵贑語(yǔ)言中null字符是字符串的結(jié)束標(biāo)志,所以函數(shù)rtrim()的作用實(shí)際上就是刪去字符串尾部的所有空格。
請(qǐng)參見(jiàn):
6.3怎樣刪去字符串頭部的空格?
6.5怎樣將字符串打印成指定長(zhǎng)度?
6.3 怎樣刪去字符串頭部的空格?
C語(yǔ)言沒(méi)有提供可刪去字符串頭部空格的標(biāo)準(zhǔn)庫(kù)函數(shù),但是,編寫這樣的一個(gè)函數(shù)是很方便的。請(qǐng)看下例;
#include <stdio. h>
#include <string. h>
void main(void);
char * ltrim (char * ) ;
char * rtrim(char * ) ;
void main (void)
{
char * lead_str = " This string has leading spaces in it. " ;,
/ * Show the status of the string before calling the Itrim()
function. * /
printf("Before calling Itrim(), lead-str is '%s'\n", lead_str);
printf("and has a length of %d. \n" , strlen(lead_str));
/ * Call the Itrim() function to remove the leading blanks. * /.
Itrim(lead_str);
/ * Show the status of the string
after calling the Itrim() function. * /
prinft("After calling Itrim(), lead_str is '%s'\n", lead_str);
print("and has a length of %d. \n'' , strlen(lead-str)) ;
}
/ * The Itrim() function removes leading spaces from a string. * /
char * ltrim(char * str)
{
strrev(str) ; / * Call strrevO to reverse the string. * /
rtrim(str)). /* Call rtrimO to remvoe the "trailing" spaces. * /
strrev(str); / * Restore the string's original order. * /
return str ; / * Return a pointer to the string. * /.
}
/ * The rtrim() function removes trailing spaces from a string. * /
char* rtrim(char* str)
{
int n = strlen (str)-l ; / * Start at the character BEFORE
the null character (\0). * /
while (n>0) / * Make sure we don't go out of bounds... * /.
{
if ( * (str+n) ! =' ') If we find a nonspace character: * /
{
* (str+n + 1) = '\0' ; / * Put the null character at one
character past our current
position. * /
break;j / * Break out of the loop. * /
}
else / * Otherwise, keep moving backward in the string. * /
n --;
}
return str; /* Return a pointer tO the string. */
}
在上例中,刪去字符串頭部空格的工作是由用戶編寫的ltrim()函數(shù)完成的,該函數(shù)調(diào)用了·6.2的例子中的rtrim()函數(shù)和標(biāo)準(zhǔn)C庫(kù)函數(shù)strrev()。ltrim()函數(shù)首先調(diào)用strrev()函數(shù)將字符串顛倒一次,然后調(diào)用rtrim()函數(shù)刪去字符串尾部的空格,最后調(diào)用strrev()函數(shù)將字符串再顛倒一次,其結(jié)果實(shí)際上就是刪去原字符串頭部的空格。
請(qǐng)參見(jiàn):
6.2怎樣刪去字符串尾部的空格?
6.5怎樣將字符串打印成指定長(zhǎng)度?
6.4 怎樣使字符串右對(duì)齊?
C語(yǔ)言沒(méi)有提供可使字符串右對(duì)齊的標(biāo)準(zhǔn)庫(kù)函數(shù),但是,編寫這樣的一個(gè)函數(shù)是很方便的。請(qǐng)看下例:
#include <stdio. h>
#include <string. h>
#include <malloc. h>
void main (void);
char * r just (char * ) ;
char * rtrim(char * );
void main (void)
{
char * rjust_str = "This string is not righ-justified. " ;
/ * Show the status of the string before calling the rjust()
function. * /
printf("Before calling rjust(), rjust_str is ' %s'\n. " , rjust_str);
/ * Call the rjustO function to right-justify this string. * /
rjust(rjust_str) ;
/ * Show the status of the string
after calling the rjust() function. * /
printf ("After calling rjust() , rjust_str is ' %s'\n. " , rjust_str) ;
}
/ * The rjust() function right-justifies a string. * /
char * r just (char * str)
{
int n = strlen(str); / * Save the original length of the string. * /
char* dup_str;
dup_str = strdup(str); / * Make an exact duplicate of the string. * /
rtrim(dup_str); /* Trim off the trailing spaces. */
/ * Call sprintf () to do a virtual "printf" back into the original
string. By passing sprintf () the length of the original string,
we force the output to be the same size as the original, and by
default the sprintf() right-justifies the output. The sprintf()
function fills the beginning of the string with spaces to make
it the same size as the original string. * /
sprintf(str, "%*. * s", n, n, dup_str);
free(dup-str) ; / * Free the memory taken by
the duplicated string. * /
return str;\ / * Return a pointer to the string. * /
}
/ * The rtrim() function removes trailing spaces from a string. * /
char * rtrim(char * str)
{
int n = strlen(str)-l; / * Start at the character BEFORE the null
character (\0). * /
while (n>0) / * Make sure we don't go out of bounds... * /
{
if ( * (str+n) ! = ' ') / * If we find a nonspace character: * /
{
* (str + n + 1) = '\0';( / * Put the null character at one
character past our current
position. * /
break; / * Break out of the loop. * /
}
else / * Otherwise, keep moving backward in the string. * /
n—;
}
return str ; / * Return a pointer to the string. * /
}
在上例中,使字符串右對(duì)齊的工作是由用戶編寫的rjust()函數(shù)完成的,該函數(shù)調(diào)用了6.2的例子中的rtrim()函數(shù)和幾個(gè)標(biāo)準(zhǔn)函數(shù)。rjust()函數(shù)的工作過(guò)程如下所示:
(1) 將原字符串的長(zhǎng)度存到變量n中。這一步是不可缺少的,因?yàn)檩敵鲎址驮址拈L(zhǎng)度必須相同。
(2) 調(diào)用標(biāo)準(zhǔn)C庫(kù)函數(shù)strdup(),將原字符串復(fù)制到dup_str中。原字符串需要有一份拷貝,因?yàn)榻?jīng)過(guò)右對(duì)齊處理的字符串要寫到原字符串中。
(3) 調(diào)用rtrim()函數(shù),刪去dup_str尾部的空格。
(4) 調(diào)用標(biāo)準(zhǔn)C庫(kù)函數(shù)sprinf(),將dup_str寫到原字符串中。由于原字符串的長(zhǎng)度(存在n中)被傳遞給sprintf()函數(shù),所以迫使輸出字符串的長(zhǎng)度和原字符串相同。因?yàn)閟printf()函數(shù)缺省使輸出字符串右對(duì)齊,因此輸出字符串的頭部將被加入空格,以使它和原字符串長(zhǎng)度相同,其效果實(shí)際上就是使原字符串右對(duì)齊。
(5)調(diào)用標(biāo)準(zhǔn)庫(kù)函數(shù)free(),釋放由strdup()函數(shù)分配給dup_str的動(dòng)態(tài)內(nèi)存。
請(qǐng)參見(jiàn):
6.5怎樣將字符串打印成指定長(zhǎng)度?
6.5 怎樣將字符串打印成指定長(zhǎng)度?
如果要按表格形式打印一組字符串,你就需要將字符串打印成指定長(zhǎng)度。利用printf()函數(shù)可以很方便地實(shí)現(xiàn)這一點(diǎn),請(qǐng)看下例:
# include <stdio. h>
char * data[25] = {
"REGION", "--Q1--", "--Q2--", "--Q3--", "--Q4--",
"North" , "10090. 50" , "12200. 10" , "26653.12" , "62634. 32" ,
"South", "21662.37", "95843.23", "23788.23", "48279.28",
"East", "23889.38", "23789.05", "89432.84", "29874.48",
"West", "85933.82", "74373.23", "78457.23", "28799.84" };
void main (void) ;
void main (void)
{
int x;
fox (x = 0, x<25; x+ + )
{
if ((x % 5) == 0&&(x !=0))
printf("\n");
printf (" %-10. 10s" , data[x]) ;
}
}
在上例中,字符串?dāng)?shù)組char *data[]中包含了某年4個(gè)地區(qū)的銷售數(shù)據(jù)。顯然,你會(huì)要求按表格形式打印這些數(shù)據(jù),而不是一個(gè)挨一個(gè)地毫無(wú)格式地打印這些數(shù)據(jù)。因此,上例中用下述語(yǔ)句來(lái)打印這些數(shù)據(jù):
printf("%-10.10s",data[x]);
參數(shù)"%-10.10s"指示printf()函數(shù)按10個(gè)字符的長(zhǎng)度打印一個(gè)字符串。在缺省情況下,printf()函數(shù)按右對(duì)齊格式打印字符串,但是,在第一個(gè)10的前面加上減號(hào)(-)后,prinft()函數(shù),就會(huì)使字符串左對(duì)齊。為此,printf()函數(shù)會(huì)在字符串的尾部加入空格,以使其長(zhǎng)度達(dá)到10個(gè)字符。上例的打印輸出非常整潔,類似于一張表格,如下所示:
REGION --Q1-- --Q2-- --Q3-- --Q4--
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -