27. 字串转数字
strtol
头文件:#include <stdlib.h>
原型:long int strtol(const char *s, char **endptr, int base);
功能:按base进制,返回字符串s表示的整数
参数:
s为字符串地址
endptr暂为NULL
base为s中整数的进制格式
示例,从"0xef"中取数字
sscanf
头文件:#include <stdio.h>
函数原型:int sscanf(const char *s, const char *format, ...);
功能:输入格式转换
参数:
s为字符串地址
format为转换格式
示例,从"机车12 E6"取数字E6
%*表示跳过不取
26. 数字转字串
sstream
标准格式
std::fixed——关闭科学计数法——#include <iostream>
std::setprecision(9)——小数点后留9位——#include <iomanip>
结果
sprintf
头文件:#include <stdio.h>
原型:int sprintf(char *s, const char *format, ...);
功能:输出格式转换
参数:
s为目标缓冲区地址
format为转换格式
示例,将char *name和double score转字符串
25. std::string操作函数
std::string s;
s.resize(n, 0);
等价于
std::string s(n, 0);
等价于
s.assign(n, 0);
可以采用上述三种方式,构造字符串缓冲区。
24. std::string构造函数
std::string s(size_t n, char c):创建s,s.length()=n,内容为n个字符c
std::string s(char *ch, size_t n):创建s,s.length()=n,内容为字符串ch的前n个字符
23. 空格和水平制表符
空白字符:空格和水平制表符,ASCII码:空格-32; \t-9
str = "空格 + \t",下面的结果是9 9, str = "\t + 空格",结果是9 32。
所以有公式:空格 + \t = \t\t; \t + 空格 = \t + 空格
总结下来就是“先水平制表符后空格”
std::string str = " ";
for(int i = 0; i < str.length(); i++)
printf("%d\n", str[i]);
22. strcpy自动添加'\0'
strcpy(dest, src);
src :源字符串,以NULL结尾的字符串
dest:目的字符串
功能:把src中连带NULL结束符所有字符串拷入dest
示例
std::string s1 = "abc";
std::string s2(10, '1');
strcpy(&s2[0], s1.c_str());
printf("str.size() = %d\n", s1.size());
for(int i = 0; i != 10; ++i)
printf("%c ", s2[i]);
printf("\n");
char *c = "abc";
char ch[10] = {0};
memset(ch, '1', 10);
strcpy(ch, c);
for(int i = 0; i != 10; ++i)
printf("%c ", ch[i]);
printf("\n");
结果
21. 特区字符处理
问:0xd5, 0xc5, 0xb2, 0xfd, 0xca, 0xa2表示的是一个字符串,请打印出这个字符串的值?
答:
char ch[] = {0xd5, 0xc5, 0xb2, 0xfd, 0xca, 0xa2,0x00};
printf("%s\n", ch);
结果:张昌盛
20.去除空格
20.2 去除收尾空白
bool TrimBothSideSpace(std::string &s)
{
s.erase(0, s.find_first_not_of(" "));
if(s.find_last_not_of(" ") + 1 != s.length())
s.erase(s.find_last_not_of(" ") + 1);
return true;
}
" "为先制表符后空格
20.1 去除所有空格
C++ string去除所有空格标准手法:
1.auto pos = std::remove(str.begin(), str.end(), ' ');str.erase(pos, str.end());
2.std::copy_if(str1.begin(), str1.end(), std::back_inserter(str2), std::not1(std::ptr_fun(isspace)));
remove(beg, end, value):覆盖区间[beg, end)内所有与value相等的elem.
#include <algorithm>
/*方法一*/
std::string str("12:43 14:29 abcs dfd ");
auto pos = std::remove(str.begin(), str.end(), ' ');
str.erase(pos, str.end());
/*方法二*/
std::string str1("12:43 14:29 abcs dfd");
std::string str2;
std::copy_if(str1.begin(), str1.end(), std::back_inserter(str2), std::not1(std::ptr_fun(isspace)));
1.字符串查找函数:
1.1 正向查找:size_t find(std::string substr, int pos = 0)
从字符串pos(首字符位置为0)开始查找substr第一次出现的位置,并返回索引(首字符位置为0)。
int pos = 8;
size_t index = obj.find("\\u00", pos);
pos缺省值0:
std::string str = "abABfbcdABc";
size_t index = find("AB"); //index = 2
查找字符串中所有的子串:
size_t index = 0;
while((index = obj.find("\\u00", index)) != std::string::npos){ //npos标志查找的结束。std::string::npos 无符号长整形最大值即ULONG_MAX,64位全1。
.............
index++;
}
1.2 反向查找:size_t rfind(std::string substr, int pos)
从pos开始,反向查找substr,返回正向索引。即寻找字符串中从0到pos最后一次匹配substr的正向索引。pos、索引从0计数。没有返回std::string::npos。
std::string str("\"name\":\"jijifujijixx\\u00E6\\u009A\\u0097caonima\\u00E6\\u0088\\u009878d\"");
size_t n = str.find("\\u00", 0);
size_t = str.rfind("\"", n);
std::cout<<n<<std::endl; //输出:7
特别注意:
std::string str("hello world");
size_t n = str.rfind("world", 6);
std::cout<<n<<std::endl; //输出:6
1.3 正向查找第一个匹配字符:size_t find_first_of(std::string substr, int pos = 0)
从pos开始,查找第一个位于substr字符集合中的字符位置。
std::string str("hello world");
std::string substr("eod");
size_t n = str.find_first_of(substr, 0);
std::cout<<str.substr(n, str.length()-n)<<std::endl; //输出:ello world
1.4 反向查找第一个匹配字符:
size_t find_last_of(std::string substr, int pos = std::string::npos)
size_t find_last_of(const char *s, int pos = std::string::npos)
从pos开始反向查找第一个位于substr中的字符,返回位置,默认从最后开始搜索。
std::string str("hello world");
std::string substr("eo");
size_t n = str.find_last_of(substr, str.length()-1);
std::cout<<str.substr(n, str.length()-n)<<std::endl; //输出:orld
例2
char ch[300] = {0};
//第一参数NULL即取出当前进程exe文件全路径,如:E:\projects\attemp3\Debug\attemp3.exe
if(!GetModuleFileName(NULL, ch, 300))
{
std::cout<<"GetModuleFileName error : "<<GetLastError()<<std::endl;
return -1;
}
std::string str = ch;
//find_last_of省略第二参数默认从最后开始搜索。
size_t index = str.find_last_of("\\");
std::string substr = str.substr(0, index+1);
std::cout<<substr<<std::endl; //E:\projects\attemp3\Debug\
2014.09.10 find遇到巨大埋伏。
find函数返回值为size_t,具体类型不明,就目前所知非无符号整形即无符号长整形。
std::string::npos 无符号长整形最大值即ULONG_MAX,64位全1。
故下列凡涉及find方法,index的类型选取格外留心。
若index为int,find返回无符号长整形ULONG_MAX赋值给index,index = -1(参考linux编程手册33)。则index == std::string::npos成立(参考linux编 | 程手册34)。跳出循环实属巧合。
若index为unsigned,unsigned即为unsigned int 4字节32位。find返回无符号长整形ULONG_MAX赋值给index,index = UINT_MAX,32位全1。则 index == std::string::npos不成立(index先扩展为无符号长整形,由于index无符号则高位补零,值不变仍为UINT_MAX)。陷入死循环。遇到的就是这 个问题。
无畏级驱逐舰:接收find返回值的index类型size_t。
2.生成子串函数:std::string substr(int pos = 0, int len = std::string::npos);
返回字符串中从pos开始长度为len的子串,就是个副本,pos还是从0计数。
没有len参数,则从pos开始一直取到字符串结尾。
int pos = 6;
int len = 2;
std::string substr = obj.substr(pos, len);
pos默认值0,len默认值std::string::npos:
std::string str = "0123456789abc";
std::string substr;
substr = str.substr();
std::cout<<substr<<std::endl; //substr = "0123456789abc"
substr = str.substr(5);
std::cout<<substr<<std::endl; //substr = "56789abc"
3.字符串替换函数:void replace(int pos, int len, std::string str);
把字符串中从pos开始长为len的部分替换成str。
obj.replace(5, 3, "宇宙总司令sdjsaifheuiahlkasjldfdfjsladf"); //用很长的字符串换掉obj中长为3的部分串,没问题。
3.1全字符串替换函数:
void replace_all(std::string& obj, const std::string substr, const std::string newstr){
size_t index = 0;
int len_sub = substr.length();
int len_new = newstr.length();
while((index = obj.find(substr, index)) != std::string::npos){
obj.replace(index, len_sub, newstr);
index += len_new;
}
}
整体替换,
一次替换,不递归。一次替换后出现的再匹配不处理。
std::string s("1234e28298");
replace_all(s, "2", "222");
std::cout<<s<<std::endl; //输出122234e222822298
3.2子串计数函数:
int count(std::string str, std::string substr){
int count = 0;
size_t index = 0;
int len = substr.length();
while((index = str.find(substr, index)) != std::string::npos){
count++;
index += len;
}
return count;
}
6.string转char*:
6.1 c_str()函数:const char* c_str()
const char *ch = str.c_str();
注意: char *c = str.c_str() 是错的,const指针赋值给普通指针的问题。
6.2 copy()函数:str.copy(char *ch, int len, int pos)
从std::string中pos位置开始复制len个字符到char*中,pos从0计数。
std::string str("nilaomei");
char ch[10] = {0};
str.copy(ch, 6, 2);
std::cout<<ch<<std::endl; //输出:laomei
7.字符串内容长度函数:int length();
std::string str("asd dfea");
int len = str.length(); //len = 7 相当于char* 的strlen
8.
char ch[] = "12345";
int len = strlen(ch); //len = 6
int size = sizeof(ch); //size = 7 除了五个数字字符外,还有一个'\0'
9.字符串输出函数:printf
9.1 将数字按十六进制输出:
int main(void)
{
int i = 47; //10进制数
printf("%x\n", i); //方法1:输出结果 2f
printf("%X\n", i); //方法2:输出结果 2F
printf("%#x\n", i); //方法3:输出结果 0x2f
printf("%#X\n", i); //方法4:输出结果 0X2F (推荐使用该格式)
}
9.2 字符串十六进制输出标准格式:
for(int i = 0; i != strlen(ch); ++i)
printf("0x%02x\n", static_cast<unsigned char>(ch[i]));
例:
char c = 0XE8;
printf("%X\n",c); //输出FFFFFFE8
printf("%#x\n",c); //输出0xfffffffe8
这是因为%X输出long int,c经过了char到long的隐式类型转化,有符号数转更宽类型是扩展符号位所以有三个字节的1被填进来,就是FFFFFF前缀。
9.4宽字符串十六进制输出标准格式:
for(int i = 0; i != wcslen(wch); ++i)
printf("%04x\n", static_cast<unsigned wchar_t>(wch[i]));
宽字符wchar_t,编码多Unicode,两字节一字符
9.3 输出指针地址:%p
9.4 浮点数精度:%.nf
例如,精确到小数点后两位,同时输出百分号
double dNetworkUsageRate = 0.12576;
printf("%.2f%%\n", dNetworkUsageRate + 0.005);
9.5 定长输出、左对齐:%-ns
printf("%-20s%-15s%-15s%-30s\n", "LocalIp", "LocalPort", "Pid", "Process Name");
10.查看错误信息:
#include <errno.h> //errno
#include <string.h> //strerror()
int main(){
int fd =socket(AF_INET,SOCK_STREAM,0);
if(fd == -1){
std::cout<<"create socket fail : "<<strerror(errno)<<std::endl;
return -1;
}
return 0;
}
11.string比较可以直接==:
If(str == “child”) std::cout<<”child”<<std::endl;
12.std::string str(char *buf); 申请的是栈空间。没有在堆上分配空间,故不需要释放空间。
13.warning :deprecated converion from string constant to char*
char * s = “rongxiaojun”;
warning :deprecated converion from string constant to char*
为什么呢?原来char *背后的含义是:给我个字符串,我要修改它。
而理论上,我们传给函数的字面常量是没法被修改的。
所以说,比较和理的办法是把参数类型修改为const char *。
改为:const char * s = “rongxiaojun”;
14.string s = “rong”; s=“1”+s+“2”; 但是不可以 s = s+4;
15.字符串构造函数:
char* buf = "rongxiaojun";
std::string s(buf,4);
std::cout<<s<<std::endl;
输出:rong
17.C/C++字符串转化为整数:atoi 头函数#include<stdlib.h>
18.字符数组初始化:
18.1 char ch[] = {'a', 'c'}; 数组大小仅仅是2
char ch[] = {'a', 'c'};
sizeof(ch) = 2
strlen(ch) = 3 //已失效
//这种初始化方式不会在数组最后添加元素'\0'来标志结束,strlen已经失效了。
18.2 char ch[] = "ac"; 数组大小为3,自动在字符数组最后扩展一个元素,赋值'\0',表终结。
char ch[] = "ac";
sizeof(ch) = 3
strlen(ch) = 2
19.wchar_t宽字符:
19.1 宽字符概要:
宽字符的世界里没有汉字、字母的区别,一个汉字一个字母都视为一个字符,一个字符都占4字节。
19.2
wchar_t ch = L'九';
wchar_t ch2 = L'a';
std::cout<<"wchar_t size = "<<sizeof(wchar_t)<<std::endl; //输出4
std::cout<<"chinese character size = "<<sizeof(ch)<<std::endl; //输出4
std::cout<<"english character size = "<<sizeof(ch2)<<std::endl; //输出4
setlocale(LC_ALL,"zh_CN.UTF-8");
printf("%C %C\n", ch, ch2); //输出 九 a
19.3 宽字符串字符个数、宽字符串长度函数:wcslen()
wchar_t ch[] = L"黄粱一梦";
wchar_t ch2[] = L"abcd";
std::cout<<wcslen(ch)<<std::endl; //输出4
std::cout<<wcslen(ch2)<<std::endl; //输出4
setlocale(LC_ALL,"zh_CN.UTF-8");
printf("%S\n%S\n", ch, ch2); //输出 黄粱一梦 abcd
19.4 普通字符串前加L:该字符串作宽字符处理、作宽字符存储、给宽字符变量赋值。
19.5宽字符输出:
setlocale(LC_ALL,""); //不加这句输不出来,第二个参数可以是“zh_CN.UTF-8”
printf("%C") //输出宽字符用%C
printf("%S") //输出宽字符串用%S (普通字符串用%S,输出为空)
下面是根据上头的几个函数写的转码程序,可以把"\\u00E8\\u008D\\u0089\\u00E6\\u00B3\\u00A5\\u00E9\\u00A9\\u00AC" 转化成 "草泥马"
char ch[] = {0xE8, 0x8D, 0x89};
std::cout<<ch<<std::endl; //输出“草” E8 8D 89是汉字“草”的UTF8编码
void UTF8(std::string& obj){
int count = 0;
size_t index = 0;
while((index = obj.find("\\u00", index)) != std::string::npos){
count++;
index++;
}
char ch[count+1];
index = 0;
std::string substr;
for(int i = 0; i < count; i++){
index = obj.find("\\u00", index);
index += 4;
substr = obj.substr(index, 2);
ch[i] = strtol(substr.c_str(), NULL, 16);
}
ch[count] = '\0';
obj = ch;
}
void decode(std::string& obj){
size_t beg = 0;
std::string substr;
while((beg = obj.find("\\u00", 0)) != std::string::npos){
substr = obj.substr(beg, 18);
UTF8(substr);
obj.replace(beg, 18, substr);
}
}
在std::string中查找指定字符:int find_first_of(char c, int i),从i开始搜索c第一次出现的索引值,实际位置减1。
在std::string中取子串:std::string substr(int i, int len),返回从i开始长度len的子串。
std::string s("123:tem:53.2");
size_t i = s.find_first_of(‘:’,0);
std::string res = s.substr(0,i);
此时res为“123”。
2.数字转化为字符串标准流程:
float f = 13.4;
char temp[10] = {0};
sprintf(temp,"%f",f);
std::string s(temp);
此时s为"13.4"。
注意:
a.c_str()函数完整形式为 const char* c_str(),故s.c_str()返回静态字符指针
b.静态指针不能给普通指针赋值
c.sprintf完整形式:int sprintf(char *dest," ",.....),第一个参数要求为普通字符指针
结论:
不可以走捷径:
std::string s;
sprintf(s.c_str(),"%f",f);
3.生成特定格式字符串:
char *temp[10] = {0};
sprintf(temp,"%04d-%02d-%02d",year,month,day);
std::string s(temp);
此时s为XXXX-XX-XX格式的日期字符串。
4.