当前位置: 首页 > 工具软件 > Restbed > 使用案例 >

使用restbed库的创建基于rest风格的web后端之C++(1)之文件、字符串、容器相关操作

公孙成仁
2023-12-01

1 文件操作

背景:此次主要使用的是将请求和响应的数据资源保存到文件中不是数据库,会涉及到很多C++的文件操作

1.1 文件操作之以每行写入字符串到文件中

ofstream outfile;
outfile.open("./file/data.txt",ios::app);
outfile<<str<<endl;
outfile.flush();
outfile.close();

2 字符串操作

背景:前台的请求参数是字符串的形式,从文件中也是读取字符串响应到前台,所以会涉及到很多字符串的处理操作。

2.1 字符串的替换操作

new_value替换str中的所有old_value

string& replace_all_distinct(string& str,const string& old_value,const string&  new_value)     
{     
    for(string::size_type   pos(0);   pos!=string::npos;   pos+=new_value.length()){ 
        if((pos=str.find(old_value,pos))!=string::npos )     
            str.replace(pos,old_value.length(),new_value);     
        else
            break;     
    }
    return str;   
}

2.2 map与json字符串互转

2.2.1 map转为json字符串

{"id":first,"item":second}
string map2jsonstr(const map<string,string>& map_info)
{
	Json::Value jObject;
	for (map<string, string>::const_iterator iter = map_info.begin( ); iter != map_info.end( ); ++iter)
	{
		jObject[iter->first] = iter->second;
	}
	return jObject.toStyledString();
}

2.2.2 map转为子json字符串数组的形式

#include <iostream>
#include <map>
#include <jsoncpp/json/json.h>

using namespace std;

string map2jsonstr(const map<string,string>& map_info)
{
    Json::Value root;
	Json::Value jObject;
	for (map<string, string>::const_iterator iter = map_info.begin( ); iter != map_info.end( ); ++iter)
	{
        jObject["id"] = iter->first;
        jObject["item"] = iter->second;
		// jObject[iter->first] = iter->second;
        root.append(jObject);
	}
	return root.toStyledString();
}

int main()
{
    map<string, string> test;
    test.emplace("1","make a note");
    test.emplace("2","make a note");
    test.emplace("3","eat an apple");

    string testline = map2jsonstr(test);
    cout<<testline<<endl;

    return 0;
}
注意编译的时候要添加-l jsoncpp 
这种类型的json字符串:
[
	{
	   "id":1,
		"item":"make a note"
	},
	{
		"id":2,
		"item":"make a note"
	}
]

2.2.3 json字符串转为map

string itoa_self(int i)
{
	stringstream ss;
	ss << i;
	return ss.str();
}
 
map<string,string> jsonstr2map(const string& json)
{
	Json::Reader reader;
	Json::Value value;
	map<string, string> maps;
 
	if (json.length() > 0) 
	{
		if (reader.parse(json, value)) 
		{
			Json::Value::Members members = value.getMemberNames();
			for (Json::Value::Members::iterator it = members.begin(); it != members.end(); it++) 
			{  
				Json::ValueType vt = value[*it].type();
				switch (vt)
				{
				case Json::stringValue:
					{
						maps.insert(pair<string, string>(*it, value[*it].asString()));
						break;
					}
				case Json::intValue:
					{
						int intTmp = value[*it].asInt();
						maps.insert(pair<string, string>(*it, itoa_self(intTmp)));
						break;
					}
				case Json::arrayValue:
					{
						std::string strid;
						for (unsigned int i = 0; i < value[*it].size(); i++)
						{
							strid +=value[*it][i].asString();
							strid +=",";
						}
						if(!strid.empty())
						{
							strid = strid.substr(0,strid.size()-1);
						}
						maps.insert(pair<string, string>(*it, strid));
						break;
					}
				default:
					{
						break;
					}
				}//end switch
			}//end for
		}//end if
	}
 
	return maps;
}

int main()
{
    string json = "{\"id\":\"11\",\"item\":\"今天8点有个会议\"}";
    map<string, string> myMap = jsonstr2map(json);
    //判断当前 myMap 容器是否为空
    if (!myMap.empty()) {
        //借助 myMap 容器迭代器,将该容器的键值对逐个输出
        for (auto i = myMap.begin(); i != myMap.end(); ++i) {
            cout << i->first << " " << i->second << endl;
        }
    }
    else
    {
        cout<<"map is null"<<endl;
    }
    return 0;
}

2.3 关于char* 与 string转换,const、unsigned

2.3.1 char*与string的本质区别

string是一个容器,c++在中封装了一个string类,功能极其强大
char*则是一个指针,指向一个数组的首地址

2.3.2 char*转string类型

char*向string转换支持隐式类型转换。

const char *arr= "12131";
string str = arr; // char* 隐式转为 string

2.3.3 string转char*

string转char*一般需要用到一个c_str()函数,注意c_str()函数返回的是const类型

string str = "hello world";

const char *p = str.c_str();
char *p1 = const_cast<char *>(str.c_str());

2.3.4 signed和unsigned强转相关问题

先看一道题目:

unsigned int a = 6;
int b = -20;
std::cout << ((a + b < 0) ? "true" : "false") << std::endl;

解析:a和b相加的时候,b会先自动转为unsigned int再进行相加。b为负数,最高位为1,转为unsigned,最高位1不算做符号位而是数值,计算进去就会是很大的无符号整数了

再看一道题目:

int main()
{
	unsigned char a = -1;
	char b = a;

	printf("%d", a);
	printf("%d", b);
	return 0;
}

解析:-1是个int常量,在内存中表示为0xffffffff,取8位即0xff给a和b
a按照unsigned char解析,即所有位都是数值位,255
b按照signed解析,即1位符号位,7位数值位,-1

char vs unsigned char:
都是1个字节8位,区别在于最高位是否是符号位,导致数值范围的区别
实际使用中,如普通的赋值,读写文件和网络字节流都没有区别,不管最高位是什么,最终的读取结果都一样。

但是要把一个char类型的变量赋值给int、long等数据类型或进行类似的强制类型转换时时,系统会进行类型扩展,这时区别就大了。对于char类型的变量,系统会认为最高位为符号位,然后对最高位进行扩展,即符号扩展。若最高位为1,则扩展到int时高位都以1填充。对于unsigned char类型的变量,系统会直接进行无符号扩展,即0扩展。扩展的高位都以0填充。所以在进行类似的操作时,如果char和unsigned char最高位都是0,则结果是一样的,若char最高位为1,则结果会大相径庭。

2.3.5 const和非const的转换

通过C++的关键字 const_cast进行转换。

3.3 urlencode和urldecode的C++实现

参考:https://www.cnblogs.com/claireyuancy/p/6915447.html

3.3.1 字符串转为16进制

4 vector容器

项目中的示例:

const vector<unsigned char> body = request->get_body();
const unsigned char* tmp = body.data();

4.1 data()

返回容器第一个元素的指针

int main()
{
	vector<int> v1;

	for(int i = 1; i < 5; i++)
	{
		v1.push_back(1);
	}

	for(auto it = v1.begin(); it != v1.end(); it++)
	{
		cout<<*it<<" ";
	}
	cout<<endl;

	auto v = v1.data(); // int *v = v1.data();
	for(int i = 0; i < v1.size(); i++)
	{
		cout<<*v<<" ";
	}
	cout<<endl;

	return 0;
}
 类似资料: