Cプログラミング
 Computer >> コンピューター >  >> プログラミング >> Cプログラミング

C言語のfgets()とgets()の違いと安全な文字列入力の方法

C言語で標準入力から文字列を読み込む際に使われる代表的な関数が fgets()gets() です。どちらも文字列を取得する目的は同じですが、安全性の面で大きな違いがあります。本記事では、それぞれの構文・使い方・特徴をサンプルコードとともに詳しく解説します。


fgets()とは

fgets() は、改行文字まで(または指定した文字数まで)文字列を読み取る関数です。最大の特徴は配列の境界をチェックする点にあり、バッファオーバーフローを防げるため安全な入力関数として推奨されています。

fgets()の構文

char *fgets(char *string, int value, FILE *stream)

引数の説明

  • string … 読み込んだ文字列を格納するchar型配列へのポインタ。
  • value … 読み込む最大文字数(終端のヌル文字 '\0' を含む)。
  • stream … 入力元となるFILEオブジェクトへのポインタ(標準入力の場合は stdin を指定)。

fgets()の使用例

#include <stdio.h>
#define FUNC 8
int main() {
    char b[FUNC];
    fgets(b, FUNC, stdin);
    printf("The string is: %s\n", b);
    return 0;
}

出力結果

標準入力ストリームに「Hello World!」と入力した場合の出力例です。

The string is: Hello W

プログラムの解説

このプログラムでは、まずchar型の配列 b を宣言しています。その後、fgets() がSTDIN(標準入力)ストリームから指定された文字数分だけ読み込みます。配列サイズが8バイトのため、終端のヌル文字を除いた7文字「Hello W」までしか格納されません。これにより、たとえ長い文字列が入力されてもバッファオーバーフローが発生しないことがわかります。

char b[FUNC];
fgets(b, FUNC, stdin);

gets()とは

gets() は、標準入力デバイスから文字列を読み取る関数です。しかし、配列の境界を一切チェックしないため、入力された文字数が配列サイズを超えるとバッファオーバーフローが発生し、深刻なセキュリティ脆弱性につながります。この危険性から、C11規格では gets()廃止(削除)されました。現在の開発では使用を避け、fgets() を使うことが強く推奨されます。

gets()の構文

char *gets(char *string);

引数の説明

  • string … 読み込んだ文字列を格納するchar型配列へのポインタ。

gets()の使用例

#include <stdio.h>
#include <string.h>
int main() {
    char s[100];
    int i;
    printf("\nEnter a string : ");
    gets(s);
    for (i = 0; s[i]!='\0'; i++) {
        if(s[i] >= 'a' && s[i] <= 'z') {
            s[i] = s[i] - 32;
        }
    }
    printf("\nString in Upper Case = %s", s);
    return 0;
}

出力結果

Enter a string : hello world!
String in Upper Case = HELLO WORLD!

プログラムの解説

このプログラムでは、gets() を使って標準入力から文字列を読み込み、char型配列 s に格納しています。その後、forループで各文字を走査し、小文字('a'〜'z')をASCIIコード上で32減算することで大文字へ変換しています。

char s[100];
int i;
printf("\nEnter a string : ");
gets(s);

この例では配列サイズが100バイトあるため問題なく動作しますが、仮に101文字以上が入力されるとメモリ領域を破壊してしまいます。これが gets() が危険とされる理由です。


まとめ:fgets()とgets()の比較

項目fgets()gets()
配列境界のチェックあり(安全)なし(危険)
改行文字の扱い改行も含めて読み込む改行は除去される
C11規格での扱い利用可能廃止(削除)
推奨度◎ 推奨× 非推奨

現代のC言語プログラミングにおいては、文字列入力には必ず fgets() を使用しましょう。必要に応じて改行文字の除去や sscanf() との組み合わせを行うことで、安全かつ柔軟な入力処理が実現できます。

  1. JavaScriptのTextEncoderとTextDecoderとは?文字列とバイト列の相互変換をわかりやすく解説

    JavaScriptでは、文字列とバイト列(バイナリデータ)を相互に変換したい場面がよくあります。そんなときに活躍するのが、TextEncoderとTextDecoderという2つの標準組み込みAPIです。本記事では、それぞれの役割と基本的な使い方を、実際に動くサンプルコードとともに解説します。 TextEncoderとは TextEncoderは、指定した文字列をUTF-8形式に変換(エンコード)するためのオブジェクトです。encode()メソッドに文字列を渡すと、変換結果がUint8Array(符号なし8ビット整数の配列)として返されます。 TextDecoderとは TextDecod

  2. C言語で文字列⇔数値の相互変換を行う方法|sscanf関数とsprintf関数の使い方

    はじめにC言語のプログラミングにおいて、「文字列から数値への変換」および「数値から文字列への変換」とは何を意味するのでしょうか?本記事では、標準ライブラリ関数を使った双方向の変換方法を、構文・サンプルコード・実行結果とあわせて解説します。解決策:使用する2つの関数C言語には、この変換を実現するための関数が用意されています。sscanf() ― 文字列を数値に変換するsprintf() ― 数値を文字列に変換する文字列から数値への変換(sscanf)sscanf()関数を使うことで、文字列として格納されたデータを、書式指定子に従って解析し、数値として各変数に読み込むことができます。scanf()