C++中标准库std::string的实现

以下实现了C++标准模板库中std::string中的部分实现,参考了cplusplus.

关于C++中标准模板库std::string的介绍和用法可以参考: https://blog.csdn.net/fengbingchun/article/details/62417284  

实现代码string.hpp如下:

#ifndef FBC_STL_STRING_HPP_
#define FBC_STL_STRING_HPP_

#include 

namespace fbcstd {

class string {
public:
	string();
	string(const string& str);
	string(const string& str, size_t pos, size_t len = npos);
	string(const char* s);
	string(const char* s, size_t n);
	string(size_t n, char c);
	~string();

	const char* c_str() const; 
	size_t length() const;
	size_t size() const;
	
	char& operator [] (size_t pos);
	const char& operator [] (size_t pos) const;
	string& operator = (const string& str);
	string& operator = (const char* s);
	string& operator = (char c);
	string& operator += (const string& str);
	string& operator += (const char* s);
	string& operator += (char c);

	string& append(const string& str);
	string& append(const char* s);

	string& assign(const string& str);
	string& assign(const char* s);

	char& at(size_t pos);
	const char& at(size_t pos) const;

	void clear();

	int compare(const string& str) const;
	int compare(const char* s) const;

	const char* data() const;
	bool empty() const;

	static const size_t npos = -1;

private:
	size_t size_;
	char* buffer_;
}; // class string

inline string::string()
{
	size_ = 0;
	buffer_ = new char[1];
	buffer_[0] = '\0';
}

inline string::string(const string& str)
{
	size_ = str.size_;
	buffer_ = new char[size_+1];
	strcpy(buffer_, str.buffer_);	
}

inline string::string(const string& str, size_t pos, size_t len)
{
	if (pos > str.size_) {
		size_ = 0;
		buffer_ = new char[1];
		buffer_[0] = '\0';
	} else {
		if (pos + len > str.size_)
			size_ = str.size_ - pos;
		else
			size_ = len;

		buffer_ = new char[size_+1];
		const char* p = str.c_str() + pos;
		
		for (size_t i = 0; i < size_; ++i) {
			buffer_[i] = p[i];
		}
		buffer_[size_] = '\0';
	}
}

inline string::string(const char* s)
{
	size_ = strlen(s);
	buffer_ = new char[size_+1];
	strcpy(buffer_, s);
}

inline string::string(const char* s, size_t n)
{
	if (strlen(s) <= n) {
		size_ = strlen(s);
		buffer_ = new char[size_+1];
		strcpy(buffer_, s);
	} else {
		size_ = n;
		buffer_ = new char[size_+1];
		strncpy(buffer_, s, n);
	}
}

inline string::string(size_t n, char c)
{
	size_ = n;
	buffer_ = new char[size_+1];
	memset(buffer_, c, n);
}

inline string::~string()
{
	if (buffer_)
		delete [] buffer_;
	size_ = 0;
}

inline const char* string::c_str() const
{
	return buffer_;
}

inline size_t string::length() const
{
	return size_;
}

inline size_t string::size() const
{
	return size_;
}
	
inline char& string::operator [] (size_t pos)
{
	return buffer_[pos];	
}
	
inline const char& string::operator [] (size_t pos) const
{
	if (pos >= size_)
		return '\0';
	else
		return buffer_[pos];	
}


inline string& string::operator = (const string& str)
{
	if (this->size_ != 0)
		delete [] buffer_;

	size_ = str.size_;
	buffer_ = new char[size_+1];
	strcpy(buffer_, str.c_str());
	return *this;
}

inline string& string::operator = (const char* s)
{
	if (this->size_ != 0)
		delete [] buffer_;

	size_ = strlen(s);
	buffer_ = new char[size_+1];
	strcpy(buffer_, s);
	return *this;
}

inline string& string::operator = (char c)
{
	if (this->size_ != 1)
		delete [] buffer_;

	size_ = 1;
	buffer_ = new char[size_+1];
	buffer_[0] = c;
	buffer_[size_] = '\0';
	return *this;
}
	
inline string& string::operator += (const string& str)
{
	size_ += str.size_;
	char* data = new char[size_+1];
	strcpy(data, buffer_);
	strcat(data, str.buffer_);

	delete [] buffer_;
	buffer_ = data;
	return *this;
}

inline string& string::operator += (const char* s)
{
	size_ += strlen(s);
	char* data = new char[size_+1];
	strcpy(data, buffer_);
	strcat(data, s);

	delete [] buffer_;
	buffer_ = data;
	return *this;
}

inline string& string::operator += (char c)
{
	size_ += 1;
	char* data = new char[size_+1];
	strcpy(data, buffer_);
	strcat(data, &c);

	delete [] buffer_;
	buffer_ = data;
	return *this;
}

inline string& string::append(const string& str)
{
	*this += str;
	return *this;
}

inline string& string::append(const char* s)
{
	*this += s;
	return *this;
}

inline string& string::assign(const string& str)
{
	*this = str;
	return *this;
}
	
inline string& string::assign(const char* s)
{
	*this = s;
	return *this;
}

inline char& string::at(size_t pos)
{
	return buffer_[pos];
}
	
inline const char& string::at(size_t pos) const
{
	return buffer_[pos];
}

inline void string::clear()
{
	delete [] buffer_;
	size_ = 0;
	buffer_ = new char[1];
	buffer_[0] = '\0';
}
	
inline int string::compare(const string& str) const
{
	return strcmp(buffer_, str.buffer_);
}

inline int string::compare(const char* s) const
{
	return strcmp(buffer_, s);
}

inline const char* string::data() const
{
	return buffer_;
}
	
inline bool string::empty() const
{
	return (size_ == 0);
}

static inline string operator + (const string& lhs, const string& rhs)
{
	string str(lhs);
	str += rhs;
	return str;
}

static inline string operator + (const string& lhs, const char* rhs)
{
	string str(lhs);
	str += rhs;
	return str;
}

static inline string operator + (const char* lhs, const string& rhs)
{
	string str(lhs);
	str += rhs;
	return str;
}

static inline string operator + (const string& lhs, char rhs)
{
	string str(lhs);
	str += rhs;
	return str;
}

static inline string operator + (char lhs, const string& rhs)
{
	string str(&lhs);
	str += rhs;
	return str;
}

static inline bool operator == (const string& lhs, const string& rhs)
{
	return (lhs.compare(rhs) == 0);
}

static inline bool operator == (const char* lhs, const string& rhs)
{
	return (rhs.compare(lhs) == 0);
}

static inline bool operator == (const string& lhs, const char* rhs)
{
	return (lhs.compare(rhs) == 0);
}

static inline bool operator != (const string& lhs, const string& rhs)
{
	return (lhs.compare(rhs) != 0);
}

static inline bool operator != (const char* lhs, const string& rhs)
{
	return (rhs.compare(lhs) != 0);
}

static inline bool operator != (const string& lhs, const char* rhs)
{
	return (lhs.compare(rhs) != 0);
}

static inline bool operator < (const string& lhs, const string& rhs)
{
	return (lhs.compare(rhs) < 0);
}

static inline bool operator < (const char* lhs, const string& rhs)
{
	return (rhs.compare(lhs) >= 0);
}

static inline bool operator < (const string& lhs, const char* rhs)
{
	return (lhs.compare(rhs) < 0);
}

static inline bool operator <= (const string& lhs, const string& rhs)
{
	return (lhs.compare(rhs) <= 0);
}

static inline bool operator <= (const char* lhs, const string& rhs)
{
	return (rhs.compare(lhs) > 0);
}

static inline bool operator <= (const string& lhs, const char* rhs)
{
	return (lhs.compare(rhs) <= 0);
}

static inline bool operator > (const string& lhs, const string& rhs)
{
	return (lhs.compare(rhs) > 0);
}

static inline bool operator > (const char* lhs, const string& rhs)
{
	return (rhs.compare(lhs) <= 0);
}

static inline bool operator > (const string& lhs, const char* rhs)
{
	return (lhs.compare(rhs) > 0);
}

static inline bool operator >= (const string& lhs, const string& rhs)
{
	return (lhs.compare(rhs) >= 0);
}

static inline bool operator >= (const char* lhs, const string& rhs)
{
	return (rhs.compare(lhs) < 0);
}

static inline bool operator >= (const string& lhs, const char* rhs)
{
	return (lhs.compare(rhs) >= 0);
}

} // namespace fbcstd

#endif // FBC_STL_STRING_HPP_

测试代码test_string.cpp如下:

#include 
#include "string.hpp"

#define std fbcstd

int main()
{

{ // constructor
	std::string s0("Initial string");
	fprintf(stdout, "s0: %s\n", s0.c_str());
	std::string s1;
	fprintf(stdout, "s1: %s\n", s1.c_str());
	std::string s2(s0);
	fprintf(stdout, "s2: %s\n", s2.c_str());
	std::string s3(s0, 8, 3);
	fprintf(stdout, "s3: %s\n", s3.c_str());
	std::string s4("A character sequence ");
	fprintf(stdout, "s4: %s\n", s4.c_str());
	std::string s5("Another character sequence", 12);
	fprintf(stdout, "s5: %s\n", s5.c_str());
	std::string s6a(10, 'x');
	fprintf(stdout, "s6a: %s\n", s6a.c_str());
	std::string s6b(10, 42);
	fprintf(stdout, "s6b: %s\n", s6b.c_str());
} // constructor

{ // length, size, c_str()
	std::string str("Test string");
	fprintf(stdout, "str length: %d\n", str.length());
	fprintf(stdout, "str size: %d\n", str.size());
	fprintf(stdout, "str: %s\n", str.c_str());
}

{ // operator []
	std::string str("Test String");
	const char &c1 = str[0], &c2 = str[5];
	fprintf(stdout, "c1: %c; c2: %c; str: %s\n", c1, c2, str.c_str());
	char &c3 = str[0], &c4 = str[5];
	c3 = 't'; c4 = 's';
	fprintf(stdout, "c3: %c; c4: %c; str: %s\n", c3, c4, str.c_str());
}

{ // operator =
	std::string str("https://blog.csdn.net/fengbingchun/");
	std::string str1, str2, str3;
	str1 = str;
	str2 = "https://github.com/fengbingchun";
	str3 = 'x';
	fprintf(stdout, "str1: %s; str2: %s; str3: %s\n", str1.c_str(), str2.c_str(), str3.c_str());
}

{ // operator +=
	std::string name("John");
	std::string family("Smith");
	name += " K. ";
	name += family;
	name += '\n';
	fprintf(stdout, "name: %s", name.c_str());
}

{ // append
	std::string str1 = "CSDN: ";
	std::string str2 = "https://blog.csdn.net/fengbingchun/";
	str1.append(str2);
	fprintf(stdout, "str1: %s\n", str1.c_str());

	std::string str3("GitHub: ");
	str3.append("https://github.com/fengbingchun");
	fprintf(stdout, "str3: %s\n", str3.c_str());
}

{ // assign
	std::string str1, str2;
	std::string str3("CSDN: https://blog.csdn.net/fengbingchun/");
	str1.assign(str3);
	fprintf(stdout, "str1: %s\n", str1.c_str());	

 	str2.assign("GitHub: https://github.com/fengbingchun");
	fprintf(stdout, "str2: %s\n", str2.c_str());
}

{ // at
	std::string str("Test String");
	const char& a = str.at(5);
	fprintf(stdout, "a: %c, str: %s\n", a, str.c_str());

	char& b = str.at(5);
	b = 's';
	fprintf(stdout, "b: %c, str: %s\n", b, str.c_str());
	 
}

{ // clear
	std::string str("Test String");
	fprintf(stdout, "str: %s\n", str.c_str());
	str.clear();
	fprintf(stdout, "str: %s\n", str.c_str());
}

{ // compare
	std::string str1("Test"), str2("String"), str3("Apple"), str4("String");
	fprintf(stdout, "str2:str1: %d; st2:str3: %d; str2:str4: %d\n",
		str2.compare(str1), str2.compare(str3), str2.compare(str4));
	fprintf(stdout, "str2:str1: %d; st2:str3: %d; str2:str4: %d\n",
		str2.compare("Test"), str2.compare("Apple"), str2.compare("String"));
}

{ // data, empty
	std::string str("Test String"), str2;
	fprintf(stdout, "str: %s\n", str.data());

	fprintf(stdout, "str is empty: %d; st2 is empty: %d\n", str.empty(), str2.empty());
}

{ // operator +
	std::string firstlevel("com");
	std::string secondlevel("cplusplus");
	std::string scheme("http://");
	std::string hostname;
	std::string url;
	
	hostname = "www." + secondlevel + '.' + firstlevel;
	url = scheme + hostname;
	fprintf(stdout, "url: %s\n", url.c_str());
}

{ // operator: ==, !=, <, <=, >, >=
	std::string foo = "alpha";
	std::string bar = "beta";
	
	if (foo == bar) fprintf(stdout, "foo == bar\n");
	if (foo != bar) fprintf(stdout, "foo != bar\n");
	if (foo < bar) fprintf(stdout, "foo < bar\n");
	if (foo > bar) fprintf(stdout, "foo > bar\n");
	if (foo <= bar) fprintf(stdout, "foo <= bar\n");
	if (foo >= bar) fprintf(stdout, "foo >= bar\n");
}

	return 0;
}

CMakeLists.txt内容如下:

PROJECT(Samples_STL_Implementation)
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)

SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -O2 -std=c11")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -g -Wall -O2 -std=c++11")

INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src)
MESSAGE(STATUS "project source dir: ${PROJECT_SOURCE_DIR}")

FILE(GLOB tests ${PROJECT_SOURCE_DIR}/test/*.cpp)

FOREACH (test ${tests})
	STRING(REGEX MATCH "[^/]+$" test_file ${test})
	STRING(REPLACE ".cpp" "" test_basename ${test_file})
	ADD_EXECUTABLE(${test_basename} ${test})
	TARGET_LINK_LIBRARIES(${test_basename} pthread)
ENDFOREACH()

脚本build.sh内容如下:

#! /bin/bash

real_path=$(realpath $0)
dir_name=`dirname "${real_path}"`
echo "real_path: ${real_path}, dir_name: ${dir_name}"

new_dir_name=${dir_name}/build
mkdir -p ${new_dir_name}
cd ${new_dir_name}
cmake ..
make

cd -

编译及测试方法:将终端定位到Samples_STL_Implementation目录下,执行:$ ./build.sh , 然后再执行$ ./build/test_string即可。

GitHub: https://github.com/fengbingchun/Linux_Code_Test  

你可能感兴趣的:(C/C++/C++11)