你可以使用这一节的函式来执行字串和阵列内容的比较,而且为了检查字串的相等,这些函式也用做排序操作函式,见 Searching and Sorting,有一个例子。

[adsense][/adsense]

不像C语言里多数的比较运算,假如字串不相等,字串的比较函式会传回非零值,这个表示值说明不相同的字串里第一个字元的相对顺序:负值表示第一个字串”小于”第二个字串,而正值表示第一个字串是 “较大的”。

最常使用的函式只是检查相等,照规范使用这样的表示式 ‘! strcmp (s1, s2)’。

这些函式都宣告在标头档 string.h中。

— 函式: int memcmp (const void *a1, const void *a2, size_t size)

函式 memcmp 比较 a1 跟 a2 记忆体前面 size 个位元组,传回值跟第一对不同的字元的差异有相同的符号(以unsigned char 物件表示,然后转成 int)。

假如这两个记忆体内容相同时, memcmp 传回0。

— 函式: int wmemcmp (const wchar_t *a1, const wchar_t *a2, size_t size)

函式 wmemcmp 比较 a1 跟 a2 前面 size 个宽字元,传回值小于零或大于零取决于 a1 第一个不同的宽字元小于或大于相对应的 a2 字元。

假如这两个记忆体内容相同时, wmemcmp 传回0。

对任意阵列来说, memcmp 函式在测试相等时相当有用,在阵列的内容上以逐字元顺序而非位元组做比较通常比较没有意义,例如,在以浮点数组成的位元组做逐字元的比较是不太可能告诉你你任何关于浮点数的值之间的关系。

wmemcmp 真的只有在型态 wchar_t 的阵列比较才有用,因为函式一次以 sizeof (wchar_t) 位元组来检查,而位元组的数目取决于作业系统。

你也应该小心使用 memcmp 来比较含有“holes”的物件,像是新增到结构物件的不明确位置的区块(padding)、在同构(unions)结尾的空间,以及长度小于配置的大小时的字串结尾多余的字元,这些 “holes” 的内容是不确定的,而且在执行逐位元比较时会有奇怪的状况发生,为了得到可预期的结果,执行明确的组件比较。

例如,给定一个结构型态定义像:

     struct foo
       {
         unsigned char tag;
         union
           {
             double f;
             long i;
             char *p;
           } value;
       };

你最好写一个特制的比较函式来比较 struct foo 物件而不是用 memcmp 来比较他们。

— 函式: int strcmp (const char *s1, const char *s2)

strcmp 函式比较字串 s1 跟 s2,传回一个跟第一对不同字元差异的符号值(以 unsigned char 物件表示,然后转成 int)。

假如两个字串相同,strcmp 传回0。

使用 strcmp 排序的结果就是假如 s1 原来是 s2一部分的字串,那么 s1 会被认为 “小于” s2

strcmp 不会考虑字串被写入的语言排序规范,要那样做必须使用 strcoll。

— 函式: int wcscmp (const wchar_t *ws1, const wchar_t *ws2)

wcscmp 函式比较宽字元字串 ws1 跟 ws2,传回值小于或大于零取决于第一个不同的宽字元是 ws1 小于或大于相对应的 ws2 字元。

假如两个字串相同, wcscmp 传回0。

使用 wcscmp 排序的结果就是假如 ws1 原来是 ws2 一部分的字串,那么 ws1 会被认为 “小于” ws2

wcscmp 不会考虑字串被写入的语言排序规范,要那样做必须使用 wcscoll。

— 函式: int strcasecmp (const char *s1, const char *s2)

这函式像 strcmp,除了大小写会忽略外,大小写字元的关系如何由目前选择的语系决定,在标准的 "C" 语系中字元 A 跟 a 不一样,但是在把这些字元当成是字母的一部份的语系里,他们是一样的。

strcasecmp 是从 BSD 衍生出来的。

— 函式: int wcscasecmp (const wchar_t *ws1, const wchar_t *ws2)

这函式像 wcscmp,除了大小写的差异会忽略外,大小写字元的关系如何由目前选择的语系来决定,在标准的 "C" 语系中字元 A 和 a 不一样,但是在把这些字元当成是字母的一部份的语系里,他们是一样的。

wcscasecmp 是 GNU 的扩充函式。

— 函式: int strncmp (const char *s1, const char *s2, size_t size)

这函式类似 strcmp,除了不超过 size 个的字元被比较之外,换句话说,假如两个字串前面 size 个字元是一样的话,传回值是零。

— 函式: int wcsncmp (const wchar_t *ws1, const wchar_t *ws2, size_t size)

这函式类似 wcscmp,除了不超过 size 个的宽字元比较之外,换句话说,假如两个字串前面 size 个宽字元是一样的话,传回值是零。

— 函式: int strncasecmp (const char *s1, const char *s2, size_t n)

这函式像 strncmp,除了大小写会被忽略之外,像 strcasecmp,它也是取决于语系来决定大小写字元的关系。

strncasecmp 是 GNU 的扩充函式。

— 函式: int wcsncasecmp (const wchar_t *ws1, const wchar_t *s2, size_t n)

这函式像 wcsncmp,除了大小写会被忽略之外,像 wcscasecmp,它也是取决于语系来决定大小写字元的关系。

wcsncasecmp 是 GNU 的扩充函式。

这里有一些例子显示 strcmp 和 strncmp的使用(相同的例子可以建构于宽字元的函式)这些范例假设使用 ASCII 字元集,(假如改用其他的字元集–如 EBCDIC,那么字型会有不同数值码,传回的值跟顺序也会不同。)

     strcmp ("hello", "hello")
         ⇒ 0    /* These two strings are the same. */
     strcmp ("hello", "Hello")
         ⇒ 32   /* Comparisons are case-sensitive. */
     strcmp ("hello", "world")
         ⇒ -15  /* The character 'h' comes before 'w'. */
     strcmp ("hello", "hello, world")
         ⇒ -44  /* Comparing a null character against a comma. */
     strncmp ("hello", "hello, world", 5)
         ⇒ 0    /* The initial 5 characters are the same. */
     strncmp ("hello, world", "hello, stupid world!!!", 5)
         ⇒ 0    /* The initial 5 characters are the same. */

— 函式: int strverscmp (const char *s1, const char *s2)

strverscmp 函式比较字串 s1 跟 s2,但会考虑里面的索引/版本数字,传回值有跟 strcmp 函式一样的规范,事实上假如s1 和 s2 没有数字, strverscmp 就像 strcmp一样。

基本上我们通常比较字串(逐字元),直到我们在字串里发现数字 – 接着我们进入一个特殊比较模式,在这里每个数字序列看成是一个数目,假如我们到达这两个部份的最后没有注意到差异,我们就会返回标准的比较模式,有两种数值型态的部份:”整数的” 跟 “零数的” (以 ‘0’开始的数字),数值部份的型态会影响到我们排序它们的方式:

  • 整数的/整数的:我们会如你预期的方式比较值。
  • 零数的/整数的:零数的部份比整数的部份小,这也是我预期的。
  • 零数的/零数的:这件事会变得有点复杂,如果常见的前缀只有零,最长的部份小于另一个;否则比较会是正常的。
          strverscmp ("no digit", "no digit")
              ⇒ 0    /* same behavior as strcmp. */
          strverscmp ("item#99", "item#100")
              ⇒ <0   /* same prefix, but 99 < 100. */
          strverscmp ("alpha1", "alpha001")
              ⇒ >0   /* fractional part inferior to integral one. */
          strverscmp ("part1_f012", "part1_f01")
              ⇒ >0   /* two fractional parts. */
          strverscmp ("foo.009", "foo.0")
              ⇒ <0   /* idem, but with leading zeroes only. */

这函式在处理档案名称的排序时特别有用,因为档案名称通常会有索引/版本数。

strverscmp 是 GNU 的扩充函式。

— 函式: int bcmp (const void *a1, const void *a2, size_t size)

这函式是 memcmp 过时的别名, 是从 BSD 衍生出来的。

下一节: ,上一节: Copying and Concatenation,这一章:字串和阵列的工具

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *