Make My Ostream!

Make My OStream 题解

山中何事,松花酿酒,春水煎茶

Description:

自由实现代码,使得下面的代码,以及相关的代码的结果成立:所有需要待实现的东西都已经在代码中。
另外,iostream 和 sstream已经禁用,因此需要用cstdio里面的一些东西来实现效果。

已知mypres的精度不超过6

//其实也就是练习输出下面的东西

int main()
{
         const char *test1 = "Test char";

         myout << test1 << myendl;

         myout << test1[0]<< myendl;

         double e = 6.12345;

         int pres = 1;

         myout << mypres(pres*2);//setprecision(2),2位有效数字

         myout << e << myendl;

         myout << myfixed ;//改为定点输出,即2位小数

         myout << e << myendl;

         int d=15;

         myout << d << myendl;

         myout << myhex << d << myendl;
}

Sample Output
Test char
T
6.1
6.12
15
f
Hint
不需要交main函数

Problem Source: poetry

思路一:期末复习题

这个学期学了好多东西啊..满满干货的日子快要到头了(误)..

于是大大给出了一道class和流结合,官方题解为构造class来实现的神奇题目

具体”考点”如下:

  • 运算符重载

    这道题明显重载左移运算符<<,但是和模板不同的是,这道题重载左移运算符的目的不同,一般是实现流输出比如std::cout << "Hello World" << std::endl;但是这道题重载返回的不是流,而是要求实现输出功能.

    //P17 模板
    friend <函数类型> operator <运算符> (形参表)
    {
    函数体;
    } 
    //一般对输出流重载
    ostream& operator<< (ostream& stream,类名 &other)//重载输出流
    {
     stream << 格式化输出内容;
     return stream;
    }

    但是这道题黑掉了cout.题意也就变成了通过cstdio实现输出流

    记得在SICP中,流就是一种对象

    所以也就不涉及ostream了,那么对比模板和一般模板,发现可以少很多东西,所以我觉得这里是这道题的关键所在

    Write function definition as normal(重载函数跟普通函数一样,具有返回类型和形参表)(课件p6)

    也就是所这道题吧运算符当做函数来重载,实现一个像函数一样的功能.放这道题标准实现前,先回顾一下标准重载在这道题中的一个矛盾

  • 函数的串联 P32

    myout << test1[0]<< myendl;

    上面留下的一个矛盾是,重载返回了一个流,但是新的输出函数如果返回的是void的话就不能实现.所以这里复习了函数的串联.串联就是返回对象本身,然后本身当然可以继续调用本身的函数嘛

    从前有座山,山里有个庙

    所以到这里就可以概括基本实现了,由于myout是山寨一个流对象,所以不妨把它当做一个对象,然后在这个类中实现对于不同内容的输出.

    //举个栗子
    /*重载运算流就是函数*/
    class str
    {
    public:
      str &operator << (const char * a)
      {
          printf("%s",a);
          return *this;
      };
    }
  • printf考察

    很多简单的标记符比如%c,%d就不水了

    但是这道题有趣的是考虑了fixed和setpresion

    第一个是保留小数点后presion位,第二个是设置多少位保留

    • 基本思路是fixed没有参量,可以直接变成一个标志的变化
    • setpresion需要构造一个新的类变成一个新的对象,来”暂时保存”函数值

    hex的思路和fixed一样..我的实现是转化为string(“hex”)来作输出流函数然后设置标志位,输出时候判断.

    //实现代码块
    //忘记这次的变量命名和宏定义毁掉的代码风格QAQ
    
    //part1 define
    
    #define myendl '\n'//对我就是这么黑掉结束符的..
    
    
    #define myhex string("hex")
    
    
    #define myfixed string("myfixed")
    
    
    #define mypres(n) PPP(n)
    
    
    class PPP //maybe an interesting name...
    {
    public:
      PPP(int a):pres(a){};
      int pres;
    };
    //part2 select
    str &operator << (string p)
      {
          if( p == string("hex"))
              h = true;//h is a flag for hex
          else if(p == string("myfixed"))
              f = true;//f is a flag for fixed
          return *this;
      }
    
      str &operator << (PPP k)
      {
          pre = k.pres;//pre for precision
          return *this;
      }

    这里之后输出就需要判断了

    • 输出double判断fixed,
    • fixed用%.*g作为标志位,在pjr大神的题解中用sprintf来输出(fixed就是把precision的意义输出小数点后几位)
    • 否则用%.*lf输出即可
    • 输出int判断hexed
    • 一个用%x,另一种情况用%d

    BTW..突然想起URAL居然有卡printf速度的题= =还以为是soj特色

需要注意的细节

  • 对于<<运算符的重载,需要加&引用符,不然会不停的调用= =(某大大的形容词是不敢想象)

  • double输出有两个参数,一个是*的值

    printf("%.*lf",pre,a);

思路二: 复制粘贴大法好

发现某学霸群大神说了句把iostream内容复制过去然后define掉..然后就跪了QAQ

他的题解

源代码在编译器目录下面有

//贤城大神的代码
#include <bits/c++config.h>
#include <ostream>
#include <istream>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <map>
#include <iomanip>
using namespace std;


#include <bits/c++config.h>
#include <ostream>
#include <istream>

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION


  extern istream cin;       /// Linked to standard input
  extern ostream cout;      /// Linked to standard output
  extern ostream cerr;      /// Linked to standard error (unbuffered)
  extern ostream clog;      /// Linked to standard error (buffered)


  extern wistream wcin;     /// Linked to standard input
  extern wostream wcout;    /// Linked to standard output
  extern wostream wcerr;    /// Linked to standard error (unbuffered)
  extern wostream wclog;    /// Linked to standard error (buffered)

  //@}

  // For construction of filebuffers for cout, cin, cerr, clog et. al.
  static ios_base::Init __ioinit;

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

#define myhex hex
#define myout cout
#define myfixed fixed
#define myendl endl
#define  mypres(x) setprecision(x)  

Trick #undef

因为屏蔽<iostream>是通过判断#define的

//'AC'代码
#include <iostream>
#include <iomanip>
#define myendl endl
#define myfixed fixed
#define mypres(n) setprecision(n)
#define myhex hex
#define myout  cout
using namespace std;
#undef _GLIBCXX_IOSTREAM

思路三(误)

上课时一直在想一个思路.然而并没有实现出来..

就是cout来自iostream是继承ostream

于是就可以够着一个类似于cout的ostream,然后一切就可以顺理成章了

然后进一步发现ostream这个居然没有默认构造函数��…

需要这样来声明(来着cplusplus)

// ostream constructor
#include <iostream>     // std::cout, std::ostream, std::ios
#include <fstream>      // std::filebuf

int main () {
  std::filebuf fb;
  fb.open ("test.txt",std::ios::out);
  std::ostream os(&fb);
  os << "Test sentence\n";
  fb.close();
  return 0;
}

就是声明一个filebuf对象,然后给ostream一个它的指针

但是这里留下的疑难是怎么把stdout赋给fb或者os(也就是myout)

如果解决了后就可以用以前诗源大大helloworld系列来实现

//优先加载全局变量
ostream myout(...)//没有无参数构造函数
int f()
{
  ...
}
int k = f();

~欢迎大大交流讨论

另外安利一个搜索链接,里面有谷歌的镜像.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值