C_and_CPP 版 (精华区)

发信人: seaboy (浪小), 信区: C_and_CPP
标  题: 新的起点,第二部分 
发信站: 哈工大紫丁香 (2003年06月21日08:51:31 星期六), 站内信件

新的起点,第二部分 
amature 翻译 

-------------------------------------------------------------------------------
-

控制权的改变来得非常突然。 

吉尔伯一直在监视舞厅的大门,我们已经听到几阵撞门声。他们通过两边的大门攻了过来
,当我们被俘时大部分还在睡梦中。 

我被巨大的重击声和在两个相对的大门之间移动的强烈灯光所惊醒。很明显,敌人想进行
突然袭击。吉尔伯的命令再清楚不过了-遇到攻击的时候,抓上我们的行李和外星文物,
跳入森林大门,这也正是我们想做的。 

Glib和他的几个官员就是这样做的,他们迅速地到另一个世界里并从我们的视线中消失吉
尔伯和几个官员跳了进去,旋即消失于我们的视野当中。当大门卷起、全副武装的战士高
喊“不许动”,从两边向我们冲过来时,我们中的大部分人正拼命地奔向金属球门。我在
珍妮前面,靠近大门,正犹豫不决着....这时敌人的子弹飞了过来,我赶快跳了进去。 

当我穿过那扇大门时,我没有感觉到什么不寻常,但是我衣服外面的温度计显示温度已跃
升到了28°C。我向后快速地扫视了一下-珍妮仍然在舞厅里,包裹扔到地上,双手高举着
。我没有等着继续看她怎么被捕俘,赶紧跟随着Glib的随行人员,匆忙地走进了新世界的
丛林中。 


-------------------------------------------------------------------------------
-

管理上的变化来得很突然。 

由于我们公司和我们的买主都不是上市交易的,董事会能够悄悄地谈交易,而且对员工也
保密,这种状况一直持续到实际合并日的前几周。因此在新年后不久我们第一次听到了“
合并”的声明(用这个词来代替“收购”或“出售”显得体面一些,因为我们公司无论规
模和状况均不如我们的买主)而且在两个星期内我们发现自己已经替新的老板工作了。 

彼得.威廉姆斯给人的第一印象像是个通情达理的人,尽管作为一个技术队伍的管理者他有
点沉迷于体育。随着时间的过去,我有更多的机会来完善对他的看法,而且在他手下工作
我也获得了经验。我非常赞同彼得的第一把火,或者说是没什么动作:他保留了我们整个
队伍,而且不来干预我们的工作。大家对这个安排非常满意,除了鲍勃,他以为自已这次
能获得提升。 

一些紧急任务使我从低优先级的内部建库工作中脱离出来(不是说内部库不重要而是说指
派给我的每一个任务都不重要,因为我刚刚开始做)。等我再次有喘息的机会时,我回到
了刚写一半的库代码。我做的部分只需满足两个需求:需求247要求是“一个叫做ConvertB
ase的函数,它带有一个string参数,表示一个以N为基数的数字string参数,功能是将它
转换为一个string,这个string 表示以M为基数的相同的数字”。Guru告诉我需求314是“
一种从文本流中读和写任意基数的数字的方法”。在这样的指导下,我希望可以用后者来
实现前者而避免多余的工作,我写了如下的代码: 

string ConvertBase( size_t base1, size_t base2,
                    const string& src )
{
  stringstream s1( src );
  long value;
  if( !( s1 >> Num( base1, value )).eof() || 
      !( s1 >> std::ws ).eof() )
    throw logic_error( "src is not a valid number" );
  stringstream s2;
  if( !( s2 << Num( base2, value ) ) )
    throw logic_error( "unexpected error emitting "
                       "converted number" );
  return s2.str();
}

这似乎是用来实现需求247的,虽然它要依赖于需求314的Num,而且要等我完成了Num 这才
能起作用。迄今为止,我只有一个简单的测试例,用一个接到一个Num桩模块来通过编译,
并且当我考虑它时,我加了一个检查条件把基数限制在一个合理的范围内。 

class Num
{
public:
  Num( size_t base, long& value )
  : base_(base), value_(value)
  {
    if( base < 1 || base > 36 )
      throw logic_error( "base must be from "
                         "1 to 36" );
  }
  size_t Base() const { return base_;  }
  long& Value() { return value_; }
  long  Value() const { return value_; } 
private:
  size_t base_;
  long& value_;
};
istream& operator>>( istream& i, Num& n )
{
  string s;
  i >> s;
  n.Value() = 255; // todo: really convert input
     // to n's base_
  return i;
}
ostream& operator<<( ostream& o, const Num& /* n */ )
{
  return o << "FF"; // todo: really output
                    //n.value_ in n.base_
}
int main()
{
  string result = ConvertBase( 10, 16, "255" );
  cout << result << endl;
  return result == "FF" ? 0 : 1;
}

接下来,我知道我必须通过为Num s真正实现<<和>>来完成314。在我准备开始编码时,我
发现在已有的操作符<<和>>上有一个严重的缺陷。我的身体向屏幕靠近,正准备开始修改
时,“啪”的一声,一本书合拢的声音向我提示Guru的存在。 

"鲍勃在附近吗?"我低声问道。 

“不在,我们尽管说吧”,她说着并在我的客椅上座了下来。她用手指着屏幕,继续说:
“到底是什么使你着魔似地做那件事?” 

“是的,我知道,我正在研究。我已经好几个星期没有碰它们了,而现在最明显不过的事
情摆在了我面前。” 

“哈,那么自个想办法。” 

我指着<<和>>这两个讨厌的操作符:“我有意无意地简单实现它们,只用于基本的char以
及char_traits<char>流。” 

她微笑着站起来,补充道:“很好,继续,徒弟,” 这时我们都听到了鲍勃呷咖啡的声音
传了过来。 

“哦,那是?”我问道,“不再演说,没有道德演说,没有编程课?” 

她的眉毛令人开心地向上弯了一下:“那么为什么会这样呢?你不用我帮忙就发现了你作
品中的严重缺陷,而现在你需要时间来修正它。在你完成之前用不着我说什么吧?”没有
等我进一步的答复,她轻轻微笑着,打开她的书本,静静地走了出去。 

既然她不给我好好上课就放心让我自己去干,我猜想自己肯定有了不小进步。因此我重新
回到了那段代码。首先来修正函数原型: 

template<class CharT, class Traits>
basic_istream<CharT, Traits>& operator>>
  ( basic_istream<CharT, Traits>& i, Num& n );
template<class CharT, class Traits>
basic_ostream<CharT, Traits>& operator<<
  ( basic_ostream<CharT, Traits>& o, const Num& n );

这更好一些。我目视检查,这次它看起来是对了。接下来,我决定让输入变成最容易的,
我熟练地开始了: 

template<class CharT, class Traits>
basic_istream<CharT, Traits>& operator>>
  ( basic_istream<CharT, Traits>& input, Num& n )
{
  locale loc = input.getloc();
  CharT c;

当我避免了读简单的char和忘记本地数据的类似缺陷时,我对自己的镇定自若感到庆贺。
接着我想起前导空白字符可以被有选择地略过,所以我继续完善: 

  // If we should, then skip leading
  // whitespace, if any.
  if( input.flags() & ios_base::skipws )
  {
    do
    {
      input >> c;
    }
    while( isspace( c, loc ) );
  }
  // Handle sign, if any.
  int sign = ( c == '-' ? —1 : 1 );
  if( c == '-' || c == '+' )
    input >> c;

到此,很好。当真正开始处理数字时,逻辑很简单,而且主要的工作就是决定一个合理的
方法来对数字进行解码。不管怎样,虽然我还是新手,但我最起码会认识到我不能仅仅假
设数字和(或)字母是相邻的并且和字符集中的顺序一样(虽然每个组中的元素是相邻的
并在ASCII中是有序的)。暂时地,我决定用一个辅助结构,它对于用 std::find()来查找
是很合适的: 

  CharT digits[]
    = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  size_t numDigits 
    = sizeof( digits ) / sizeof( digits[0] );
  n.Value() = 0;
  while( input.good() )
  {
    int index = find(digits, digits + numDigits,
                     toupper (c, loc) )
            -digits;
    if( index < 0 || index > n.Base() )
    {
      break;
    }
    n.Value() = n.Value() * n.Base() + index;
    input >> c;
  }
  if ( !input.eof() )
    input.putback( c );
  n.Value() *= sign;
  return input;
}

对输入来说,这显得非常合理了,现在只剩下输出了。输出更容易些,部分原因是我做了
一个深谋远虑的决定:不提供输出像 showpos 和 uppercase 的格式化标志;这些可以留
到下一个需求去做,如果它真的很需要的话- 

我偷偷地从侧面扫视,以防Guru已经靠近并猛扑过来,抗议我必须支持标准流的所有标志
。四周很暗(正是一年中白天最短的时候),且非常寂静,Guru并没有出现。我等了一会
,还是没什么动静,便心满意足地思绪返回到代码中。 

很好,我自言自语,格式化标志的问题我就跳过算了。如果导师不喜欢它,在我提交后她
可以抗议,我将在代码的2.0版本中做更加完全的工作。如果温迪不喜欢它,我将尽力为我
的方式辩解,我会说我们还不知道这是否是一个需求,那么为什么要没必要地将代码复杂
化?如果鲍勃不喜欢它,他可以一头跳到湖里,特别是在一年中的这个时候。 

因此我的在一个实际的插入操作符上的代码如下面所示: 

template<class CharT, class Traits>
basic_ostream<CharT, Traits>& operator<<
  ( basic_ostream<CharT, Traits>& o, const Num& n )
{
  long value = n.Value();
  basic_string<CharT, Traits> s;
  CharT digits []
    = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  basic_string<CharT, Traits>::size_type start=0;
  do
  {
    s.insert( start, 1, 
              digits[ value % n.Base() ] );
    value /= n.Base();
  }
  while( value > 0 );
  if( n.Value() < 0 )
    s.insert( start, 1, '-' );
  return o << s;
}

我开始通过一个更加广泛的测试例集合来运行这段代码,我准备在我的正常项目工作量内
解决下一个任务。我们的新管理者很善于“时间管理,”这好像是由细化我们的任务列表
来组成的。我想知道那是怎么达到效果的。 

幸运的时,我在小组中领先。或许今天我可以早点离开。 


-------------------------------------------------------------------------------
-

幸运的是,我们现在发现自己所在的世界是非常好客的-因为这很明显,如果只是从更加
巨大的地心引力,这是一个和我们从Sol的小孩子中知道的任何一个都不同的世界。是的,
非常之好客:当少量的配给用完后,我们发现当地的植物亦可食用,而且我们没有立即碰
到任何本地居民,或者更准确地说是他们没有碰到我们。 

吉尔伯成了当地凶猛动物的牺牲品。几天后,我们安葬了他并设置了岗哨监视这些不友好
的五腿食肉动物,我们称它们为“大笨蛋”,因为跟卡通角色有几分相似之处。达.罗萨成
了我们这个小队的头,他制定了一个对那些文物更加严格的测试计划,看看能否用作武器
。 

我担心着珍妮。 

--
欢迎到C_and_CPP版讨论相关问题。

※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.239.80]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:2.816毫秒