C++ 能否成为你新的脚本语言?

开发 后端
第一个我真正喜爱的编程语言是 C。我花了不少时间才找到它:当我还是一个孩子,我就开始在珍贵的ZX Spectrum上使用 Z80 汇编。那些日子是你能够真正掌握你的电脑的时候,你不需要苹果,谷歌,微软或者其他任何人的允许就能写一个程序。

一些背景

***个我真正喜爱的编程语言是 C。我花了不少时间才找到它:当我还是一个孩子,我就开始在珍贵的ZX Spectrum上使用 Z80 汇编。那些日子是你能够真正掌握你的电脑的时候,你不需要苹果,谷歌,微软或者其他任何人的允许就能写一个程序。我在漂亮的128K ZX Spectrum +2上学习了在超出 CPU 寻址空间时对内存块分页。直到我进入大学,我才拥有一台 IBM PC 机 。我玩遍了电子表格,试图修复现存的 Fortran 程序,用土耳其字符给键盘驱动打补丁,还学了点 Pascal 语言。之后,在我就职于土耳其中央银行期间,我又学习了 SQL 和 APL。

[[135397]]

我一直对 C 语言有所耳闻,但我一直没有接触到一款C语言编译器。直到我到康奈尔大学拥有了一个Unix 账号之后,我编译了我人生中的***个 hello.c 文件,不久之后,我有了***台电脑……我在 DOS 分区上安装了 DJGPP 编译器,构建了我人生中***个 Linux 内核(我***个发行版是 Debian),并且开始学习 C 语言。Plauger 的 “Standard C Library” 是我最喜欢的书。

当我开始享受用 C 编程的时候,C++ 已经广泛应用超过十年了。所以,我下一步使用 C++ 看起来是很自然的一步了。

除了……好吧,除了 C++ 是一片混乱。那段时间,所有人都被继承层次深深吸引了,每个人都在编写精心设计的字符串类。大多数硬盘都太慢,不能再有限的时间内编译出可靠的 C++ 库(好吧,我有点夸张了),大部分 CPU 都在试图实例化模板中融化了,大部分人,那些假装 C++ 程序员的 C 程序员们,差点就把 malloc 的返回值给扔了。

在那时,我正忙于试图建立定制化的网络经济实验,看起来 Java 似乎很有优势。至少,它不需要麻烦地拼凑出一个对话框。产生少量的 socket 连接,并且使你的应用编译和运行在多种多样的系统上。当然,AWT 和 Swing 都很丑陋且笨重,但对我的目的来说,那没关系。

但是,仅仅是因为不能在实验室之外运行我的实验(因为在实验室已经配置了所有电脑,java应用程序运行不会有问题)。所以我快速的把 FreeBSD部署到了一台拥有100Mhz奔腾处理器,16Mb内存,在角落里收集灰尘的机器上,并搭建了一个拥有perl模块(mod_perl)的 Apache服务器,然后就能工作了。那就是我爱上Perl的时候。

那份爱完全起源于实用的原因,我并不是认为Perl特别的***,并且那时候我认为包括其他许多语言都不是很***,他们中的每一个都有自己的瑕疵。

Perl总是能减少我必须解决的特别问题的工作的数量,有些是因为语言特性,但大部分是因为 CPAN

举例来说,作为一个 Perl 程序员,解析 HTML 作为 HTML 是一个解决方案。我必须决定,要么就构造整个树, 或者使用流化的方式。在某些情况下,前者是具有优势的,但后者的好处是可以使内存的需求降至***,即使是在这个年代,如果你处理 HTML 文档以兆字节方式还是可以奏效的。不论哪种方式,这些工具都不会在无效的 HTML 上被卡住,并在非 XML 的有效 HTML 上运作良好。

还有,Perl 提供可移植性。如果我不需要操作系统特定的功能,不用任何修改地方,我的 perl 代码就可以运行。

当我写了一些类,并为它们做了封装,也不会有复杂的架构。

C++ 涅槃

在过去的数年,C++如获新生。许多聪明人已经开始意识到须要向C++程序员提供同时涵盖 work of the ISO committee boost的构建模块。

在真实环境下,仍然有90%的菜鸟生成C++程序员就是没有意识到new是一个合法符号的C程序员。在这方面,C++与Perl非常相似:大部分人写过Perl代码的人也没有意识到Perl不是C、Java、Python、shell、Awk或者其他你可以列举的语言。

但是,当你看到新C++标准中的新东西,以及编译器不断实现浙西特性的新闻时,我们无法抑制住内心的兴奋和好奇。

单词计算练习

这是一个简单的练习,使用 C++ 或者 Perl 并且不依赖外部库,所以这是一个很好的起点。

这是 Perl 版本,供您参考:

 

  1. #!/usr/bin/env perl 
  2.  
  3. use strict; 
  4. use warnings; 
  5.  
  6. run(/@ARGV); 
  7.  
  8. sub run { 
  9.     my $argv = shift; 
  10.     my @counts; 
  11.  
  12.     for my $file ( @$argv ) { 
  13.         my $count = -1; 
  14.         eval { 
  15.             $count = word_count($file); 
  16.             1; 
  17.         } or warn "$@"
  18.  
  19.         push @counts, { 
  20.             file => $file, 
  21.             word_count => $count, 
  22.         }; 
  23.     } 
  24.  
  25.     for my $result (@counts) { 
  26.         printf "%s: %d words/n", $result->{file}, $result->{word_count}; 
  27.     } 
  28.  
  29. sub word_count { 
  30.     my $file = shift; 
  31.     my %words; 
  32.  
  33.     open my $fh, '<', $file 
  34.         or die "Cannot open '$file': $!"
  35.  
  36.     while (my $line = <$fh>) { 
  37.         my @words = split ' ', $line; 
  38.         $words{ $_ } += 1 for @words; 
  39.     } 
  40.  
  41.     close $fh; 
  42.  
  43.     my $word_count; 
  44.     $word_count += $_ for values %words; 
  45.     return $word_count; 

而且,这是我***的付出在转化 Perl 到现代风格的 C++ 上面。我没有尝试写特别搞笑的代码:只是和 Perl 一样,我把重点放在写代码上面,使得我感到非常自然,同时确保两个程序都做大致相同的事情。

 

  1. #include <cerrno> 
  2. #include <cstdio> 
  3. #include <cstdlib> 
  4. #include <fstream> 
  5. #include <iostream> 
  6. #include <numeric> 
  7. #include <unordered_map> 
  8. #include <string> 
  9. #include <vector> 
  10.  
  11. using std::accumulate; 
  12. using std::cerr; 
  13. using std::cout; 
  14. using std::endl; 
  15. using std::ifstream; 
  16. using std::make_pair; 
  17. using std::pair; 
  18. using std::strerror; 
  19. using std::string; 
  20. using std::unordered_map; 
  21. using std::vector; 
  22.  
  23. int word_count(const char *const file) noexcept(false); 
  24.  
  25. int main(int argc, char *argv[]) { 
  26.     vector< pair<string, int> > counts {}; 
  27.  
  28.     for (auto i = 1; i < argc; i += 1) { 
  29.         try { 
  30.             counts.push_back(make_pair(argv[i], word_count(argv[i]))); 
  31.         } catch (const string& e) { 
  32.             cerr << e << endl; 
  33.             counts.push_back(make_pair(argv[i], -1)); 
  34.         } 
  35.     } 
  36.  
  37.     for (auto& result : counts) { 
  38.         cout << result.first << ": " << result.second << " words" << endl; 
  39.     } 
  40.  
  41.     return 0; 
  42.  
  43. int 
  44. word_count(const char *const file) noexcept(false) { 
  45.     errno = 0; 
  46.     ifstream fp(file); 
  47.     { 
  48.         // Does fp.fail() preserve errno? 
  49.         int save_errno = errno; 
  50.         if (fp.fail()) { 
  51.             throw("Cannot open '" + string(file) + "': " + strerror(save_errno)); 
  52.         } 
  53.     } 
  54.  
  55.     unordered_map<string, int> word_count {}; 
  56.     string word; 
  57.  
  58.     while (fp >> word) { 
  59.         word_count[word] += 1; 
  60.     } 
  61.  
  62.     fp.close(); 
  63.  
  64.     return accumulate( 
  65.         word_count.cbegin(), 
  66.         word_count.cend(), 
  67.         0, 
  68.         [](int sum, auto& el) { return sum += el.second; } 
  69.     ); 

20 行代码用于 #include 和 using 声明可能看起来有点多,但是我抬眼 using namespace std,也讨厌不断地输入 std::… 更多的是因为我喜欢较短的代码行。

首先要注意的是没有看得见的显式的内存分配。容器集装箱管理自己的内存。

第二,这是一个大问题:我们有自动导入(autovivification)!

 

  1. unordered_map<string, int> word_count {}; 
  2. string word; 
  3.  
  4. while (fp >> word) { 
  5.     word_count[word] += 1; 

第三,我们有 lambda 表达式:

  1. return accumulate( 
  2.     word_count.cbegin(), 
  3.     word_count.cend(), 
  4.     0, 
  5.     [](int sum, auto& el) { return sum += el.second; } 
  6. ); 

在这背后,accumulate 将内部变量初始化为 0,并调用一个匿名函数,其***一个参数指定为当前值,以及word_count的下一个元素。

现在,我不得不承认,我不知道这些特性是如何实现的,但是 Microsoft Visual C++ 2015 RC 成功运行了,微软似乎终于赶上了在该领域的***发展。

现在的情况

然而,一切都不乐观。尽管 boost libraries 填补了许多空白,而且标准库提供了令人印象深刻的构件,但是也很难战胜 Perl 和 CPAN 结合带来的那种编写可在任何地方***运行的可移植代码的便利性。

例如,我能找到一个平台无关的库,可以让我在不需要 Excel 的情况下解析或创建 Excel 文件吗?这个库能够用 clang、g++ 和 cl 轻易地编译出来吗?好像不太可能。

我真的非常感谢标准委员会的人们的辛勤工作,和那些开发编译器,众多库的人们。它们让我不必在编写 C++ 程序时辛苦的思考。

这让我在真正控制我的计算机时还能感觉舒适。

在这里,我真的非常感谢。

你可以在/r/cpp评论本文。

责任编辑:王雪燕 来源: oschina
相关推荐

2009-06-10 08:41:15

Linux脚本语言

2011-08-16 10:03:45

Groovy编程语言Web

2011-08-22 18:00:53

Lua语言

2022-07-04 08:35:57

Vim 9.0Linux脚本语言

2010-02-24 14:04:32

Python脚本语言

2012-07-16 11:23:18

LinuxWindows脚本语言

2010-02-26 09:33:51

Python脚本

2011-08-25 10:40:21

Lua游戏

2011-08-22 16:59:28

Lua

2011-08-25 11:02:04

2023-01-09 16:44:53

编程语言C++C

2011-07-05 10:39:55

JVM

2011-05-07 08:35:22

PHP

2011-06-22 10:14:49

JVM

2011-07-06 16:54:44

ASP

2010-02-26 13:03:31

Python脚本语言

2011-09-07 09:51:27

Javascript

2011-08-22 18:08:09

Lua脚本

2010-03-17 17:06:10

python脚本语言

2021-08-23 15:05:21

PyretJavaScript编程
点赞
收藏

51CTO技术栈公众号