字符串

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.stringchar*:


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.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值