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

本文介绍了一个简单的 C++ 标准模板库 std::string 的实现,包括构造函数、运算符重载等方法,并提供了测试代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

实现代码string.hpp如下:

#ifndef FBC_STL_STRING_HPP_
#define FBC_STL_STRING_HPP_

#include <string.h>

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 <iostream>
#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.youkuaiyun.com/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 = "优快云: ";
	std::string str2 = "https://blog.youkuaiyun.com/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("优快云: https://blog.youkuaiyun.com/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即可。

GitHubhttps://github.com/fengbingchun/Linux_Code_Test  

<think>嗯,用户遇到了在C++中使用std::to_string()函数时的报错,需要解决方案。首先,我得回忆一下常见的导致这个错误的原因。可能的情况包括编译器版本不支持、未包含必要的头文件,或者命名空间的问题。 首先,检查头文件是否正确。std::to_string()函数在C++11中引入,位于<string>头文件中。如果用户没有包含这个头文件,编译器会找不到函数的声明,导致未定义的引用错误。这时候需要确保代码中有#include <string>。 然后,编译器是否支持C++11标准。如果用户使用的是较旧的编译器,或者没有启用C++11或更高版本的编译选项,比如在g++中没有使用-std=c++11,那么std::to_string可能不可用。这时候需要检查编译命令是否包含正确的标志,如-std=c++11、-std=c++14等。 接下来,链接错误的问题。有时候,特别是使用某些标准库实现时,可能需要正确链接库文件。比如,使用g++时可能需要显式链接libstdc++,不过这种情况相对少见,通常编译器会自动处理。但用户如果遇到未定义的符号错误,可能需要检查链接步骤是否正确。 另外,用户可能错误地使用了命名空间。比如,如果在代码中使用了using namespace std;,但错误地调用了to_string而不是std::to_string,或者存在命名冲突,也可能导致问题。需要确认函数的调用方式是否正确,以及是否有其他同名的函数干扰。 还有,参数类型是否正确。std::to_string()接受整数、浮点数等基本类型作为参数,如果传入的是自定义类型或其他不支持的类型,编译器会报错。需要确保传入的参数类型是函数所支持的。 然后,根据用户提供的引用内容,引用[1]和[2]提到了未定义引用的错误,可能与标准库的链接有关。可能用户没有正确链接C++标准库,或者编译器版本不一致导致符号不匹配。例如,不同版本的libstdc++可能存在ABI兼容性问题,导致链接时找不到正确的符号。 此外,引用[3]中的std::reference_wrapper示例可能无关,但用户提供的引用可能提示其他可能的上下文,比如在代码中使用了某些包装器或引用类型,但可能与当前问题无关。 最后,需要综合这些可能性,给出逐步的解决方案,包括检查头文件、启用C++11标准、检查编译选项、验证参数类型等步骤。同时,提醒用户注意编译器的版本和兼容性问题,确保环境配置正确。</think>以下是关于C++中$std::to\_string()$报错的解决方案分析: ### 一、常见报错原因 1. **缺少头文件** $std::to\_string()$定义在$<string>$头文件中。未包含该头文件会导致编译错误,报错信息如: `error: 'to_string' is not a member of 'std'` 解决方案:添加`#include <string>` 2. **未启用C++11标准** 该函数是C++11引入的。若编译器未开启C++11支持,会报错: `error: 'to_string' is not a member of 'std'` 解决方案:编译时添加参数`-std=c++11`,如: ```bash g++ -std=c++11 your_file.cpp ``` 3. **参数类型不匹配** $std::to\_string()$仅支持基本数值类型(如$int$, $double$等),若传递自定义类型会报错: `error: no matching function for call to 'to_string'` 解决方案:重载$std::to\_string()$或自定义转换函数[^2] ### 二、进阶排查步骤 1. **检查ABI兼容性** 若使用混合编译环境(如同时链接新旧版本库),可能出现符号未定义错误: `undefined reference to std::__cxx11::basic_string...` 解决方案:统一编译器版本,或添加编译选项`-D_GLIBCXX_USE_CXX11_ABI=0` 2. **验证编译环境** 在Eclipse等IDE中检查C++标准设置(路径:Project Properties → C/C++ Build → Settings → Dialect → Language standard)[^4] ### 三、代码示例修正 错误代码: ```cpp #include <iostream> int main() { int num = 42; std::string str = std::to_string(num); // 报错 return 0; } ``` 修正后: ```cpp #include <iostream> #include <string> // 添加头文件 int main() { int num = 42; std::string str = std::to_string(num); // 正常编译 return 0; } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值