C++ - 为我的字符串 class 重载运算符 >>
C++ - overloading operator >> for my string class
我实现了字符串classMyString。这是代码:
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
class MyString{
private:
char * content;
int length;
void copy(const MyString & source);
public:
MyString();
MyString(const char * source);
~MyString();
MyString(const MyString & source);
void print(void);
MyString & operator = (const MyString &source);
friend std::ostream & operator << (std::ostream & out, const MyString& towrite);
friend std::istream & operator >> (std::istream & in, MyString & toread);
};
MyString::MyString(){
content = new char[1];
content[0] = '[=11=]';
length = 0;
}
MyString::MyString(const char *source){
length = strlen(source);
content = new char[length + 1];
strcpy(content, source);
}
MyString::~MyString(){
delete[] content;
}
void MyString::copy(const MyString & source){
length = source.length;
content = new char[length + 1];
strcpy(content, source.content);
}
MyString::MyString(const MyString & source){
copy(source);
}
void MyString::print(void){
cout << "" << content << endl;
}
MyString &MyString::operator=(const MyString &source){
copy(source);
return *this;
}
std::ostream & operator<<(std::ostream & out,const MyString& towrite){
out << towrite.content;
return out;
}
std::istream & operator >> (std::istream & in, MyString & toread){
int length;
std::cout << "Enter length of word: " << endl;
std::cin >> length;
toread.length = length;
toread.content = new char[toread.length+1];
for (int i = 0; i < toread.length; i++){
in >> toread.content[i] ;
}
toread.content[toread.length] = '[=11=]';
return in;
}
我的问题与运算符重载相关 >>.
对于这个主程序:
int main(){
MyString word;
std::cout<<"Enter some word: "<<endl;
std::cin>>word;
std::cout<<"Your entered: "<<word<<endl;
}
这是输出:
Enter some word:
Enter length of word:
5
stack
Your entered: stack
Process returned 0 (0x0) execution time : 8.313 s
Press any key to continue.
它正确地打印了用户输入的字符串,但它没有按我想要的方式 "mimic" 原始字符串 class。这就是原因。
如果使用 C++ 字符串 class:
int main(){
std::string word;
std::cout<<"Enter some word: "<<endl;
std::cin>>word;
std::cout<<"Your entered: "<<word<<endl;
}
用户不需要输入单词的长度。我可以用 class 实现吗?
编辑 1:
我是这样做的:
std::istream & operator >> (std::istream & in, MyString & toread){
char *temp;
temp = new char[100];
char c;
int i = 0;
while(c != '\n'){
c = getchar();
temp[i++] = c;
}
temp[i] = '[=15=]';
int length = i-1;
toread.length = length;
toread.content = new char[toread.length+1];
for(int i = 0 ; i < toread.length ; i++){
toread.content[i] = temp[i];
}
delete [] temp;
toread.content[toread.length+1]='[=15=]';
}
它正常工作。但是,我收到警告是因为我没有 return "in":
||=== Build: Debug in fdsfsdf (compiler: GNU GCC Compiler) ===|
C:\Users\hae\Desktop\fdsfsdf\main.cpp||In function 'std::istream& operator>>(std::istream&, MyString&)':|
C:\Users\hae\Desktop\fdsfsdf\main.cpp|137|warning: no return statement in function returning non-void [-Wreturn-type]|
||=== Build finished: 0 error(s), 1 warning(s) (0 minute(s), 4 second(s)) ===|
||=== Run: Debug in fdsfsdf (compiler: GNU GCC Compiler) ===|
这是我很久以前写的类似 class 的精简版。这是一个古董,但它应该可以工作,并解决了您 class.
的一些问题
class charray {
public:
charray();
~charray();
charray(const charray&);
charray(const char*);
charray& operator=(const charray&);
charray& operator=(const char*);
void swap(charray&);
const char* c_str() const
{ return m_elem; }
unsigned int size() const
{ return m_size; }
private:
void m_resize(unsigned int size);
char* m_elem;
unsigned int m_size;
};
// private.
void charray::m_resize(unsigned int size)
{
char* elem = new char[size+1];
memcpy(elem, m_elem, std::min(m_size, size));
elem[size] = '[=10=]';
delete [] m_elem;
m_elem = elem;
m_size = size;
}
// public.
charray::charray()
: m_elem(0), m_size(0)
{
m_resize(0);
}
charray::~charray()
{
delete [] m_elem;
}
charray::charray(const charray& src)
: m_elem(0), m_size(0)
{
unsigned int size = src.size();
m_resize(size);
memcpy(m_elem, src.c_str(), size);
}
charray::charray(const char* src)
: m_elem(0), m_size(0)
{
unsigned int size = std::strlen(src);
m_resize(size);
memcpy(m_elem, src, size);
}
charray& charray::operator=(const charray& rhs)
{
charray temp(rhs);
this->swap(temp);
return *this;
}
charray& charray::operator=(const char* rhs)
{
charray temp(rhs);
this->swap(temp);
return *this;
}
void charray::swap(charray& b)
{
std::swap(m_elem, b.m_elem);
std::swap(m_size, b.m_size);
}
这可能是您最感兴趣的内容。请密切注意细节。直接处理内存时,有效实现和损坏实现之间的区别通常非常微妙。
注意:运营商不是朋友。他们不访问私人数据。
std::ostream& operator<<(std::ostream& out, const charray& in)
{
return out << in.c_str();
}
std::istream& operator>>(std::istream& in, charray& out)
{
// verify no errors are set, flush tied streams, strip leading
// whitespace.
std::istream::sentry sentry(in);
if (!sentry)
return in;
unsigned int size = 0;
unsigned int tail = 0;
char* temp = 0;
int next; // @note int not char (to record EOF).
while ((next = in.get()) != in.eof() && !std::isspace(next)) {
// if temp buffer is exhausted, then double the buffer size.
// (base size of 16).
if (tail == size) {
unsigned int newsize = std::max(2*size, 16u);
char* newtemp = new char[newsize+1];
memcpy(newtemp, temp, size);
delete [] temp;
temp = newtemp;
size = newsize;
}
temp[tail++] = next;
}
// @note because the stream is prepeared with istream::sentry, there
// will be at least one non-whitespace character in the stream.
assert(temp != 0);
temp[tail] = '[=11=]';
out = temp;
delete [] temp;
return in;
}
一种更简单、更安全的方法来完成同样的事情,
#include <vector>
std::istream& operator>>(std::istream& in, charray& out)
{
std::istream::sentry sentry(in);
if (!sentry)
return in;
std::vector<char> temp;
int next;
while ((next = in.get()) != in.eof() && !std::isspace(next))
temp.push_back(next);
temp.push_back('[=12=]');
out = &temp[0];
return in;
}
编辑
以上内容已经过时(C++11 之前)。现代实现可能会以不同方式处理构建和分配。以下是这些方法的更新版本,
注:方法m_resize
没了。一切都通过构造函数处理。
charray::charray(const char* src, unsigned int size)
: m_elem{ new char[size+1]{} }, m_size{ size }
{
std::copy(src, src + size, m_elem);
}
charray::charray()
: charray(nullptr, 0)
{}
charray::charray(const charray& src)
: charray(src.m_elem, src.m_size)
{}
charray::charray(const char* src)
: charray(src, std::strlen(src))
{}
charray::charray(charray&& src)
: m_elem{ src.m_elem }, m_size{ src.m_size }
{
src.m_elem = nullptr;
src.m_size = 0;
}
// handle both move and copy assignment.
charray& charray::operator=(charray rhs)
{
this->swap(rhs);
return *this;
}
希望这对您有所帮助。祝你好运。
我实现了字符串classMyString。这是代码:
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
class MyString{
private:
char * content;
int length;
void copy(const MyString & source);
public:
MyString();
MyString(const char * source);
~MyString();
MyString(const MyString & source);
void print(void);
MyString & operator = (const MyString &source);
friend std::ostream & operator << (std::ostream & out, const MyString& towrite);
friend std::istream & operator >> (std::istream & in, MyString & toread);
};
MyString::MyString(){
content = new char[1];
content[0] = '[=11=]';
length = 0;
}
MyString::MyString(const char *source){
length = strlen(source);
content = new char[length + 1];
strcpy(content, source);
}
MyString::~MyString(){
delete[] content;
}
void MyString::copy(const MyString & source){
length = source.length;
content = new char[length + 1];
strcpy(content, source.content);
}
MyString::MyString(const MyString & source){
copy(source);
}
void MyString::print(void){
cout << "" << content << endl;
}
MyString &MyString::operator=(const MyString &source){
copy(source);
return *this;
}
std::ostream & operator<<(std::ostream & out,const MyString& towrite){
out << towrite.content;
return out;
}
std::istream & operator >> (std::istream & in, MyString & toread){
int length;
std::cout << "Enter length of word: " << endl;
std::cin >> length;
toread.length = length;
toread.content = new char[toread.length+1];
for (int i = 0; i < toread.length; i++){
in >> toread.content[i] ;
}
toread.content[toread.length] = '[=11=]';
return in;
}
我的问题与运算符重载相关 >>.
对于这个主程序:
int main(){
MyString word;
std::cout<<"Enter some word: "<<endl;
std::cin>>word;
std::cout<<"Your entered: "<<word<<endl;
}
这是输出:
Enter some word:
Enter length of word:
5
stack
Your entered: stack
Process returned 0 (0x0) execution time : 8.313 s
Press any key to continue.
它正确地打印了用户输入的字符串,但它没有按我想要的方式 "mimic" 原始字符串 class。这就是原因。
如果使用 C++ 字符串 class:
int main(){
std::string word;
std::cout<<"Enter some word: "<<endl;
std::cin>>word;
std::cout<<"Your entered: "<<word<<endl;
}
用户不需要输入单词的长度。我可以用 class 实现吗?
编辑 1:
我是这样做的:
std::istream & operator >> (std::istream & in, MyString & toread){
char *temp;
temp = new char[100];
char c;
int i = 0;
while(c != '\n'){
c = getchar();
temp[i++] = c;
}
temp[i] = '[=15=]';
int length = i-1;
toread.length = length;
toread.content = new char[toread.length+1];
for(int i = 0 ; i < toread.length ; i++){
toread.content[i] = temp[i];
}
delete [] temp;
toread.content[toread.length+1]='[=15=]';
}
它正常工作。但是,我收到警告是因为我没有 return "in":
||=== Build: Debug in fdsfsdf (compiler: GNU GCC Compiler) ===| C:\Users\hae\Desktop\fdsfsdf\main.cpp||In function 'std::istream& operator>>(std::istream&, MyString&)':| C:\Users\hae\Desktop\fdsfsdf\main.cpp|137|warning: no return statement in function returning non-void [-Wreturn-type]| ||=== Build finished: 0 error(s), 1 warning(s) (0 minute(s), 4 second(s)) ===| ||=== Run: Debug in fdsfsdf (compiler: GNU GCC Compiler) ===|
这是我很久以前写的类似 class 的精简版。这是一个古董,但它应该可以工作,并解决了您 class.
的一些问题class charray {
public:
charray();
~charray();
charray(const charray&);
charray(const char*);
charray& operator=(const charray&);
charray& operator=(const char*);
void swap(charray&);
const char* c_str() const
{ return m_elem; }
unsigned int size() const
{ return m_size; }
private:
void m_resize(unsigned int size);
char* m_elem;
unsigned int m_size;
};
// private.
void charray::m_resize(unsigned int size)
{
char* elem = new char[size+1];
memcpy(elem, m_elem, std::min(m_size, size));
elem[size] = '[=10=]';
delete [] m_elem;
m_elem = elem;
m_size = size;
}
// public.
charray::charray()
: m_elem(0), m_size(0)
{
m_resize(0);
}
charray::~charray()
{
delete [] m_elem;
}
charray::charray(const charray& src)
: m_elem(0), m_size(0)
{
unsigned int size = src.size();
m_resize(size);
memcpy(m_elem, src.c_str(), size);
}
charray::charray(const char* src)
: m_elem(0), m_size(0)
{
unsigned int size = std::strlen(src);
m_resize(size);
memcpy(m_elem, src, size);
}
charray& charray::operator=(const charray& rhs)
{
charray temp(rhs);
this->swap(temp);
return *this;
}
charray& charray::operator=(const char* rhs)
{
charray temp(rhs);
this->swap(temp);
return *this;
}
void charray::swap(charray& b)
{
std::swap(m_elem, b.m_elem);
std::swap(m_size, b.m_size);
}
这可能是您最感兴趣的内容。请密切注意细节。直接处理内存时,有效实现和损坏实现之间的区别通常非常微妙。
注意:运营商不是朋友。他们不访问私人数据。
std::ostream& operator<<(std::ostream& out, const charray& in)
{
return out << in.c_str();
}
std::istream& operator>>(std::istream& in, charray& out)
{
// verify no errors are set, flush tied streams, strip leading
// whitespace.
std::istream::sentry sentry(in);
if (!sentry)
return in;
unsigned int size = 0;
unsigned int tail = 0;
char* temp = 0;
int next; // @note int not char (to record EOF).
while ((next = in.get()) != in.eof() && !std::isspace(next)) {
// if temp buffer is exhausted, then double the buffer size.
// (base size of 16).
if (tail == size) {
unsigned int newsize = std::max(2*size, 16u);
char* newtemp = new char[newsize+1];
memcpy(newtemp, temp, size);
delete [] temp;
temp = newtemp;
size = newsize;
}
temp[tail++] = next;
}
// @note because the stream is prepeared with istream::sentry, there
// will be at least one non-whitespace character in the stream.
assert(temp != 0);
temp[tail] = '[=11=]';
out = temp;
delete [] temp;
return in;
}
一种更简单、更安全的方法来完成同样的事情,
#include <vector>
std::istream& operator>>(std::istream& in, charray& out)
{
std::istream::sentry sentry(in);
if (!sentry)
return in;
std::vector<char> temp;
int next;
while ((next = in.get()) != in.eof() && !std::isspace(next))
temp.push_back(next);
temp.push_back('[=12=]');
out = &temp[0];
return in;
}
编辑
以上内容已经过时(C++11 之前)。现代实现可能会以不同方式处理构建和分配。以下是这些方法的更新版本,
注:方法m_resize
没了。一切都通过构造函数处理。
charray::charray(const char* src, unsigned int size)
: m_elem{ new char[size+1]{} }, m_size{ size }
{
std::copy(src, src + size, m_elem);
}
charray::charray()
: charray(nullptr, 0)
{}
charray::charray(const charray& src)
: charray(src.m_elem, src.m_size)
{}
charray::charray(const char* src)
: charray(src, std::strlen(src))
{}
charray::charray(charray&& src)
: m_elem{ src.m_elem }, m_size{ src.m_size }
{
src.m_elem = nullptr;
src.m_size = 0;
}
// handle both move and copy assignment.
charray& charray::operator=(charray rhs)
{
this->swap(rhs);
return *this;
}
希望这对您有所帮助。祝你好运。