Srilm 阅读文档8

取自 自然语言处理百科

跳转到: 导航, 搜索

Count.h Count.cc

文档作者:jianzhu

创立时间:08.09.10


1、概述


这两个文件主要定义了一组将字符串转换为整数或将整数转化为字符串的函数。同时定义了一组用于读写整数和浮点数的函数。


2、函数功能解释


a) 将整数转化为字符串

<src>
0  inline const char *
1  countToString(unsigned count);
2
3  inline const char *
4  countToString(int count);
5
6  inline const char *
7  countToString(long count);
8
9  inline const char *
10 countToString(unsigned long count);
11
12 inline const char *
13 countToString(unsigned long long count);
14
15 inline const char *
16 countToString(XCount count);
17
18 template <class CountT>
19 inline const char *
20 countToString(CountT count);
</src>
   功能:以上一组函数定义了将不同类型的整数转换
   为字符串的功能。
  
   细解:以上各函数均通过调用sprintf函数将整数输出
   到全局的字符串buffer中,并返回该buffer达到了转换
   的目的;

b) 将字符串转化为整数

<src>
0  inline Boolean
1  stringToCount(const char *str, unsigned int &count);
2 
3  inline Boolean
4  stringToCount(const char *str, int &count);
5
6  inline Boolean
7  stringToCount(const char *str, unsigned short &count);
8
9  inline Boolean
10 stringToCount(const char *str, unsigned long &count);
11
12 inline Boolean
13 stringToCount(const char *str, unsigned long long &count);
14
15 inline Boolean
16 stringToCount(const char *str, long &count);
17
18 inline Boolean
19 stringToCount(const char *str, XCount &count);
20
21 template <class CountT>
22 static inline Boolean
23 stringToCount(const char *str, CountT &count);
</src>
   功能:以上一组函数定义了将字符串转换为不同类型的整数的功能。
  
   细解:以上各函数均通过调用sscanf函数从字符串中读出整数,并将其
   保存到count中;

c) 将unsigned long long类型的整数写入到文件中的函数

<src>
0  unsigned
1  writeBinaryCount(FILE *fp, unsigned long long count, unsigned minBytes)
2  {
3    if (minBytes <= sizeof(short) && count < isLongBit) {
4      short int scount = count;
5
6      byteSwap(&scount, sizeof(scount));
7      fwrite(&scount, sizeof(scount), 1, fp);
8      return sizeof(scount);
9    } else if (minBytes <= sizeof(int) && count < isLongLongBit) {
10     unsigned int lcount = count;
11     lcount |= (unsigned int)isLongBit << (sizeof(short)*NBBY);
12
13     byteSwap(&lcount, sizeof(lcount));
14     fwrite(&lcount, sizeof(lcount), 1, fp);
15     return sizeof(lcount);
16   } else if (count < isTooLongBit) {
17     unsigned int lcount = (count >> sizeof(int)*NBBY) |
19       ((unsigned int)isLongBit << (sizeof(short)*NBBY))|
20       isLongLongBit;
21
22     byteSwap(&lcount, sizeof(lcount));
23     fwrite(&lcount, sizeof(lcount), 1, fp);
24  
25     lcount = (unsigned int)count;
26     byteSwap(&lcount, sizeof(lcount));
27     fwrite(&lcount, sizeof(lcount), 1, fp);
28     return 2*sizeof(lcount);
29   } else {
30     cerr << "writeBinaryCount: count " << count << " is too large\n";
31     return 0;
32   }
33 }
</src>
   功能:用于将unsigned long long类型的整数以二进制方式写入到文件中。主要分三种方式
   写。当整数小于isLongBit时,将其以short类型写入到文件中;否则当整数小于isLongLongBit
   时,将其以int类型写入到文件中;否则当整数小于isTooLongBit时,将其以long long类型
   写入到文件中。
  
   细解:第3-9行用于处理当count小于isLongBit时的写入。此时直接将count值赋给short类型的
   临时变量scount,然后通过调用byteSwap函数将该变量转换为大字节序(big-endian),转换
   结束后将scount以二进制方式写入到文件中。
   第9-16行用于处理当count大于isLongBit而小于isLongLongBit时的写入。此时直接将count值赋
   给unsigned类型的变量lcount,同时将lcount的第32位置为1,然后通过调用byteSwap函数将该变
   量转换为大字节序(big-endian),转换结束后将lcount以二进制方式写入到文件中。
   第16-29行用于处理当count大于isLongLongBit而小于isTooLongBit时的写入。此时首先获取count
   中的高sizeof(unsigned long long)*8 - sizeof(int)*8位的值,同时将其第32和31位设为1,并
   保存到unsigned int类型的变量lcount中。然后通过调用byteSwap函数将该变量转换为大字节序(
   big-endian),转换结束后将lcount以二进制方式写入到文件中。然后获取count的低sizeof(int)*8
   位的数值,并将其保存到lcount中,同时通过调用byteSwap函数将该变量转换为大字节序(big-endi
   an),转换结束后将lcount以二进制方式写入到文件中。
  
   注:这里统一转换为bid-endian的原因是,写入的时候先写低字节,而big-endian高位处于低字节序,
   因此从文件中部分读出的时候,可以先读出高位部分,然后通过判断标志位来确定写入的数值类型。
  

byteSwap函数

   <src>
   0  static inline
 1  void byteSwap(void *data, unsigned size)
 2  {
 3    if (isLittleEndian()) {
 4      assert(size <= sizeof(double));
 5
 6      char byteArray[sizeof(double)];
 7
 8      for (unsigned i = 0; i < size; i ++) {
 9        byteArray[i] = ((char *)data)[size - i - 1];
 10     }
 11     memcpy(data, byteArray, size);
 12   }
 13 }
   </src>
       功能:第3行调用isLittleEndian函数判断当前系统是否是little-endian字节序,
       若是该字节序,则通过第8-11行的字节序反转,将data值转换为big-endian字节序。
       否则不做任何操作。
 

isLittleEndian函数

  <src>
  0  static inline
 1  Boolean isLittleEndian()
 2  {
 3    static Boolean haveEndianness = false;
 4    static Boolean endianIsLittle;
 5
 6    if (!haveEndianness) {
 7      union {
 8       char c[2];
 9       short i;
 10      } data;
  11
 12      data.i = 1;
 13
 14      endianIsLittle = (data.c[0] != 0);
 15      haveEndianness = true;
 16    }
 17
 18    return endianIsLittle;
 19  }
  </src>
      功能:第3-4行定义了两个静态变量用于记录当前函数是否已经被调用过。若被调用
      过则haveEndianness为true,直接执行第18行返回。否则执行第6-17行。
      第7-10行定义了一个union类型的对象,其中包含了两个变量i和c其中c为char类型的
      数组,这两个变量共享一块内存存储区。
      第12行将i值设为1。
      第14行通过c引用刚才保存到i中的第0个字节,如当前机器为little-endian字节序,则
      c[0]不为0,否则c[0]为0。同时将判断结果保存到endianIsLittle中。
      第15行将haveEndianness设为true。
      第18行返回endianIsLittle值。
     
      注:如果处理器体系结构支持big-endian字节序,最小的有意义的字节(least significant
       byte-LSB)位置保存最高的字节。little-endian字节序和big-endian字节序正好相反,最
       小的有意义的字节位置保存最低的字节。
  

c) 从文件中读出unsigned long long类型的整数的函数

<src>
0  unsigned
1  readBinaryCount(FILE *fp, unsigned long long &count)
2  {
3    unsigned short scount;
4
5    if (fread(&scount, sizeof(scount), 1, fp) != 1) {
6      return 0;
7    } else {
8      byteSwap(&scount, sizeof(scount));
9
10     if (!(scount & isLongBit)) {
11       // short count
12       count = scount;
13       return sizeof(scount);
14     } else {
15       // long or long long count
16       unsigned int lcount = (unsigned)(scount & ~isLongBit)
17                  << sizeof(short)*NBBY;
18 
19       // read second half of long count
20       if (fread(&scount, sizeof(scount), 1, fp) != 1) {
21         cerr << "readBinaryCount: incomplete long count\n";
22         return 0;
23       } else {
24         byteSwap(&scount, sizeof(scount));
25  
26         // assemble long count from two shorts
27         lcount |= scount;
28  
29         if (!(lcount & isLongLongBit)) {
30           // long count
31           count = lcount;
32           return sizeof(lcount);
33         } else {
34           // long long count
35           count = (unsigned long long)(lcount & ~isLongLongBit)
36               << sizeof(unsigned)*NBBY;
37
38           // read second half of long count
39           if (fread(&lcount, sizeof(lcount), 1, fp) != 1) {
40             cerr << "readBinaryCount: incomplete long long count\n";
41             return 0;
42           } else {
43             byteSwap(&lcount, sizeof(lcount));
44 
45             // assemble long long count from two longs
46             count |= lcount;
47             return 2*sizeof(lcount);
48           }
49         }
50       }
51     }
52   }
53 }
</src>
   功能:从文件中正确读取出unsigned long long类型的值。
  
   细解:第5-7行从文件中读取出unsigned short类型的整数,并在读取失败后返回0。
   第8行调用byteSwap函数,首先将该整数转换为写入之前的字节序。
   第10-14行判断当前scount值是否小于isLongBit,若小于该值,则说明写入时的值
   为short类型,于是可以直接将scount赋给count,并返回读出的字节数。
   第14-51行处理当scount值大于isLongBit的情况,这时写入的值存在两种类型:
   unsigned int类型、unsigned long long类型。
   第16-17行首先将scount的 (sizeof(short)*NBBY-1)对应的标志位清除,然后左移
   sizeof(short)*NBBY位,并将该值赋给lcount。然后从文件中读取出第二段的unsigned
   short值。
   第24行调用byteSwap将scount转换为写入之前的字节序。
   第27行将scount或到lcount的低sizeof(short)*NBBY位中。
   第29-33行处理当lcount的第(unsigned int)1 << (sizeof(int)*NBBY-2)位为0的情况,
   这时写入文件的值为unsigned int类型。此时直接将lcount赋给count,并返回读出的
   字节数。
   第33-49行处理当写入的文件的数值类型为unsigned long long类型的情况。
   此时首先将标志位(unsigned int)1 << (sizeof(int)*NBBY-2)清零,然后左移sizeof
   (unsigned)*NBBY位,为保存第二段unsigned类型数值做准备,并将结果赋给count。然后
   从文件中读出第二段unsigned int类型的值,并将其或到count的低(unsigned int)1 <<
   (sizeof(int)*NBBY-2)位中,然后返回读出的字节数。

知识点:


字节序

   字节序是处理器体系结构的一个特性,用来描述字节在较大的数据类型(如整型)内部
是如何排序的。在同一台计算机上进程之间交流时,由于字节序一样,所以不会引起错误。 
但如果进程之间的交流发生在两台字节序不同的计算机之间,就有可能会引发错误。
   如果处理器体系结构支持big-endian字节序,最小的有意义的字节(least significant
byte-LSB)位置保存最高的字节。little-endian字节序和big-endian字节序正好相反,最小 
的有意义的字节位置保存最低的字节。
   如果我们做如下操作
   int num = 0x04030201;
   char* cp = (char*)&num; 
则在little-endian处理器体系结构中,cp[0]将代表LSB并且为1,cp[3]代表MSB并且为4;在
big-endian处理器体系结构中,cp[0]将代表MSB并且为4,cp[3]代表LSB并且为1。
   因此,当两台电脑之间的进程发生交流时,需要判断当前电脑字节序,并在约定好以一
种字节序进行交流。
   通过观察上面写数据和读数据的过程,可以发现字节序转换可能存在如下情况:
   1) 同一种处理器体系结构
      big-endian    ---- big-endian      (W) (R) (不发生字节变序)
      little-endian ---- little-endian   (W) (R) (读写过程均发生字节序变换)
   2) 不同处理器体系结构
      big-endian    ---- little-endian   (W) (R) (读时发生字节序变换)
      little-endian ---- big-endian      (W) (R) (写时发生字节序变换)


转自:http://blog.chinaunix.net/u1/58264/showart_1333611.html

个人工具
工具箱