【问题标题】:How does cin read strings into an object of string class?cin 如何将字符串读入字符串类的对象?
【发布时间】:2021-12-15 04:23:14
【问题描述】:

在线阅读一些文档后,我发现istream 类早在添加string 类之前就属于C++。所以istream 设计可以识别基本的C++ 类型,例如doubleint,但它不知道string 类型。所以有istream类方法处理doubleint等基本类型,但没有istream类方法处理string对象。

我的问题是如果没有istream 类方法来处理string 对象,为什么这个程序可以工作以及如何工作?

#include <iostream>

int main(void)
{
  std::string str;
  
  std::cin >> str;
  std::cout << str << std::endl;

  return 0;
}

【问题讨论】:

标签: c++ cin stdstring istream


【解决方案1】:

这可以通过使用运算符重载来实现。如下例所示,您可以创建自己的类并重载operator&gt;&gt;operator&lt;&lt;

#include <iostream>

class Number 
{  
    //overload operator<< so that we can use std::cout<<  
    friend std::ostream& operator<<(std::ostream &os, const Number& num);
    
    //overload operator>> so that we can use std::cin>>
    friend std::istream &operator>>(std::istream &is, Number &obj);

    int m_value = 0;
    
    public:
        Number(int value = 0);    
};

Number::Number(int value): m_value(value)
{ 
}

std::ostream& operator<<(std::ostream &os, const Number& num)
{
    os << num.m_value;
    return os;
}

std::istream &operator>>(std::istream &is, Number &obj)
{
    is >> obj.m_value;
    if (is)        // check that the inputs succeeded
    {
        ;//do something
    }
    else
    {
        obj = Number(); // input failed: give the object the default state
    
    }
    return is;
}

int main()
{
     Number a{ 10 };
     
     std::cout << a << std::endl; //this will print 10
     
     std::cin >> a; //this will take input from user 
    
    std::cout << a << std::endl; //this will print whatever number (m_value) the user entered above

    return 0;
}

通过重载operator&gt;&gt;operator&lt;&lt;,我们可以在上面的程序中写std::cin &gt;&gt; astd::cout &lt;&lt; a

与上面显示的Number 类类似,std::string 类也使用运算符重载。特别是 std::string overloads operator&gt;&gt; and operator&lt;&lt;,允许我们编写 std::cin &gt;&gt; strstd::cout &lt;&lt; str,就像您在示例中所做的那样。

【讨论】:

  • 问题是关于istream 输入,但你的答案是关于ostream 输出。即使您的答案是正确的,您也应该将其扩展以涵盖实际询问的内容。
  • @RemyLebeau 问题中的代码 sn-p 也包含std::cout&lt;&lt;str; 所以我据此给出了答案。现在我还在std::cin &gt;&gt; str 的答案末尾添加(编辑)。看看吧。
【解决方案2】:

因为运算符重载。

在您的情况下,包括&lt;iostream&gt; 将包括&lt;string&gt;std::basic_string 的特化。 std::basic_string 定义了 non-member functions operator&lt;&lt; and operator&gt;&gt;

同样,您也可以为自己的自定义类型重载 operator&lt;&lt;operator&gt;&gt;

【讨论】:

  • "包括&lt;iostream&gt; 将包括&lt;string&gt;" - 请注意,标准标头允许相互包含,但不能要求。因此,如果您想在代码中使用std::string,请不要依赖包括&lt;string&gt; 在内的其他标头,请在您自己的代码中自行完成。与任何其他标准类型相同。
  • @RemyLebeau 感谢修复。是的,很高兴明确指出这一点。在发布后,我已经通过添加“在你的情况下......”在快速编辑中更正了这一点。 (我仍然是第一个并在我几分钟后重复所有其他答案显然不是一个足够好的答案......)
【解决方案3】:

因为std::string 重载了&gt;&gt;&lt;&lt; 运算符以返回类型std::istreamstd::ostream

他们是如何超载的,你可以看看Mat给出的这个link

您也可以创建自己的类和重载运算符。这是一个例子:

class MyClass
{
   int numberOne;
   double numberTwo;
public:
   friend std::ostream& operator<<(std::ostream &out, const MyClass& myClass);
   friend std::istream& operator>> (std::istream& in, MyClass& myClass);
};
// Since operator<< is a friend of the MyClass class, we can access MyClass's members directly.
std::ostream& operator<<(std::ostream &out, const MyClass& myClass)
{
    out << myClass.numberOne <<  ' ' << myClass.numberTwo;
    return os;
}
// Since operator>> is a friend of the MyClass class, we can access MyClass's members directly.
std::istream& operator>> (std::istream& in, MyClass& myClass)
{
    in >> myClass.numberOne;
    in >> myClass.numberTwo;

    return in;
}


int main()
{
    MyClass myClass;
    std::cin >> myClass;
    std::cout << myClass;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 2016-06-28
    • 1970-01-01
    • 2013-01-11
    • 2012-01-15
    • 2014-02-10
    • 1970-01-01
    相关资源
    最近更新 更多