字符串(一):char 数组
字符串使用方法整理 系列:
字符串(一):char 數組
字符串(二):string
1. 聲明
如下是一個例子(=> 表示表達式等價):
char a[20] = "abcd";
char b[] = "abcd"; // => char b[5] = "abcd";
const char c[] = "abcd";
char *d = "abcd"; // => const char d[] = "abcd";
const char *e = "abcd"; // => const char e[] = "abcd";
char *f = a + 1; // 指針 f 指向 a[1]
const char *g = b; // 定指針 g 指向 b[0]
char *h = f; // 指針 h 與 f 指向同一地址
2. 字符和字符串
2.1 char 字符
char 是字符,也是 0~127 的無符號整數。通常能用一個 char 表示的被稱為 ASCII 編碼。
字符串是以 NULL 結尾的連續地址。日常生活中常用轉義字符 '' 表示。
字符和字符串特性的研究可參看:Link
2.2 char [] 是數組
這里談到數組,必然需要知道與指針的關系。
基本常識:數組名本身就是一個指針,指向數組起始元素。
編譯器在處理形如 a[i] 的表達式時,將這個表達式轉換成 *(a + i) 的形式,然后計算表達式的指向地址。(這也是 C/C++ 下標從 0 開始的原因,表示與頭地址的偏移量。)
表達式轉換如圖所示:
由此,可以解釋:
使用 scanf("%s", str) 語句,只有字符串不用加取地址符,因為 str 本身代表 str[] 的地址;
使用 sort(a + 1, a + n + 1) 語句,a + 1 和 a[1] 編譯后是相同的,同為 a[1] 的地址。
2.3 char * 與 char [] 的區別
char * 本質上是指針;char [] 本質上是數組。
特殊的:
char *a = "abcd"; // (1)
char a[20] = "abcd"; // (2)
在源代碼中出現的字符串(用 "" 包括的內容)都是字符串常量。(1)句是把指針指向字符串常量 "abcd" 的首字符;(2)句則把字符串常量復制到字符數組中。顯然前者不可修改,后者可修改。
詳細的區別可以參考這篇文章:Link
3. <cstring> 庫
建議配合使用快捷鍵
Control + F。
3.1 字符串操作 #include <cstring>
strcpy(p, p1) 復制字符串
strncpy(p, p1, n) 復制指定長度字符串
strcat(p, p1) 附加字符串
strncat(p, p1, n) 附加指定長度字符串
strlen(p) 取字符串長度
strcmp(p, p1) 比較字符串
strcasecmp 忽略大小寫比較字符串
strncmp(p, p1, n) 比較指定長度字符串
strchr(p, c) 在字符串中查找指定字符
strrchr(p, c) 在字符串中反向查找
strstr(p, p1) 查找字符串
strpbrk(p, p1) 以目標字符串的所有字符作為集合,在當前字符串查找該集合的任一元素
strspn(p, p1) 以目標字符串的所有字符作為集合,在當前字符串查找不屬于該集合的任一元素的偏移
strcspn(p, p1) 以目標字符串的所有字符作為集合,在當前字符串查找屬于該集合的任一元素的偏移
具有指定長度的字符串處理函數在已處理的字符串之后填補零結尾符
3.2 字符串到數值類型的轉換 #include <cstdlib>
strtod(p, ppend) 從字符串 p 中轉換 double 類型數值,并將后續的字符串指針存儲到 ppend 指向的 char* 類型存儲。
strtol(p, ppend, base) 從字符串 p 中轉換 long 類型整型數值,base 顯式設置轉換的整型進制,設置為 0 以根據特定格式判斷所用進制,0x, 0X 前綴以解釋為十六進制格式整型,0 前綴以解釋為八進制格式整型
atoi(p) 字符串轉換到 int 整型
atof(p) 字符串轉換到 double 符點數
atol(p) 字符串轉換到 long 整型
3.3 字符檢查 #include <cctype>
isalpha() 檢查是否為字母字符
isupper() 檢查是否為大寫字母字符
islower() 檢查是否為小寫字母字符
isdigit() 檢查是否為數字
isxdigit() 檢查是否為十六進制數字表示的有效字符
isspace() 檢查是否為空格類型字符
iscntrl() 檢查是否為控制字符
ispunct() 檢查是否為標點符號
isalnum() 檢查是否為字母和數字
isprint() 檢查是否是可打印字符
isgraph() 檢查是否是圖形字符,等效于 isalnum() | ispunct()
3.4 函數原型
原型:strcpy(char destination[], const char source[]);
功能:將字符串 source 拷貝到字符串 destination 中
例程:
#include <iostream.h>
#include <string.h>
void main(void)
{
char str1[10] = { "TsinghuaOK"};
char str2[10] = { "Computer"};
cout <<strcpy(str1,str2)<<endl;
}
運行結果是: Computer
第二個字符串將覆蓋掉第一個字符串的所有內容!
注意:在定義數組時,字符數組1的字符串長度必須大于或等于字符串2的字符串長度。不能用賦值語句將一個字符串常量或字符數組直接賦給一個字符數組。所有字符串處理函數都包含在頭文件string.h中。
原型:strncpy(char destination[], const char source[], int numchars);
功能:將字符串source中前numchars個字符拷貝到字符串destination中
例程:
#include <iostream.h>
#include <string.h>
void main(void)
{
char str1[10] = { "Tsinghua "};
char str2[10] = { "Computer"};
cout <<strncpy(str1,str2,3)<<endl;
}
運行結果:Comnghua
注意:字符串source中前numchars個字符將覆蓋掉字符串destination中前numchars個字符!
原型:strcat(char target[], const char source[]);
功能:將字符串source接到字符串target的后面
例程:
#include <iostream.h>
#include <string.h>
void main(void)
{
char str1[] = { "Tsinghua "};
char str2[] = { "Computer"};
cout <<strcpy(str1,str2)<<endl;
}
運行結果:Tsinghua Computer
注意:在定義字符數組1的長度時應該考慮字符數組2的長度,因為連接后新字符串的長度為兩個字符串長度之和。進行字符串連接后,字符串1的結尾符將自動被去掉,在結尾串末尾保留新字符串后面一個結尾符。
原型:strncat(char target[], const char source[], int numchars);
功能:將字符串source的前numchars個字符接到字符串target的后面
例程:
#include <iostream.h>
#include <string.h>
void main(void)
{
char str1[] = { "Tsinghua "};
char str2[] = { "Computer"};
cout <<strncat(str1,str2,3)<<endl;
}
運行結果:Tsinghua Com
原型:int strcmp(const char firststring[], const char secondstring);
功能:比較兩個字符串firststring和secondstring
例程:
#include <iostream.h>
#include <string.h>
void main(void)
{
char buf1[] = "aaa";
char buf2[] = "bbb";
char buf3[] = "ccc";
int ptr;
ptr = strcmp(buf2,buf1);
if(ptr > 0)
cout <<"Buffer 2 is greater than buffer 1"<<endl;
else
cout <<"Buffer 2 is less than buffer 1"<<endl;
ptr = strcmp(buf2,buf3);
if(ptr > 0)
cout <<"Buffer 2 is greater than buffer 3"<<endl;
else
cout <<"Buffer 2 is less than buffer 3"<<endl;
}
運行結果是:
Buffer 2 is less than buffer 1
Buffer 2 is greater than buffer 3
原型:strlen(const char string[]);
功能:統計字符串string中字符的個數
例程:
#include <iostream.h>
#include <string.h>
void main(void)
{
char str[100];
cout <<"請輸入一個字符串:";
cin >>str;
cout <<"The length of the string is :"<<strlen(str)<<"個"<<endl;
}
運行結果The length of the string is x (x為你輸入的字符總數字)
注意:strlen函數的功能是計算字符串的實際長度,不包括''在內。另外,strlen函數也可以直接測試字符串常量的長度,如:strlen("Welcome")。
void *memset(void *dest, int c, size_t count);
將dest前面count個字符置為字符c. 返回dest的值.
void *memmove(void *dest, const void *src, size_t count);
從src復制count字節的字符到dest. 如果src和dest出現重疊, 函數會自動處理. 返回dest的值.
void *memcpy(void *dest, const void *src, size_t count);
從src復制count字節的字符到dest. 與memmove功能一樣, 只是不能處理src和dest出現重疊. 返回dest的值.
void *memchr(const void *buf, int c, size_t count);
在buf前面count字節中查找首次出現字符c的位置. 找到了字符c或者已經搜尋了count個字節, 查找即停止. 操作成功則返回buf中首次出現c的位置指針, 否則返回NULL.
void *_memccpy(void *dest, const void *src, int c, size_t count);
從src復制0個或多個字節的字符到dest. 當字符c被復制或者count個字符被復制時, 復制停止.
如果字符c被復制, 函數返回這個字符后面緊挨一個字符位置的指針. 否則返回NULL.
int memcmp(const void *buf1, const void *buf2, size_t count);
比較buf1和buf2前面count個字節大小.
返回值< 0, 表示buf1小于buf2;
返回值為0, 表示buf1等于buf2;
返回值> 0, 表示buf1大于buf2.
int memicmp(const void *buf1, const void *buf2, size_t count);
比較buf1和buf2前面count個字節. 與memcmp不同的是, 它不區分大小寫.
返回值同上.
char *strrev(char *string);
將字符串string中的字符順序顛倒過來. NULL結束符位置不變. 返回調整后的字符串的指針.
strrev 函數不是 C++ 標準函數,在 gcc 編譯器中未定義。一份替代辦法(有 BUG):
char* strrev(char* s) { /* h指向s的頭部 */ char* h = s; char* t = s; char ch; /* t指向s的尾部 */ while (*t++); t--;/* 與t++抵消 */ t--;/* 回跳過結束符'' */ /* 當h和t未重合時,交換它們所指向的字符 */ while (h < t) { ch = *h; *h++ = *t; /* h向尾部移動 */ *t-- = ch; /* t向頭部移動 */ } return (s); }代碼源自:Link
char *_strupr(char *string);
將string中所有小寫字母替換成相應的大寫字母, 其它字符保持不變. 返回調整后的字符串的指針.
char *_strlwr(char *string);
將string中所有大寫字母替換成相應的小寫字母, 其它字符保持不變. 返回調整后的字符串的指針.
char *strchr(const char *string, int c);
查找字 串string中首次出現的位置, NULL結束符也包含在查找中. 返回一個指針, 指向字符c在字符串string中首次出現的位置, 如果沒有找到, 則返回NULL.
char *strrchr(const char *string, int c);
查找字符c在字符串string中最后一次出現的位置, 也就是對string進行反序搜索, 包含NULL結束符.
返回一個指針, 指向字符c在字符串string中最后一次出現的位置, 如果沒有找到, 則返回NULL.
char *strstr(const char *string, const char *strSearch);
在字符串string中查找strSearch子串. 返回子串strSearch在string中首次出現位置的指針. 如果沒有找到子串strSearch, 則返回NULL. 如果子串strSearch為空串, 函數返回string值.
char *strdup(const char *strSource);
函數運行中會自己調用malloc函數為復制strSource字符串分配存儲空間, 然后再將strSource復制到分配到的空間中. 注意要及時釋放這個分配的空間.
返回一個指針, 指向為復制字符串分配的空間; 如果分配空間失敗, 則返回NULL值.
char *strcat(char *strDestination, const char *strSource);
將源串strSource添加到目標串strDestination后面, 并在得到的新串后面加上NULL結束符. 源串strSource的字符會覆蓋目標串strDestination后面的結束符NULL. 在字符串的復制或添加過程中沒有溢出檢查, 所以要保證目標串空間足夠大. 不能處理源串與目標串重疊的情況. 函數返回strDestination值.
char *strncat(char *strDestination, const char *strSource, size_t count);
將源串strSource開始的count個字符添加到目標串strDest后. 源串strSource的字符會覆蓋目標串strDestination后面的結束符NULL. 如果count大于源串長度, 則會用源串的長度值替換count值. 得到的新串后面會自動加上NULL結束符. 與strcat函數一樣, 本函數不能處理源串與目標串重疊的情況. 函數返回strDestination值.
char *strcpy(char *strDestination, const char *strSource);
復制源串strSource到目標串strDestination所指定的位置, 包含NULL結束符. 不能處理源串與目標串重疊的情況.函數返回strDestination值.
char *strncpy(char *strDestination, const char *strSource, size_t count);
將源串strSource開始的count個字符復制到目標串strDestination所指定的位置. 如果count值小于或等于strSource串的長度, 不會自動添加NULL結束符目標串中, 而count大于strSource串的長度時, 則將strSource用NULL結束符填充補齊count個字符, 復制到目標串中. 不能處理源串與目標串重疊的情況.函數返回strDestination值.
char *strset(char *string, int c);
將string串的所有字符設置為字符c, 遇到NULL結束符停止. 函數返回內容調整后的string指針.
char *strnset(char *string, int c, size_t count);
將string串開始count個字符設置為字符c, 如果count值大于string串的長度, 將用string的長度替換count值. 函數返回內容調整后的string指針.
size_t strspn(const char *string, const char *strCharSet);
查找任何一個不包含在strCharSet串中的字符 (字符串結束符NULL除外) 在string串中首次出現的位置序號. 返回一個整數值, 指定在string中全部由characters中的字符組成的子串的長度. 如果string以一個不包含在strCharSet中的字符開頭, 函數將返回0值.
size_t strcspn(const char *string, const char *strCharSet);
查找strCharSet串中任何一個字符在string串中首次出現的位置序號, 包含字符串結束符NULL.
返回一個整數值, 指定在string中全部由非characters中的字符組成的子串的長度. 如果string以一個包含在strCharSet中的字符開頭, 函數將返回0值.
char *strspnp(const char *string, const char *strCharSet);
查找任何一個不包含在strCharSet串中的字符 (字符串結束符NULL除外) 在string串中首次出現的位置指針. 返回一個指針, 指向非strCharSet中的字符在string中首次出現的位置.
char *strpbrk(const char *string, const char *strCharSet);
查找strCharSet串中任何一個字符在string串中首次出現的位置, 不包含字符串結束符NULL.
返回一個指針, 指向strCharSet中任一字符在string中首次出現的位置. 如果兩個字符串參數不含相同字符, 則返回NULL值.
int strcmp(const char *string1, const char *string2);
比較字符串string1和string2大小.
返回值< 0, 表示string1小于string2;
返回值為0, 表示string1等于string2;
返回值> 0, 表示string1大于string2.
int stricmp(const char *string1, const char *string2);
比較字符串string1和string2大小,和strcmp不同, 比較的是它們的小寫字母版本.返回值與strcmp相同.
int strcmpi(const char *string1, const char *string2);
等價于stricmp函數, 只是提供一個向后兼容的版本.
int strncmp(const char *string1, const char *string2, size_t count);
比較字符串string1和string2大小,只比較前面count個字符. 比較過程中, 任何一個字符串的長度小于count, 則count將被較短的字符串的長度取代. 此時如果兩串前面的字符都相等, 則較短的串要小.
返回值< 0, 表示string1的子串小于string2的子串;
返回值為0, 表示string1的子串等于string2的子串;
返回值> 0, 表示string1的子串大于string2的子串.
int strnicmp(const char *string1, const char *string2, size_t count);
比較字符串string1和string2大小,只比較前面count個字符. 與strncmp不同的是, 比較的是它們的小寫字母版本. 返回值與strncmp相同.
char *strtok(char *strToken, const char *strDelimit);
在strToken 串中查找下一個標記, strDelimit字符集則指定了在當前查找調用中可能遇到的分界符. 返回一個指針, 指向在strToken中找到的下一個標記. 如果找不到標記, 就返回NULL值. 每次調用都會修改strToken內容, 用NULL字符替換遇到的每個分界符.
以下轉自 Link
sscanf 與 scanf 類似,都是用于輸入的,只是后者以屏幕 (stdin) 為輸入源,前者以固定字符串為輸入源。
函數原型:
int scanf(const char *format [,argument]..、);
其中的 format 可以是一個或多個:
{%[*][width][{h|l|I64|L}]type|''|' '|'
'| 非 % 符號},
注:
1、 * 亦可用于格式中, (即 %*d 和 %*s) 加了星號 (*) 表示跳過此數據不讀入。
(也就是不把此數據讀入參數中)
2、{a|b|c} 表示 a,b,c 中選一,[d], 表示可以有 d 也可以沒有 d。
3、width: 寬度,一般可以忽略,用法如:
const char sourceStr[] ="hello, world";
char buf[10] = {0};
sscanf(sourceStr,"%5s", buf); //%5s,只取 5 個字符
cout << buf<< endl;
結果為: hello
4、{h|I|I64|L}: 參數的 size, 通常 h 表示單字節 size,I 表示 2 字節 size,
L 表示 4 字節 size (double 例外), l64 表示 8 字節 size。
5、type : 這就很多了,就是 %s,%d 之類。
6、特別的:%*[width] [{h|l|I64|L}]type 表示滿足該條件的被過濾掉,不會向目標參數中寫入值。如:
const char sourceStr[] ="hello, world";
char buf[10] = {0};
sscanf(sourceStr,"%*s%s", buf);
//%*s 表示第一個匹配到的 %s 被過濾掉,即 hello 被過濾了
cout << buf<< endl;
結果為: world
7、支持集合操作:
%[a-z] 表示匹配 a 到 z 中任意字符,貪婪性 (盡可能多的匹配)
%[aB'] 匹配 a、B、'中一員,貪婪性
%[^a] 匹配非 a 的任意字符,貪婪性
和正則表達式很相似,而且仍然支持過濾,即可以有 %*[a-z]。
例子:
1、常見用法。
char buf[512] = {0};
sscanf("123456", "%s", buf);
printf("%s
", buf);
結果為:123456
2、取指定長度的字符串。如在下例中,取最大長度為 4 字節的字符串。
sscanf("123456", "%4s", buf);
printf("%s
", buf);
結果為:1234
3、取到指定字符為止的字符串。如在下例中,取遇到空格為止字符串。
sscanf("123456 abcdedf", "%[^]", buf);
printf("%s
", buf);
結果為:123456
4、取僅包含指定字符集的字符串。如在下例中,取僅包含 1 到 9 和小寫字母的字符串。
sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);
printf("%s
", buf);
結果為:123456abcdedf
5、取到指定字符集為止的字符串。如在下例中,取遇到大寫字母為止的字符串。
sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);
printf("%s
", buf);
結果為:123456abcdedf
6、給定一個字符串 iios/12DDWDFF@122,獲取 / 和 @ 之間的字符串,先將 "iios/" 過濾掉,再將非'@'的一串內容送到 buf 中
sscanf("iios/12DDWDFF@122","%*[^/]/%[^@]", buf);
printf("%s
", buf);
結果為:12DDWDFF
7、給定一個字符串 hello, world,僅保留 world。(注意:, 之后有一空格)
sscanf(`hello, world`, "%*s%s", buf);
printf("%s
", buf);
結果為:world
%*s 表示第一個匹配到的 %s 被過濾掉,即 hello 被過濾了,如果沒有空格則結果為 NULL。
8、分隔字符串 2006:03:18
int a, b, c;
sscanf("2006:03:18", "%d:%d:%d", a, b, c);
9、分隔字符串 2006:03:18 - 2006:04:18
char sztime1[16] = "", sztime2[16] = "";
sscanf("2006:03:18 - 2006:04:18", "%s - %s", sztime1, sztime2);
10、分隔字符串 2006:03:18-2006:04:18
char sztime1[16] = "", sztime2[16] = "";
sscanf("2006:03:18-2006:04:18", "%[0-9,:] - %[0-9,:]", sztime1, sztime2);
僅僅是取消了 - 兩邊的空格,卻打破了 %s 對字符串的界定 format-type 中有 %[] 這樣的 type field。如果讀取的字符串,不是以空格來分隔的話,就可以使用 %[]。%[] 類似于一個正則表達式。 [a-z] 表示讀取 a-z 的所有字符,[^a-z] 表示讀取除 a-z 以外的所有字符。
Post author 作者: Grey
Copyright Notice 版權說明: Except where otherwise noted, all content of this blog is licensed under a CC BY-NC-SA 4.0 International license. 除非另有說明,本博客上的所有文章均受 知識共享署名 - 非商業性使用 - 相同方式共享 4.0 國際許可協議 保護。
總結
以上是生活随笔為你收集整理的字符串(一):char 数组的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何理性看待广岛原爆问题
- 下一篇: 南川方竹论坛售房信息(南川方竹论坛)