C言語の文字列変換系の関数(tolower, toupper, atoi, atol, atof, strtol)

tolower, toupperの最大のめんどくさい点はロケール依存であること。 atoi とかも小数点にロケールが絡んだりする??いまいち細かい点がわからない。 ロケール非依存にしたいなら自作したほうがいい気がする。

void tolower_test() {
  for (int i = 0; i <= 0xFFFF; i++) {
    if (i != tolower(i)) {
      assert(isupper(i));
      printf("%c", tolower(i)); // abcdefghijklmnopqrstuvwxyz
    }
  }
}

void toupper_test() {
  for (int i = 0; i <= 0xFFFF; i++) {
    if (i != toupper(i)) {
      assert(islower(i));
      printf("%c", toupper(i)); // ABCDEFGHIJKLMNOPQRSTUVWXYZ
    }
  }
}

void atoi_test() {
  // atoi は文字列を int に変換 (uint32_tではないので環境依存)
  printf("%d\n", atoi("")); // 0
  printf("%d\n", atoi("0")); // 0
  printf("%d\n", atoi("1")); // 1
  printf("%d\n", atoi("20")); // 20
  printf("%d\n", atoi("030")); // 30
  printf("%d\n", atoi("0x40")); // 0
  printf("%d\n", atoi("5hoge")); // 5
  printf("%d\n", atoi("6.66")); // 6
  printf("%d\n", atoi("-7")); // -7
  printf("%d\n", atoi("-8-8-8-")); // -8

  /*
   UINT_MAX を超えると UINT_MAX で割った余りに変換される?
   */
  printf("%d\n", INT_MAX); //  INT_MAX = 2147483647
  printf("%u\n", UINT_MAX);// UINT_MAX = 4294967295
  printf("%d\n", atoi("2147483647")); // 2147483647
  printf("%d\n", atoi("2147483648")); // -2147483648
  printf("%d\n", atoi("4294967294")); // -2
  printf("%d\n", atoi("4294967295")); // -1
  printf("%d\n", atoi("4294967296")); // 0
  printf("%d\n", atoi("4294967297")); // 1
  printf("%d\n", atoi("4294967298")); // 2
  printf("%d\n", atoi("429496729800")); // 200

  printf("%d\n", atoi(NULL)); // Segmentation Fault
}

void atol_test() {
  // atol は atoi と似たようなもので 文字列を long に変換する。
  /*
   らしいのだけどなんか挙動がよくわからん…
   */
  printf("%ld\n", LONG_MAX); // 9223372036854775807
  printf("%ld\n", atol("-1234567890000000"));    // -1234567890000000
  printf("%ld\n", atol("9223372036854775807"));  // 9223372036854775807
  printf("%ld\n", atol("9223372036854775808"));  // 9223372036854775807
  printf("%ld\n", atol("-9223372036854775808")); // -9223372036854775808
  printf("%ld\n", atol("-9223372036854775809")); // -9223372036854775808
  printf("%ld\n", atol("18446744073709551615")); // 9223372036854775807
}

void atof_test() {
  // atof は 文字列を double に変換する。floatではない。
  // atof は strtod(s, (char **)NULL) と等価
  printf("%.5f\n", atof("1.23")); // 1.23000
  printf("%.5f\n", atof("-4.56789")); // -4.56789
}

void strtol_test() {
  // long strtol(const char *文字列s, char **終了ポインタendp, int 基数base)
  // strtol は n進数の文字列を long に変換する。
  // strtoul という関数もあるがこれは unsigned long に変換する点が異なる
  // 基数は 2 ~ 36 まで指定可能
  printf("%ld\n", strtol("11111111", NULL, 2)); // 255
  printf("%ld\n", strtol("255", NULL, 10)); // 255
  printf("%ld\n", strtol("FF", NULL, 16)); // 255
  printf("%ld\n", strtol("ff", NULL, 16)); // 255
  printf("%ld\n", strtol("zz", NULL, 36)); // 1295
}
Share
関連記事