欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

C++测试题简评一下

C++测试题简评一下

C++测试题简评一下
前天我发了一道测试题
  http://bbs.pediy.com/showthread.php?t=126118
收到了三份答案,都写得很差
* 当我们说要解析一下文本文件时,通常这个文件是不大的,你第一感觉就应该是把整个文件都读到内存,然后用 char c = *p++ 之类代码就可以简单处理了。或者用 CreateFileMapping 转化成可以直接操作的内存。而这几份答案都是直接文件操作,满篇的 fread fgetc fseek ftell 看起来很乱。
* 要求中,有一个函数IsLineEnd,要得到当前是不是在一个行尾。既然是检查什么东西是不是,那么这个函数一定应该是const的,不能改变任何状态。你用fgetc得到下一个字母,发现不是行尾,这取出来的一个字母怎么还回去?即使能还回去这代码也是不好的。全读出来后用 *p++ 就不存在这个问题了。
* 要求中,多次提到要跳过空白,你应该有一个函数SkipWhiteSpace,而不要满篇代码,到处都在比较空格,很乱
* 重点戏 GetOneWord,因为需要考虑三种情况
  * 跳过开头的空白
  * 遇非单词字符要停下来,非单词字符有多种可能
  * 以引号开头要特殊处理
于是初学者就乱了方寸,不知道怎么写了,搞得代码极乱。
这里为什么我不提 \ 的行结束这种情况呢?其实可以把 \ 当作是一个空格,是个单词结束符就可以了。这个符号仅仅是 IsLineEnd 和 SkipLineEnd 要考虑的,并没有增加 GetOneWord 的复杂度。
优秀的程序员总是能把复杂的事情条理化。既然GetOneWord需要跳过开头的空白,那么在函数开始调用一下 SkipWhiteSpace 就解决了。这就少了一种情况。
以引号开头需要特殊处理,那么接下来判断一下第一个字符,如果是引号,就转到另一段例程,找到下一个引号就可以return 了
总之,函数的流程应该是这样的:
  if (IsLineEnd) return;
  SkipWhiteSpace();
  if (*p = '\"')
  {
    ...;
    return;
  }
  while (IsWordChar(*p))
  {
    ...;
    p++;
  }
整个流程清晰明了。如果
  * 你不是用*p而是用fread或fgetc来得到下一个字母,
  * 你没有用 SkipWhiteSpace 来跳过前头空白,而是到处比较,
  * 你用一个flag来表示是在单词中还是单词前,还是单词后,
  * 你没有把引号开头的情况独立处理,而是用一个flag来区分,
那么,每一种情况都会让这个简单的函数变得复杂。如果这些错误你都犯了,这个函数会复杂得不堪入目,一个小时也看不懂,而且极可能有BUG。
GetOneWord的原型定义,可能是
  void GetOneWord(OUT stl:string & s);
  bool GetOneWord(OUT char s[]);
  CString GetOneWord();
等等。如果你写成 char * GetOneWord() 那是不好的。
当你拿到一个模块工作任务时,你应该安静地完成。你不能因为文件打开失败就
  cout << "file open error";
你怎么知道我有cout ? 你怎么知道我是一个命令行console的工程而不是GUI甚至驱动?当你要失败时,你只能return false,或者抛出异常。
实际应用中,我们还考虑了以下这些情况,
  * 单词中出现\
  * 单词中出现引号
  * 引号中出现\换行
  * 引号不配对
  * 自动支持多种格式的文本文件unicode,utf-8,ansi

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功