Archive

Archive for March, 2010

C++ Primer 学习笔记:标准库类型

March 6th, 2010 leeing No comments

C++ Primer 学习笔记二:标准库类型

1. 有一种情况下,必须总是使用完全限定的标准库名字:在头文件中。因为头文件的内容会被预处理器复制到程序中。用#include包含文件时,相当于头文件中的文本将成为我们编写的文件的一部分。如果在头文件中放置using声明,就相当于每个包含此头文件的程序都放置了同一using声明,不论该程序是否需要using声明。而通常,头文件中只应当定义确实必要的东西。

2. 字符串字面值与标准库中的string并不是同一个类型,这是因为历史的原因及C兼容性。
当进行string对象和字符串字面值混合连接操作时,+ 操作符的左右操作数必须至少有一个是string类型的:

string str = "hello " + "world" // 非法
string str0 = "world";
string str1 = "hello" + ", " + str0 // 非法

3. 从标准输入读取string,将:

  • 读取并忽略开头所有的空白字符(如空格,换行符,制表符)
  • 读取字符直到再次遇到空白字符,读取终止。

例如,如果输入为:’        hello world     ‘,则实际保存的是: ‘hello’
一种不常见的初始化方式为:
string str(n,c):将str初始化为字符 c 的n个副本。

4. string.empty() 将返回bool值,判断是否为空串。

5. string:size_type。因为string::size()返回的是string::size_type类型的值,string类类型和许多其它库类型都定义了一些配套类型,通过这些配套类型,库类型的使用就可以与机器无关,size_type定义为与unsigned类型(unsigned int或者unsigned long)具有相同的含义,而且可以保证足够大的能够存储任意string对象的长度。为了使用由string类型定义的size_type类型,必须加上string::来限定所使用的size_type是由string类定义的。
任何存储string的size操作结果的变量必须为string::size_type类型。特别重要的是,不要把size的返回值赋给一个int变量,这是为了避免溢出现象的发生。
对于vector,则应当使用vector::size_type。
并且,习惯用!=而不是 <来编写循环判断条件,如:

for(vector::size_type ix = 0; ix ! = vec.size(); ++ ix) { }

并且,由于string, vector都是可以动态增长的,因此倾向于在每次循环时测试size的当前值,而不是在进入循环前就存储size值的副本。像size() 这样的小库函数一般定义为内联函数,所以每次循环过程中调用它的运行代价是比较小的。

Read more…

Categories: C++ Tags:

OMNeT++ 的仿真流程

March 6th, 2010 leeing 1 comment

Simulation with OMNeT++

用OMNeT++进行仿真的大致流程如下:

  1. 一个OMNeT++模型是用通过交换信息来通讯的组件(模块)来构建的。模块可以嵌套,也就是说,几个模块可以组成一个复合模块。在创建模型时,你需要将系统映射到一个相互通讯的模块体系中。
  2. 用NED语言定义模型的结构。你可以在OMNet++提供的IDE中以文本或图形化方式来编辑NED文件。
  3. 模型的活动组件(简单模块)需要用C++来编程,当中要使用仿真内核及类库。
  4. 提供一个拥有配置和参数的omnetpp.ini文件给模型,一个配置文件可以用不同的参数来描述若干个仿真过程。
  5. 构建仿真程序并运行它。你可以将代码链接到OMNet++的仿真内核及其提供的一个用户接口:命令行和交互式接口或图形化接口。
  6. 仿真结果将写入输出向量和输出标量文件中。你可以使用IDE中提供的分析工具来进行可视化。结果文件是普通的文本,所以你能用R,Matlab或其它工具来进行绘图。

原文在 >> 这里 <<。

Categories: OMNeT++, 计算机网络 Tags:

OMNet++ 10 分钟教程

March 5th, 2010 leeing 3 comments

OMNet++ in a nutshell



本文适合对网络模拟器有一定了解的读者,阅读本文时,最好同时打开用户手册和API文档以便随时查阅。

1. 在omnetpp.org中提到的仿真模型和框架与OMNet++是什么关系?

OMNet++提供了基本的工具和机制来编写仿真代码,但它本身并不提供任何特定用于计算机网络仿真,系统架构仿真和任意其它领域的组件;具体的仿真是由一些仿真模型和框架如Mobility Framework或INET Framework来支持,这些模型独立于OMNet++开发,并有自己的发布周期。

2. OMNet++提供了什么?

一个C++库,它由仿真内核及一些用来创建仿真组件(简单模块和信息)的工具类(如随机数生成,统计收集,拓扑发现等);组装和配置这些组件的基础设施(NED语言,ini文件);运行时用户接口或仿真环境(TKenv,Cmdenv);一个用来设计,运行和评估仿真的IDE环境;实时仿真的扩展接口;MRIP,并行的分布式仿真,数据库连接等等这些组成。

3. OMNet++的仿真模型是什么样的?

OMNet++提供了一个基于组件的架构,模型是由可重用的组件或模块组成的。模块之间可以通过gates(在其它系统中称为ports,即端口)进行连接,以构成复合模块。每个仿真模型是一个复合模块类型的实例。这一层次(组件和拓扑)由NED文件来处理。例如,一个名为EtherMAC的组件可以用NED来描述:

  //
  // Ethernet CSMA/CD MAC
  //
  simple EtherMAC {
      parameters:
          string address; // others omitted for brevity
      gates:
          input phyIn;    // to physical layer or the network
          output phyOut;  // to physical layer or the network
          input llcIn;    // to EtherLLC or higher layer
          output llcOut;  // to EtherLLC or higher layer
   }

它可以使用在下面的Ethernet station的模型中:

  //
  // Host with an Ethernet interface
  //
  module EtherStation {
      parameters: ...
      gates: ...
          input in;    // for connecting to switch/hub, etc
          output out;
      submodules:
          app: EtherTrafficGen;
          llc: EtherLLC;
          mac: EtherMAC;
      connections:
          app.out --> llc.hlIn;
          app.in < -- llc.hlOut;
          llc.macIn <-- mac.llcOut;           llc.macOout --> mac.llcIn;
          mac.phyIn < -- in;           mac.phyOut --> out;
  }

其中,注释能用来生成文档。简单模块,例如上面的EtherMAC,会与一个C++ 文件关联以提供行为,它是以simple关键字来声明的。复合模块则是用module关键字来声明的,为了仿真一个Ethernet LAN,应该创建一个复合模块EtherLAN并用network关键字来表示它可以通过自身运行。


network EtherLAN {
      ... (submodules of type EtherStation, etc) ...
  }

NED文件可以在IDE中以图形化方式或文件模式编辑。

NED文件只定义了模型的结构(拓扑),其行为和模块参数的某个子集则是开放的,如前面所提到的,行为是通过在简单模块相关联的C++代码来定义的,而在NED文件中没有赋值的模块参数则从ini文件中获取它们的值。

Read more…

Categories: OMNeT++, 计算机网络 Tags:

C++ Primer 学习笔记:变量和类型

March 4th, 2010 leeing No comments

C++ Primer 学习笔记一 :变量和基本类型

1. 在C++ 中要理解“初始化不是赋值”,因为初始化是指创建变量并给它赋初始值,而赋值是擦除对象的当前值并用新值代替。虽然只有在编写非常复杂的类时才能凸显这两种方式的区别,但这也是一个关键的概念,而且直接初始化更灵活而且效率更高。

C++中支持两种初始化的形式:复制初始化和直接初始化:

int ival(1024)  // direct-initialization
int ival = 1024  // copy-initialization

2. 在C++语言中,变量必须且仅能定义一次,而且在使用变量之前必须定义或声明变量。为了让多个文件访问相同的变量,C++区分了声明和定义。
a) 变量的定义用于为变量分配存储空间,还可以为变量指定初始值,在一个程序中,变量有且仅有一个定义。
b) 声明用于向程序表明变量的类型和名字。定义也是声明:当定义变量时我们声明了它的类型和名字,可以通过使用extern关键字声明变量名而不定义它:

extern int i; // declares but does not define i
int i; // declares and defines i

在这里,extern声明不是定义,也不分配存储空间,因为只有定义才分配存储空间。如果声明有初始化,则可以看作是定义:

extern double pi = 3.1416

虽然使用了extern,但是这条语句还是定义了pi,分配并初始化了存储空间,只有当extern声明位于函数外部时,才可以含有初始化式。
c) 任何在多个文件中使用的变量都需要有与定义分离的声明,在这种情况下,一个文件含有变量的定义,使用该变量的其它文件则包含此变量的声明(而不是定义)。
d) 通常把一个对象定义在它首次使用的地方,以提高可读性。放置声明的一个约束是,变量只能在其定义处开始到此声明所在的作用域的结束处才可以访问,必须在使用此变量的最外层作用域里面或之前定义变量。

3. 外部变量extern和const,非const变量默认为extern,而要使用const变量能在其它文件中访问,必须显示地指定它为extern。
即必须在最初就定义为:extern const int bufSize = 512;

4. 引用就是对象的另一个名字,在程序中它的主要用作函数的形式参数。引用是一种复合类型,通过在变量名前加 & 来定义,复合类型是指用其它类型定义的类型。在引用的情况下,每一种引用类型都“关联到”某一其它类型,不能定义引用类型的引用 ,但可以定义其它任何类型的引用。
引用必须用与该引用同类型的对象初始化:

	int ival = 1024;
	int &refVal = ival; // 正确
 	int &refVal2;  // 错误
	int & refVal3 = 10 // 错误

引用只是它绑定的对象的另一个名字,作用在引用上的所有操作事实上都是作用在该引用绑定的对象上,当引用初始化后,只要该引存在,它就保持绑定到初始化时指向的对象,不能将引用绑定到另一个对象。
要理解的一个重要概念是“引用只是对象的另一个名字”。
如果用const 修饰,则表示不能通过引用来修改所绑定的变量的值,而且,将普通的引用绑定到const对象也是不合法的:

const int ival = 1024;
const int &refVal = ival; // 合法,因为对象及引用都是const的
int &ref2 = ival;       // 非法,因为非const变量引用了一个const对象

Const引用可以初始化为不同类型的对象或者初始化为右值,如字面常量。

int i = 42;
const int &r = 42;
const int &r2 = r+i;

同样的初始化对于非const引用却是不合法的,下面解释它的原因:

double dval = 3.14;
const int &ri = dval;

编译器会把这些代码转换为:

int temp = dval;  // 建立一个临时变量,将ri绑定到临时变量。
const int &ri = temp;

即是说:非const引用只能绑定到与该引用同类型的对象,而const引用可以绑定到不同但相关的对象或绑定到右值。

double val = 42.999;
const int &r3 = val;
val = 2;
//r3 = 4; 非法
// 改变后 val = 2 而 r3 = 42

Read more…

Categories: C++, 编程语言 Tags: