【C言語】文字列と数値を相互に変換し合う方法を解説

C言語でプログラミングをしていると、文字列と数値を相互に変換する場面がよくあります。

例えば、ユーザーから入力された文字列を数値に変換したり、計算結果の数値を文字列として表示したりすることが必要です。

この記事では、文字列から数値への変換方法と数値から文字列への変換方法について、具体的な関数の使い方や注意点をわかりやすく解説します。

また、エラーハンドリングの方法や安全な変換のためのベストプラクティスについても紹介します。

初心者の方でも理解しやすいように、サンプルコードを交えて説明しているので、ぜひ参考にしてください。

目次から探す

文字列から数値への変換

C言語では、文字列を数値に変換するためのいくつかの方法があります。

ここでは、代表的な関数であるatoistrtolsscanfについて解説します。

atoi関数の使用

atoi関数の基本的な使い方

atoi関数は、文字列を整数に変換するための標準的な関数です。

atoiASCII to Integer の略で、文字列の先頭から数値部分を整数として解釈します。

#include <stdio.h>
#include <stdlib.h>
int main() {
    char str[] = "12345";
    int num = atoi(str);
    printf("変換された数値: %d\n", num);
    return 0;
}

atoi関数の注意点と制約

atoi関数にはいくつかの注意点があります。

まず、変換に失敗した場合のエラーチェックができません。

また、入力文字列が数値以外の文字を含む場合、その部分は無視されます。

例えば、123abcという文字列を変換すると、結果は123になります。

#include <stdio.h>
#include <stdlib.h>
int main() {
    char str[] = "123abc";
    int num = atoi(str);
    printf("変換された数値: %d\n", num);  // 結果は123
    return 0;
}

サンプルコード

以下は、atoi関数を使って文字列を整数に変換するサンプルコードです。

#include <stdio.h>
#include <stdlib.h>
int main() {
    char str1[] = "12345";
    char str2[] = "6789abc";
    char str3[] = "abc123";
    int num1 = atoi(str1);
    int num2 = atoi(str2);
    int num3 = atoi(str3);
    printf("str1の変換結果: %d\n", num1);  // 12345
    printf("str2の変換結果: %d\n", num2);  // 6789
    printf("str3の変換結果: %d\n", num3);  // 0
    return 0;
}

strtol関数の使用

strtol関数の基本的な使い方

strtol関数は、文字列を長整数(long int)に変換するための関数です。

strtolString to Long の略で、変換に失敗した場合のエラーチェックが可能です。

また、基数(10進数、16進数など)を指定することもできます。

#include <stdio.h>
#include <stdlib.h>
int main() {
    char str[] = "12345";
    char *endptr;
    long num = strtol(str, &endptr, 10);
    printf("変換された数値: %ld\n", num);
    return 0;
}

strtol関数の利点と注意点

strtol関数の利点は、エラーチェックが可能な点です。

変換に失敗した場合、endptrが変換に失敗した位置を指します。

また、基数を指定できるため、16進数や8進数の文字列も変換可能です。

#include <stdio.h>
#include <stdlib.h>
int main() {
    char str[] = "123abc";
    char *endptr;
    long num = strtol(str, &endptr, 10);
    if (*endptr != '\0') {
        printf("変換に失敗しました: %s\n", endptr);
    } else {
        printf("変換された数値: %ld\n", num);
    }
    return 0;
}

サンプルコード

以下は、strtol関数を使って文字列を長整数に変換するサンプルコードです。

#include <stdio.h>
#include <stdlib.h>
int main() {
    char str1[] = "12345";
    char str2[] = "6789abc";
    char str3[] = "abc123";
    char *endptr;
    long num1 = strtol(str1, &endptr, 10);
    printf("str1の変換結果: %ld\n", num1);  // 12345
    long num2 = strtol(str2, &endptr, 10);
    if (*endptr != '\0') {
        printf("str2の変換に失敗しました: %s\n", endptr);  // abc
    } else {
        printf("str2の変換結果: %ld\n", num2);
    }
    long num3 = strtol(str3, &endptr, 10);
    if (*endptr != '\0') {
        printf("str3の変換に失敗しました: %s\n", endptr);  // abc123
    } else {
        printf("str3の変換結果: %ld\n", num3);
    }
    return 0;
}

sscanf関数の使用

sscanf関数の基本的な使い方

sscanf関数は、文字列から指定された形式でデータを読み取るための関数です。

sscanfString Scan Formatted の略で、フォーマット指定子を使って文字列から数値を抽出します。

#include <stdio.h>
int main() {
    char str[] = "12345";
    int num;
    sscanf(str, "%d", &num);
    printf("変換された数値: %d\n", num);
    return 0;
}

sscanf関数の利点と注意点

sscanf関数の利点は、フォーマット指定子を使って柔軟にデータを抽出できる点です。

しかし、入力文字列がフォーマットに合わない場合、変換に失敗することがあります。

また、sscanf関数はエラーチェックが難しいため、入力の検証が重要です。

#include <stdio.h>
int main() {
    char str[] = "123abc";
    int num;
    int result = sscanf(str, "%d", &num);
    if (result == 1) {
        printf("変換された数値: %d\n", num);
    } else {
        printf("変換に失敗しました\n");
    }
    return 0;
}

サンプルコード

以下は、sscanf関数を使って文字列を整数に変換するサンプルコードです。

#include <stdio.h>
int main() {
    char str1[] = "12345";
    char str2[] = "6789abc";
    char str3[] = "abc123";
    int num;
    int result1 = sscanf(str1, "%d", &num);
    if (result1 == 1) {
        printf("str1の変換結果: %d\n", num);  // 12345
    } else {
        printf("str1の変換に失敗しました\n");
    }
    int result2 = sscanf(str2, "%d", &num);
    if (result2 == 1) {
        printf("str2の変換結果: %d\n", num);  // 6789
    } else {
        printf("str2の変換に失敗しました\n");
    }
    int result3 = sscanf(str3, "%d", &num);
    if (result3 == 1) {
        printf("str3の変換結果: %d\n", num);
    } else {
        printf("str3の変換に失敗しました\n");
    }
    return 0;
}

以上が、文字列から数値への変換に使用される代表的な関数です。

それぞれの関数には利点と注意点があるため、用途に応じて適切な関数を選択してください。

数値から文字列への変換

数値を文字列に変換する方法は、C言語においても非常に重要です。

ここでは、代表的な関数であるsprintfitoasnprintfの使い方とその利点・注意点について解説します。

sprintf関数の使用

sprintf関数の基本的な使い方

sprintf関数は、数値を文字列に変換するための標準的な方法です。

この関数は、指定されたフォーマットに従って文字列を生成し、バッファに格納します。

#include <stdio.h>
int main() {
    int num = 123;
    char str[10];
    sprintf(str, "%d", num);
    printf("変換された文字列: %s\n", str);
    return 0;
}

この例では、整数123を文字列に変換し、strに格納しています。

sprintf関数の利点と注意点

sprintf関数の利点は、フォーマット指定子を使用して様々な形式で数値を文字列に変換できる点です。

例えば、浮動小数点数や16進数なども簡単に変換できます。

しかし、sprintf関数にはバッファオーバーフローのリスクがあります。

バッファのサイズを超えるデータを書き込むと、メモリの破壊や予期しない動作が発生する可能性があります。

サンプルコード

以下は、sprintf関数を使用して異なる形式の数値を文字列に変換する例です。

#include <stdio.h>
int main() {
    int num = 255;
    char str[20];
    // 10進数
    sprintf(str, "%d", num);
    printf("10進数: %s\n", str);
    // 16進数
    sprintf(str, "%x", num);
    printf("16進数: %s\n", str);
    // 浮動小数点数
    double fnum = 123.456;
    sprintf(str, "%.2f", fnum);
    printf("浮動小数点数: %s\n", str);
    return 0;
}

itoa関数の使用

itoa関数の基本的な使い方

itoa関数は、整数を文字列に変換するための非標準関数です。

この関数は、数値を指定された基数(例えば10進数や16進数)で文字列に変換します。

#include <stdlib.h>
#include <stdio.h>
int main() {
    int num = 123;
    char str[10];
    itoa(num, str, 10);
    printf("変換された文字列: %s\n", str);
    return 0;
}

この例では、整数123を10進数の文字列に変換し、strに格納しています。

itoa関数の利点と注意点

itoa関数の利点は、簡単に使用できる点と、基数を指定して変換できる点です。

しかし、この関数は標準Cライブラリには含まれておらず、移植性に欠ける場合があります。

サンプルコード

以下は、itoa関数を使用して異なる基数で数値を文字列に変換する例です。

#include <stdlib.h>
#include <stdio.h>
int main() {
    int num = 255;
    char str[20];
    // 10進数
    itoa(num, str, 10);
    printf("10進数: %s\n", str);
    // 16進数
    itoa(num, str, 16);
    printf("16進数: %s\n", str);
    return 0;
}

snprintf関数の使用

snprintf関数の基本的な使い方

snprintf関数は、sprintf関数と同様に数値を文字列に変換しますが、バッファのサイズを指定できるため、バッファオーバーフローを防ぐことができます。

#include <stdio.h>
int main() {
    int num = 123;
    char str[10];
    snprintf(str, sizeof(str), "%d", num);
    printf("変換された文字列: %s\n", str);
    return 0;
}

この例では、整数123を文字列に変換し、strに格納しています。

バッファのサイズを指定することで、安全に変換を行っています。

snprintf関数の利点と注意点

snprintf関数の最大の利点は、バッファオーバーフローを防ぐことができる点です。

バッファのサイズを指定することで、書き込みがバッファの範囲内に収まるように制御できます。

ただし、バッファが小さすぎる場合、出力が切り捨てられる可能性があるため、適切なバッファサイズを確保することが重要です。

サンプルコード

以下は、snprintf関数を使用して異なる形式の数値を文字列に変換する例です。

#include <stdio.h>
int main() {
    int num = 255;
    char str[20];
    // 10進数
    snprintf(str, sizeof(str), "%d", num);
    printf("10進数: %s\n", str);
    // 16進数
    snprintf(str, sizeof(str), "%x", num);
    printf("16進数: %s\n", str);
    // 浮動小数点数
    double fnum = 123.456;
    snprintf(str, sizeof(str), "%.2f", fnum);
    printf("浮動小数点数: %s\n", str);
    return 0;
}

以上が、数値を文字列に変換するための代表的な方法です。

それぞれの関数には利点と注意点がありますので、用途に応じて適切な方法を選択してください。

エラーハンドリング

文字列と数値の変換において、エラーハンドリングは非常に重要です。

適切なエラーチェックを行わないと、プログラムが予期しない動作をする可能性があります。

ここでは、変換エラーの検出方法と安全な変換のためのベストプラクティスについて解説します。

変換エラーの検出方法

errnoの使用

errnoは、エラーが発生した際にエラーコードを格納するためのグローバル変数です。

C言語の標準ライブラリ関数の多くは、エラーが発生するとerrnoに適切なエラーコードを設定します。

変換関数でも同様に、エラーが発生した場合にerrnoを利用してエラーを検出することができます。

strtol関数のエラーチェック

strtol関数は、文字列を数値に変換する際にエラーが発生した場合、errnoを設定します。

具体的には、以下のようなエラーが考えられます。

  • 入力文字列が数値に変換できない場合
  • 変換結果が範囲外の場合

これらのエラーを検出するためには、strtol関数の戻り値とerrnoを確認する必要があります。

サンプルコード

以下に、strtol関数を使用して文字列を数値に変換し、エラーを検出するサンプルコードを示します。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
int main() {
    const char *str = "123abc";
    char *endptr;
    long val;
    errno = 0; // errnoをリセット
    val = strtol(str, &endptr, 10);
    // エラーチェック
    if (errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) {
        printf("範囲外の値です\n");
    } else if (errno != 0 && val == 0) {
        printf("変換エラーが発生しました\n");
    } else if (endptr == str) {
        printf("数値が見つかりません\n");
    } else {
        printf("変換された値: %ld\n", val);
    }
    return 0;
}

安全な変換のためのベストプラクティス

入力の検証

入力データが正しい形式であることを確認することは、エラーを防ぐための重要なステップです。

例えば、数値に変換する前に、入力文字列が数値として有効であるかをチェックすることが推奨されます。

バッファオーバーフローの防止

バッファオーバーフローは、メモリの安全性を脅かす重大な問題です。

数値を文字列に変換する際には、バッファのサイズを適切に設定し、オーバーフローを防ぐための対策を講じる必要があります。

サンプルコード

以下に、入力の検証とバッファオーバーフローの防止を行うサンプルコードを示します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int is_valid_number(const char *str) {
    // 文字列が数値として有効かをチェック
    for (int i = 0; str[i] != '\0'; i++) {
        if (!isdigit(str[i])) {
            return 0; // 数字以外の文字が含まれている
        }
    }
    return 1; // 有効な数値
}
int main() {
    const char *str = "12345";
    char buffer[20];
    // 入力の検証
    if (!is_valid_number(str)) {
        printf("無効な入力です\n");
        return 1;
    }
    // 数値から文字列への変換
    int num = atoi(str);
    snprintf(buffer, sizeof(buffer), "%d", num);
    printf("変換された文字列: %s\n", buffer);
    return 0;
}

このサンプルコードでは、まず入力文字列が数値として有効かをチェックし、その後snprintf関数を使用してバッファオーバーフローを防ぎながら数値を文字列に変換しています。

目次から探す