C/C++ 字符串處理總結
string 和 char* 的互相轉換
通常情況下,用 string 操作會更加的方便,這里是std::string的相關函數。由 char* 轉 string 非常的方便,直接賦值或者用std::string的構造函數,詳見這里learncpp.com 。由 string 轉 char* 一般有兩種辦法:(1) 利用std::string::copy()函數;(2) 先用std::string::c_str()把string 轉為 const char*, 然后利用strcpy()函數拷貝到 char* 中。一個例子如下:
#include <iostream>include <string>
using namespace std;
int main() { string str = "Hello, world!"; char ps[20]; // ps[] 某種程度類似于 cons char strcpy(ps, str.c_str()); // str.c_str() 返回值 const char ps[str.length()] = '\0'; // 或者 *(ps + str.length()) = 0;
char *p = (char*)malloc(20); str.copy(p, str.length(), 0); // 可以指定區間,前閉后開 p[str.length()] = '\0'; // 字符'\0' 就是 0 cout << ps << endl << p << endl; free(p); char* h = "freedom"; string h2(h); // 或者 string h2 = h; cout << h2 << endl; return 0;
}</pre>
char* 和 int, float 等的格式化轉換
從字符串中提取指定類型數字或子串,這種情形也是非常的常見。大部分的情形都可以用sscanf() 和 sprintf() 這兩個函數來實現,如果要求復雜,那么就用正則庫或自己手寫自動機。一個例子如下:
#include <iostream>include <string>
include<stdio.h>
int main() { // 從字符串中提取數字 char* p = "192.168.1.1"; int a[4]; sscanf(p, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]); std::cout << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << "\n";
// 從字符串中提取數字,指定的字符串 char* p2 = "170 60 Alice"; int height, weight; char name[20]; sscanf(p2, "%d %d %s", &height, &weight, name); std::cout << name << " height: " << height << " weight: " << weight << "\n"; // 浮點型數字轉字符串,并四舍五入保留指定位數小數 double pi = 3.1415; char str[50]; sprintf(str, "%s %.3f", "pi is:", pi); std::cout << str << "\n"; // 輸出 3.142 return 0;
}</pre>
介紹一下 format 參數的用法,int sscanf ( const char * s, const char * format, ...);,其中參數 format 的用法和 scanf() 函數中用法是一樣的。和正則表達式有那么一點點的類似。
format可為一個或多個{%[*][width][{h|l|L}]type|''|'\t'|'\n'|非%符號}格式轉換符。集合中{a|b|c}表示格式符a、b、c任選其一。以中括號括起來的格式符可選。%與type為必選,所有格式符必須以%開頭。一些規則:
- 賦值抑制符*表明按照隨后的轉換符指示來讀取輸入,但將其丟棄不予賦值(跳過)。抑制符無需相應的指針可變參數,該轉換也不計入函數返回的成功賦值次數。%*[width][{h|l|L}]type表示滿足該條件的字符被過濾掉,不會向目標參數中賦值。
- width表示最大讀取寬度。當讀入字符數超過該值,或遇到不匹配的字符時,停止讀取。多數轉換丟棄起始的空白字符。這些被丟棄的字符及轉換結果添加的空結束符'\0'均不計入最大讀取寬度。
- {h|l|L}為類型修飾符。h 指示輸入的數字數值以 short int 或 unsigned short int類型存儲;hh 指示輸入以 signed char 或 unsigned char 類型存儲。l(小寫L) 指示輸入以 long int、unsigned long int 或 double 類型存儲,若與 %c 或 %s 結合則指示輸入以寬字符或寬字符串存儲;ll 等同 L。L指示輸入以long long類型存儲。
- type為類型轉換符,如 %s、%d 。 </ul>
- %[]:字符集合。[]表示指定的字符集合匹配非空的字符序列;^則表示過濾。該操作不會跳過空白字符(空格、制表或換行符),因此可用于目標字符串不以空白字符分隔時。[]內可有一到多個非^字符(含連字符-),且無順序要求。%[a-z]表示匹配a到z之間的任意字符,%[aB-]匹配a、B、-中的任一字符;
- %[^a]則匹配非a的任意字符,即獲取第一個a之前的(不為a的)所有字符。^可作用于多個條件,如^a-z=表示 ^a-z且^=(既非小寫字母亦非等號)。使用[]時接收輸入的參數必須是有足夠存儲空間的 char、signed char 或unsigned char數組。[] 也是轉換符,故 %[] 后無 s。
- n:至此已讀入值(未必賦值)的等價字符數,該數目必須以 int 類型存儲,并不是很常用。 </ul>
此外還有字符集合規則,有點兒像正則表達式:
舉例:
源字符串 | format | 匹配后 |
---|---|---|
hello | %s | hello |
hello, world | %s | hello, |
hello, world | %[a-z] | hello |
12345helloWORLD | %*[1-9]%[a-z] | hello |
IpAddr=10.46.44.40 | %*[^=]=%s | 10.46.44.40 |
email:wxy@zte.com.cn | %*[^:]:%s | wxy@zte.com.cn |