「strtoll」関数で文字列を符号付き長整数に変換する方法:初心者向けチュートリアル


long long strtoll(const char *str, char **endptr, int base);

引数

  • base: 文字列を解釈する基数。有効な基数は 2 から 36 まで、または 0 です。0 を指定すると、文字列の先頭から始まる最長の有効な数値部分に基づいて基数が自動的に判別されます。
  • endptr: 変換後の文字列のポインタを格納する変数へのポインタ。変換が成功した場合、endptr は変換後の文字列の最初の文字を指すように設定されます。endptrNULL の場合、この引数は使用されません。
  • str: 変換対象の文字列を含むポインタ

戻り値

変換に成功した場合、strtoll 関数は変換された符号付き長整数値を返します。変換に失敗した場合、0 を返します。

エラー処理

strtoll 関数は、変換に失敗した場合、errno 変数にエラーコードを設定します。考えられるエラーコードは以下の通りです。

  • EINVAL: 無効な基数が指定された場合
  • ERANGE: 変換結果が符号付き長整数の表現範囲外である場合

#include <stdio.h>
#include <stdlib.h>

int main() {
  char str[] = "123456789";
  char *endptr;
  long long num;

  num = strtoll(str, &endptr, 10);
  if (num == 0) {
    printf("変換に失敗しました。\n");
  } else {
    printf("%lld\n", num);
  }

  return 0;
}

この例では、文字列 "123456789" を 10 進数として解釈し、符号付き長整数に変換しています。変換に成功すると、変換された値がコンソールに出力されます。

  • strtoll 関数は、文字列の先頭に "0" がある場合、8 進数として解釈します。
  • strtoll 関数は、文字列の先頭に "0x" または "0X" がある場合、16 進数として解釈します。
  • strtoll 関数は、文字列の先頭に符号 (+/-) がある場合、符号付き長整数として解釈します。
  • strtoll 関数は、strtol 関数と同様に、文字列の先頭の空白文字を無視します。


例 1:10 進数の文字列を符号付き長整数に変換する

#include <stdio.h>
#include <stdlib.h>

int main() {
  char str[] = "123456789";
  char *endptr;
  long long num;

  num = strtoll(str, &endptr, 10);
  if (num == 0) {
    printf("変換に失敗しました。\n");
  } else {
    printf("%lld\n", num);
  }

  return 0;
}

例 2:16 進数の文字列を符号付き長整数に変換する

#include <stdio.h>
#include <stdlib.h>

int main() {
  char str[] = "0xABCDEF";
  char *endptr;
  long long num;

  num = strtoll(str, &endptr, 16);
  if (num == 0) {
    printf("変換に失敗しました。\n");
  } else {
    printf("%lld\n", num);
  }

  return 0;
}

この例では、文字列 "0xABCDEF" を 16 進数として解釈し、符号付き長整数に変換しています。変換に成功すると、変換された値がコンソールに出力されます。

例 3:8 進数の文字列を符号付き長整数に変換する

#include <stdio.h>
#include <stdlib.h>

int main() {
  char str[] = "01234567";
  char *endptr;
  long long num;

  num = strtoll(str, &endptr, 8);
  if (num == 0) {
    printf("変換に失敗しました。\n");
  } else {
    printf("%lld\n", num);
  }

  return 0;
}

例 4:文字列の先頭に符号が付いている場合の変換

#include <stdio.h>
#include <stdlib.h>

int main() {
  char str[] = "-123456789";
  char *endptr;
  long long num;

  num = strtoll(str, &endptr, 10);
  if (num == 0) {
    printf("変換に失敗しました。\n");
  } else {
    printf("%lld\n", num);
  }

  return 0;
}

この例では、文字列 "-123456789" を 10 進数として解釈し、符号付き長整数に変換しています。変換に成功すると、変換された値がコンソールに出力されます。符号が - のため、変換された値は負の数になります。

#include <stdio.h>
#include <stdlib.h>

int main() {
  char str[] = "abc123";
  char *endptr;
  long long num;

  num = strtoll(str, &endptr, 10);
  if (num == 0) {
    if (errno == ERANGE) {
      printf("変換結果が符号付き長整数の表現範囲外です。\n");
    } else if (errno == EINVAL) {
      printf("無効な基数が指定されました。\n");
    } else {
      printf("その他のエラーが発生しました。\n");
    }
  } else {
    printf("%lld\n", num);
  }

  return 0;
}


strtol 関数

strtol 関数は、strtoll 関数と似ていますが、変換結果が long int 型になります。符号付き長整数の表現範囲を超える値を扱う場合は、strtoll 関数ではなく strtol 関数を使用する必要があります。

long int strtol(const char *nptr, char **endptr, int base);

#include <stdio.h>
#include <stdlib.h>

int main() {
  char str[] = "123456789";
  char *endptr;
  long int num;

  num = strtol(str, &endptr, 10);
  if (num == 0) {
    printf("変換に失敗しました。\n");
  } else {
    printf("%ld\n", num);
  }

  return 0;
}

atoi 関数

atoi 関数は、文字列を int 型に変換します。符号付き長整数に変換する場合は、変換結果を (long long)atoi(str) のように明示的に型変換する必要があります。ただし、atoi 関数は、符号付き長整数の表現範囲を超える値を扱うことができないため、注意が必要です。

int atoi(const char *nptr);

#include <stdio.h>
#include <stdlib.h>

int main() {
  char str[] = "123456789";
  long long num;

  num = (long long)atoi(str);
  if (num == 0) {
    printf("変換に失敗しました。\n");
  } else {
    printf("%lld\n", num);
  }

  return 0;
}

手動解析

上記の関数はいずれも使用できない場合、文字列を自分で解析して符号付き長整数に変換することができます。この方法は柔軟性がありますが、複雑でエラーが発生しやすいという欠点があります。

long long my_strtol(const char *str, int base) {
  long long result = 0;
  int sign = 1;
  int i = 0;

  if (str[i] == '+' || str[i] == '-') {
    if (str[i] == '-') {
      sign = -1;
    }
    i++;
  }

  while (str[i] != '\0') {
    int digit = str[i] - '0';
    if (digit < 0 || digit > base - 1) {
      return 0;
    }

    result = result * base + digit;
    i++;
  }

  return result * sign;
}

カスタム関数

上記の代替方法のいずれもニーズに合わない場合は、独自の関数を作成することができます。この方法は、特定の要件に合わせた柔軟なソリューションを提供できますが、開発とテストに時間がかかります。