最近想做个基于Opengl的GUI
试了下SFML发现其String类对宽字节转换有问题,
就修改了下String并重命名为Utf8
使用这个应该可以正确显示中文
该类修改如下:
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_UTF8_HPP
#define SFML_UTF8_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <string>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Utility string class that automatically handles
/// conversions between types and encodings
///
////////////////////////////////////////////////////////////
class Utf8
{
public:
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef std::basic_string<uint32_t>::iterator Iterator; ///< Iterator type
typedef std::basic_string<uint32_t>::const_iterator ConstIterator; ///< Read-only iterator type
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
static const std::size_t InvalidPos; ///< Represents an invalid position in the string
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor creates an empty string.
///
////////////////////////////////////////////////////////////
Utf8();
////////////////////////////////////////////////////////////
/// \brief Construct from a single ANSI character and a locale
///
/// The source character is converted to UTF-32 according
/// to the given locale.
///
/// \param ansiChar ANSI character to convert
/// \param locale Locale to use for conversion
///
////////////////////////////////////////////////////////////
Utf8(char ansiChar);
////////////////////////////////////////////////////////////
/// \brief Construct from single UTF-32 character
///
/// \param utf32Char UTF-32 character to convert
///
////////////////////////////////////////////////////////////
Utf8(uint32_t utf32Char);
////////////////////////////////////////////////////////////
/// \brief Construct from a null-terminated C-style ANSI string and a locale
///
/// The source string is converted to UTF-32 according
/// to the given locale.
///
/// \param ansiString ANSI string to convert
/// \param locale Locale to use for conversion
///
////////////////////////////////////////////////////////////
Utf8(const char* ansiString);
////////////////////////////////////////////////////////////
/// \brief Construct from an ANSI string and a locale
///
/// The source string is converted to UTF-32 according
/// to the given locale.
///
/// \param ansiString ANSI string to convert
/// \param locale Locale to use for conversion
///
////////////////////////////////////////////////////////////
Utf8(const std::string& ansiString);
////////////////////////////////////////////////////////////
/// \brief Construct from a null-terminated C-style UTF-32 string
///
/// \param utf32String UTF-32 string to assign
///
////////////////////////////////////////////////////////////
Utf8(const uint32_t* utf32String);
////////////////////////////////////////////////////////////
/// \brief Construct from an UTF-32 string
///
/// \param utf32String UTF-32 string to assign
///
////////////////////////////////////////////////////////////
Utf8(const std::basic_string<uint32_t>& utf32String);
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
/// \param copy Instance to copy
///
////////////////////////////////////////////////////////////
Utf8(const Utf8& copy);
////////////////////////////////////////////////////////////
/// \brief Implicit conversion operator to std::string (ANSI string)
///
/// The current global locale is used for conversion. If you
/// want to explicitly specify a locale, see toAnsiString.
/// Characters that do not fit in the target encoding are
/// discarded from the returned string.
/// This operator is defined for convenience, and is equivalent
/// to calling toAnsiString().
///
/// \return Converted ANSI string
///
/// \see toAnsiString, operator std::wstring
///
////////////////////////////////////////////////////////////
operator std::string() const;
////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to an ANSI string
///
/// The UTF-32 string is converted to an ANSI string in
/// the encoding defined by \a locale.
/// Characters that do not fit in the target encoding are
/// discarded from the returned string.
///
/// \param locale Locale to use for conversion
///
/// \return Converted ANSI string
///
/// \see toWideString, operator std::string
///
////////////////////////////////////////////////////////////
std::string toAnsiString() const;
////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to a UTF-32 string
///
/// This function doesn't perform any conversion, since the
/// string is already stored as UTF-32 internally.
///
/// \return Converted UTF-32 string
///
/// \see toUtf8, toUtf16
///
////////////////////////////////////////////////////////////
std::basic_string<uint32_t> toUtf32() const;
////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator
///
/// \param right Instance to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
Utf8& operator =(const Utf8& right);
////////////////////////////////////////////////////////////
/// \brief Overload of += operator to append an UTF-32 string
///
/// \param right String to append
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
Utf8& operator +=(const Utf8& right);
////////////////////////////////////////////////////////////
/// \brief Overload of [] operator to access a character by its position
///
/// This function provides read-only access to characters.
/// Note: the behavior is undefined if \a index is out of range.
///
/// \param index Index of the character to get
///
/// \return Character at position \a index
///
////////////////////////////////////////////////////////////
uint32_t operator [](std::size_t index) const;
////////////////////////////////////////////////////////////
/// \brief Overload of [] operator to access a character by its position
///
/// This function provides read and write access to characters.
/// Note: the behavior is undefined if \a index is out of range.
///
/// \param index Index of the character to get
///
/// \return Reference to the character at position \a index
///
////////////////////////////////////////////////////////////
uint32_t& operator [](std::size_t index);
////////////////////////////////////////////////////////////
/// \brief Clear the string
///
/// This function removes all the characters from the string.
///
/// \see isEmpty, erase
///
////////////////////////////////////////////////////////////
void clear();
////////////////////////////////////////////////////////////
/// \brief Get the size of the string
///
/// \return Number of characters in the string
///
/// \see isEmpty
///
////////////////////////////////////////////////////////////
std::size_t getSize() const;
////////////////////////////////////////////////////////////
/// \brief Check whether the string is empty or not
///
/// \return True if the string is empty (i.e. contains no character)
///
/// \see clear, getSize
///
////////////////////////////////////////////////////////////
bool isEmpty() const;
////////////////////////////////////////////////////////////
/// \brief Erase one or more characters from the string
///
/// This function removes a sequence of \a count characters
/// starting from \a position.
///
/// \param position Position of the first character to erase
/// \param count Number of characters to erase
///
////////////////////////////////////////////////////////////
void erase(std::size_t position, std::size_t count = 1);
////////////////////////////////////////////////////////////
/// \brief Insert one or more characters into the string
///
/// This function inserts the characters of \a str
/// into the string, starting from \a position.
///
/// \param position Position of insertion
/// \param str Characters to insert
///
////////////////////////////////////////////////////////////
void insert(std::size_t position, const Utf8& str);
////////////////////////////////////////////////////////////
/// \brief Find a sequence of one or more characters in the string
///
/// This function searches for the characters of \a str
/// in the string, starting from \a start.
///
/// \param str Characters to find
/// \param start Where to begin searching
///
/// \return Position of \a str in the string, or String::InvalidPos if not found
///
////////////////////////////////////////////////////////////
std::size_t find(const Utf8& str, std::size_t start = 0) const;
////////////////////////////////////////////////////////////
/// \brief Replace a substring with another string
///
/// This function replaces the substring that starts at index \a position
/// and spans \a length characters with the string \a replaceWith.
///
/// \param position Index of the first character to be replaced
/// \param length Number of characters to replace. You can pass InvalidPos to
/// replace all characters until the end of the string.
/// \param replaceWith String that replaces the given substring.
///
////////////////////////////////////////////////////////////
void replace(std::size_t position, std::size_t length, const Utf8& replaceWith);
////////////////////////////////////////////////////////////
/// \brief Replace all occurrences of a substring with a replacement string
///
/// This function replaces all occurrences of \a searchFor in this string
/// with the string \a replaceWith.
///
/// \param searchFor The value being searched for
/// \param replaceWith The value that replaces found \a searchFor values
///
////////////////////////////////////////////////////////////
void replace(const Utf8& searchFor, const Utf8& replaceWith);
////////////////////////////////////////////////////////////
/// \brief Return a part of the string
///
/// This function returns the substring that starts at index \a position
/// and spans \a length characters.
///
/// \param position Index of the first character
/// \param length Number of characters to include in the substring (if
/// the string is shorter, as many characters as possible
/// are included). \ref InvalidPos can be used to include all
/// characters until the end of the string.
///
/// \return String object containing a substring of this object
///
////////////////////////////////////////////////////////////
Utf8 substring(std::size_t position, std::size_t length = InvalidPos) const;
////////////////////////////////////////////////////////////
/// \brief Get a pointer to the C-style array of characters
///
/// This functions provides a read-only access to a
/// null-terminated C-style representation of the string.
/// The returned pointer is temporary and is meant only for
/// immediate use, thus it is not recommended to store it.
///
/// \return Read-only pointer to the array of characters
///
////////////////////////////////////////////////////////////
const uint32_t* getData() const;
////////////////////////////////////////////////////////////
/// \brief Return an iterator to the beginning of the string
///
/// \return Read-write iterator to the beginning of the string characters
///
/// \see end
///
////////////////////////////////////////////////////////////
Iterator begin();
////////////////////////////////////////////////////////////
/// \brief Return an iterator to the beginning of the string
///
/// \return Read-only iterator to the beginning of the string characters
///
/// \see end
///
////////////////////////////////////////////////////////////
ConstIterator begin() const;
////////////////////////////////////////////////////////////
/// \brief Return an iterator to the end of the string
///
/// The end iterator refers to 1 position past the last character;
/// thus it represents an invalid character and should never be
/// accessed.
///
/// \return Read-write iterator to the end of the string characters
///
/// \see begin
///
////////////////////////////////////////////////////////////
Iterator end();
////////////////////////////////////////////////////////////
/// \brief Return an iterator to the end of the string
///
/// The end iterator refers to 1 position past the last character;
/// thus it represents an invalid character and should never be
/// accessed.
///
/// \return Read-only iterator to the end of the string characters
///
/// \see begin
///
////////////////////////////////////////////////////////////
ConstIterator end() const;
private:
friend bool operator ==(const Utf8& left, const Utf8& right);
friend bool operator <(const Utf8& left, const Utf8& right);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::basic_string<uint32_t> m_string; ///< Internal string of UTF-32 characters
};
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of == operator to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return True if both strings are equal
///
////////////////////////////////////////////////////////////
bool operator ==(const Utf8& left, const Utf8& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of != operator to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return True if both strings are different
///
////////////////////////////////////////////////////////////
bool operator !=(const Utf8& left, const Utf8& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of < operator to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return True if \a left is lexicographically before \a right
///
////////////////////////////////////////////////////////////
bool operator <(const Utf8& left, const Utf8& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of > operator to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return True if \a left is lexicographically after \a right
///
////////////////////////////////////////////////////////////
bool operator >(const Utf8& left, const Utf8& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of <= operator to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return True if \a left is lexicographically before or equivalent to \a right
///
////////////////////////////////////////////////////////////
bool operator <=(const Utf8& left, const Utf8& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of >= operator to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return True if \a left is lexicographically after or equivalent to \a right
///
////////////////////////////////////////////////////////////
bool operator >=(const Utf8& left, const Utf8& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of binary + operator to concatenate two strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return Concatenated string
///
////////////////////////////////////////////////////////////
Utf8 operator +(const Utf8& left, const Utf8& right);
#include "Utf8.inl"
} // namespace sf
#endif // SFML_STRING_HPP
////////////////////////////////////////////////////////////
/// \class sf::String
/// \ingroup system
///
/// sf::String is a utility string class defined mainly for
/// convenience. It is a Unicode string (implemented using
/// UTF-32), thus it can store any character in the world
/// (European, Chinese, Arabic, Hebrew, etc.).
///
/// It automatically handles conversions from/to ANSI and
/// wide strings, so that you can work with standard string
/// classes and still be compatible with functions taking a
/// sf::String.
///
/// \code
/// sf::String s;
///
/// std::string s1 = s; // automatically converted to ANSI string
/// std::wstring s2 = s; // automatically converted to wide string
/// s = "hello"; // automatically converted from ANSI string
/// s = L"hello"; // automatically converted from wide string
/// s += 'a'; // automatically converted from ANSI string
/// s += L'a'; // automatically converted from wide string
/// \endcode
///
/// Conversions involving ANSI strings use the default user locale. However
/// it is possible to use a custom locale if necessary:
/// \code
/// std::locale locale;
/// sf::String s;
///
/// std::string s1 = s.toAnsiString(locale);
/// s = sf::String("hello", locale);
/// \endcode
///
/// sf::String defines the most important functions of the
/// standard std::string class: removing, random access, iterating,
/// appending, comparing, etc. However it is a simple class
/// provided for convenience, and you may have to consider using
/// a more optimized class if your program requires complex string
/// handling. The automatic conversion functions will then take
/// care of converting your string to sf::String whenever SFML
/// requires it.
///
/// Please note that SFML also defines a low-level, generic
/// interface for Unicode handling, see the sf::Utf classes.
///
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include "Utf8.h"
#include <iterator>
#include <cstring>
#include <iostream>
//定义查找表,长度256,表中的数值表示以此为起始字节的utf8字符长度
unsigned char utf8_look_for_table[] =
{
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1};
#define UTFLEN(x) utf8_look_for_table[(x)]
std::basic_string<uint32_t> toUint32t(const std::string& string)
{
std::basic_string<uint32_t> buffer;
int32_t count = 0;
uint32_t data = 0;
auto itr = string.begin();
while(itr != string.end())
{
if(count == 0)
{
if(data != 0)
{
if(data > 255)
data --;
buffer.push_back(data);
data = 0;
}
count = utf8_look_for_table[(unsigned char)*itr];
if(count == 1)
{
buffer.push_back(*itr);
count = 0;
data = 0;
}
else
{
data = *itr + 1;
count --;
}
}
else
{
data = (data << 8) + (1 + *itr);
count --;
}
itr ++;
}
if(data != 0)
{
if(data > 255)
data --;
buffer.push_back(data);
}
return buffer;
}
std::string toStdString(const std::basic_string<uint32_t>& utf8)
{
std::string string;
char buf[6] = {0};
uint32_t length = 0;
auto itr = utf8.begin();
while(itr != utf8.end())
{
uint32_t d = *itr;
buf[0] = *itr & 0xFF;
buf[1] = (*itr & 0xFF00) >> 8;
buf[2] = (*itr & 0xFF0000) >> 16;
buf[3] = (*itr & 0xFF000000) >> 24;
buf[4] = (*itr & 0xFF00000000) >> 32;
buf[5] = (*itr & 0xFF0000000000) >> 36;
for(int i=5;i>=0;i--)
if(buf[i] != 0 && (buf[i]) != -1)
string.push_back(buf[i]);
itr ++;
}
return string;
}
namespace sf
{
////////////////////////////////////////////////////////////
const std::size_t Utf8::InvalidPos = std::basic_string<uint32_t>::npos;
////////////////////////////////////////////////////////////
Utf8::Utf8()
{
}
////////////////////////////////////////////////////////////
Utf8::Utf8(char ansiChar)
{
m_string.push_back(ansiChar);
}
////////////////////////////////////////////////////////////
Utf8::Utf8(uint32_t utf32Char)
{
m_string += utf32Char;
}
////////////////////////////////////////////////////////////
Utf8::Utf8(const char* ansiString)
{
if(ansiString)
{
std::string copy(ansiString);
if(!copy.empty())
m_string = toUint32t(copy);
}
}
////////////////////////////////////////////////////////////
Utf8::Utf8(const std::string& ansiString)
{
m_string = toUint32t(ansiString);
}
////////////////////////////////////////////////////////////
Utf8::Utf8(const uint32_t* utf32String)
{
if(utf32String)
m_string = utf32String;
}
////////////////////////////////////////////////////////////
Utf8::Utf8(const std::basic_string<uint32_t>& utf32String):
m_string(utf32String)
{
}
////////////////////////////////////////////////////////////
Utf8::Utf8(const Utf8& copy):
m_string(copy.m_string)
{
}
////////////////////////////////////////////////////////////
Utf8::operator std::string() const
{
return toAnsiString();
}
////////////////////////////////////////////////////////////
std::string Utf8::toAnsiString()const
{
// Prepare the output string
return toStdString(m_string);
}
////////////////////////////////////////////////////////////
std::basic_string<uint32_t> Utf8::toUtf32()const
{
return m_string;
}
////////////////////////////////////////////////////////////
Utf8& Utf8::operator =(const Utf8& right)
{
m_string = right.m_string;
return *this;
}
////////////////////////////////////////////////////////////
Utf8& Utf8::operator +=(const Utf8& right)
{
m_string += right.m_string;
return *this;
}
////////////////////////////////////////////////////////////
uint32_t Utf8::operator [](std::size_t index)const
{
return m_string[index];
}
////////////////////////////////////////////////////////////
uint32_t& Utf8::operator [](std::size_t index)
{
return m_string[index];
}
////////////////////////////////////////////////////////////
void Utf8::clear()
{
m_string.clear();
}
////////////////////////////////////////////////////////////
std::size_t Utf8::getSize()const
{
return m_string.size();
}
////////////////////////////////////////////////////////////
bool Utf8::isEmpty() const
{
return m_string.empty();
}
////////////////////////////////////////////////////////////
void Utf8::erase(std::size_t position, std::size_t count)
{
m_string.erase(position, count);
}
////////////////////////////////////////////////////////////
void Utf8::insert(std::size_t position, const Utf8& str)
{
m_string.insert(position, str.m_string);
}
////////////////////////////////////////////////////////////
std::size_t Utf8::find(const Utf8& str, std::size_t start)const
{
return m_string.find(str.m_string, start);
}
////////////////////////////////////////////////////////////
void Utf8::replace(std::size_t position, std::size_t length, const Utf8& replaceWith)
{
m_string.replace(position, length, replaceWith.m_string);
}
////////////////////////////////////////////////////////////
void Utf8::replace(const Utf8& searchFor, const Utf8& replaceWith)
{
std::size_t step = replaceWith.getSize();
std::size_t len = searchFor.getSize();
std::size_t pos = find(searchFor);
// Replace each occurrence of search
while (pos != InvalidPos)
{
replace(pos, len, replaceWith);
pos = find(searchFor, pos + step);
}
}
////////////////////////////////////////////////////////////
Utf8 Utf8::substring(std::size_t position,std::size_t length)const
{
return m_string.substr(position,length);
}
////////////////////////////////////////////////////////////
const uint32_t* Utf8::getData()const
{
return m_string.c_str();
}
////////////////////////////////////////////////////////////
Utf8::Iterator Utf8::begin()
{
return m_string.begin();
}
////////////////////////////////////////////////////////////
Utf8::ConstIterator Utf8::begin()const
{
return m_string.begin();
}
////////////////////////////////////////////////////////////
Utf8::Iterator Utf8::end()
{
return m_string.end();
}
////////////////////////////////////////////////////////////
Utf8::ConstIterator Utf8::end() const
{
return m_string.end();
}
////////////////////////////////////////////////////////////
bool operator ==(const Utf8& left, const Utf8& right)
{
return left.m_string == right.m_string;
}
////////////////////////////////////////////////////////////
bool operator !=(const Utf8& left, const Utf8& right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////
bool operator <(const Utf8& left, const Utf8& right)
{
return left.m_string < right.m_string;
}
////////////////////////////////////////////////////////////
bool operator >(const Utf8& left,const Utf8& right)
{
return right < left;
}
////////////////////////////////////////////////////////////
bool operator <=(const Utf8& left, const Utf8& right)
{
return !(right < left);
}
////////////////////////////////////////////////////////////
bool operator >=(const Utf8& left, const Utf8& right)
{
return !(left < right);
}
////////////////////////////////////////////////////////////
Utf8 operator +(const Utf8& left, const Utf8& right)
{
Utf8 string = left;
string += right;
return string;
}
} // namespace sf
使用这个代替原有的String应该可以正确显示中文 有空试下