「C言語の基礎 - 標準入力から安全に文字列を取得する」の版間の差分

ナビゲーションに移動 検索に移動
113行目: 113行目:


== fgets関数の利用 ==
== fgets関数の利用 ==
fgets関数は、改行も1行に含めて一緒に取得する。<br>
<code>fgets</code>関数は、改行も1行に含めて一緒に取得する。<br>
削除する場合は、各自でコードを記述しなければならない。<br>strlen関数を使用するなどして、文字列長を求めることも必要である。<br>
削除する場合は、各自でコードを記述しなければならない。また、<code>strlen</code>関数を使用するなどして、文字列長を求めることも必要である。<br>
<br>
<br>
また、戻り値は以下のようになる。<br>
また、戻り値は以下のようになる。<br>
* 1文字以上読み取れた場合は、buffer(改行だけでも1文字以上という扱いになる)
* 1文字以上読み取れた場合は、buffer(改行だけでも1文字以上という扱いになる)
* 最初からCtrl+D(Windowsの場合はCtrl+Z)でEOFが入力された場合は、NULL
* 最初から[Ctrl] + [D](Windowsの場合は[Ctrl] + [Z])でEOFが入力された場合は、<code>NULL</code>
* 失敗した場合は、そのままreturn 1;としてプログラムを異常終了扱いにさせるとよい。
* 失敗した場合は、<code>return 1;</code>としてプログラムを異常終了扱いにさせるとよい。
<br>
<br>
以下の例では、必ず1文字以上入力させて改行を削除している。<br>
以下の例では、必ず1文字以上入力させて改行を削除している。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdio.h>
  #include <stdio.h>
  #include <string.h>
  #include <string.h>
147行目: 147行目:
     return 0;
     return 0;
  }
  }
  </source>
  </syntaxhighlight>
<br>
<br>
以下の例では、改行だけの入力を認めて改行を削除している。<br>
以下の例では、改行だけの入力を認めて改行を削除している。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdio.h>
  #include <stdio.h>
  #include <string.h>
  #include <string.h>
175行目: 175行目:
     return 0;
     return 0;
  }
  }
  </source>
  </syntaxhighlight>
<br>
<br>
以下の例では、改行だけの入力を認めて改行を削除している。<br>
以下の例では、改行だけの入力を認めて改行を削除している。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdio.h>
  #include <stdio.h>
   
   
195行目: 195行目:
     return 0;
     return 0;
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
 
== 整数の読み取り ==
==== scanf関数の使用 ====
整数を受け取る場合、一般的に<code>scanf</code>関数の<code>%d</code>を使用することが多い。<br>
<br>
以下の例では、複数個の数値が入力された時、2個目以降は無視している。<br>
ただし、以下のような欠点が存在する。<br>
* 最初が空白文字の場合、<code>scanf</code>関数が終了しない。
* 範囲外の値が入力された場合、対応できない。
<syntaxhighlight lang="c">
#include <stdio.h>
int main()
{
    int num;
    printf("Input: ");
    if (scanf("%d%*[^\n]", &num) != 1)
    {
      return 1;
    }
    scanf("%*c");
    printf("Output: %d\n", buffer);
    return 0;
}
</syntaxhighlight>
<br>
==== scanf関数とstrtol関数の使用 ====
<code>scanf</code>関数のみでは上記のような欠点があるため、文字列として読み取り整数に変換する方法がある。<br>
<br>
文字列から整数に変換するには<code>strtol</code>関数を使用するため、整数は<code>long</code>型とする。<br>
なお、<code>atoi</code>関数や<code>atol</code>関数にはエラー検出機能は無いので使用しないこと。<br>
<syntaxhighlight lang="c">
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
int main()
{
    char buffer[32], *endptr;
    long num;
    // 文字列として読み取る
    printf("Input: ");
    if (scanf("%31[^\n]%*[^\n]", buffer) != 1)
    {
      fprintf(stderr, "Error: No input specified\n");
      return 1;
    }
    scanf("%*c");
    // 文字列から整数に変換する
    num = strtol(buffer, &endptr, 10);
    if (*endptr != '\0')
    {
      fprintf(stderr, "Error: Invalid charcter found: %c\n", *endptr);
      return 1;
    }
    if (errno == ERANGE)
    {
      fprintf(stderr, "Error: Out of range (%s)\n", num == LONG_MAX ? "Overflow" : "Underflow");
      return 1;
    }
    printf("Output: %ld\n", num);
    return 0;
}
</syntaxhighlight>
<br><br>
 
== 指定サイズ内で複数行を読み取る ==
<code>fread</code>関数を使用する場合、行という概念にとらわれず,格納領域が全て埋まる、または、入力が<code>EOF</code>に到達するまで読み取ることができる。<br>
ただし、バイナリモードで読み取るため改行コードの自動変換の機能が無い。そのため、テキストを処理する場合は不便である。<br>
<br>
<code>scanf</code>関数では、<code>%4095[\x01-\xff]</code>のように記述することにより、<code>NULL</code>文字以外の文字を全て読み取ることができる。(改行も読み取ることができる)<br>
<syntaxhighlight lang="c">
#include <stdio.h>
#include <string.h>
int main()
{
    char buffer[4096] = {0},
        *p = NULL;
    printf("Input: \n");
    if (scanf("%4095[\x01-\xff]", buffer) != 1)
    {
      return 1;
    }
    printf("Output: \n");
    for (size_t i = 0, p = strtok(buffer, "\n"); p; i++, p = strtok(NULL, "\n"))
    {  // 確認用にstrtok関数を使用して行ごとに番号を付加して表示する
      printf("[%zu] %s\n", i, p);
    }
    return 0;
}
</syntaxhighlight>
<br><br>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:C]]
[[カテゴリ:C]]

案内メニュー