Advertisement
yumetodo

c_io_simple_test.c

Sep 28th, 2016
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.76 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <limits.h>//in gcc
  4. #include <errno.h>//in gcc
  5. #include <stdbool.h>
  6. #include <ctype.h>
  7. #ifdef _MSC_VER
  8. #   define RESTRICT
  9. #else
  10. #   define RESTRICT restrict
  11. #endif
  12. /**
  13.  * @brief 文字列が文字を持っているか調べます。
  14.  * @param str 対象文字列へのポインタ
  15.  * @return false: nullptrか空白文字のみの文字列 true:それ以外
  16.  */
  17. static inline bool str_has_char(const char *str) {
  18.     bool ret = false;
  19.     for (; !ret && *str != '\0'; str++) ret = (*str != ' ');
  20.     return ret;
  21. }
  22. /**
  23.  * @brief 文字列が文字を持っているか調べます。
  24.  * @param io 書き換えるbool型変数へのポインタ、呼び出し後はポインタが指す変数にnew_valueが代入される
  25.  * @param new_value 新しい値
  26.  * @return ioが指すbool変数がもともと持っていた値
  27.  */
  28. static inline bool exchange_bool(bool* RESTRICT const io, const bool new_value){
  29.     const bool tmp = *io;
  30.     *io = new_value;
  31.     return tmp;
  32. }
  33. typedef struct{
  34.     int first;
  35.     int second;
  36. } pair_int;
  37. /**
  38.  * @brief streamから入力を受け、int型に変換する
  39.  * @details fgetsしてstrtolしている。max, minの条件に合わないかエラー時は再帰
  40.  * @param stream FILE構造体へのポインタかstdin
  41.  * @param message 入力を受ける前にputsに渡す文字列。表示しない場合はnullptrか空白文字のみで構成された文字列へのポインタを渡す
  42.  * @param delim 区切り文字
  43.  * @param max 入力値を制限する。最大値を指定
  44.  * @param min 入力値を制限する。最小値を指定
  45.  * @return 入力した2つの数字、EOFのときは{0, 0}なのでfeofを呼んで判断すべし
  46.  */
  47. static inline pair_int finput_int_pair(FILE * RESTRICT stream, const char* message, const char delim, const int max, const int min){
  48.     if(str_has_char(message)) puts(message);
  49.     char s[100];
  50.     long t = 0;
  51.     bool first_flg = true;
  52.     char* endptr2 = s;
  53.     pair_int re = { 0, 0 };
  54.     do{
  55.         char* endptr1 = s;
  56.         do{
  57.             if(!exchange_bool(&first_flg, false)) puts("再入力してください");
  58.             if (NULL == fgets(s, 100, stream)){
  59.                 if (feof(stream)){
  60.                     re.first = 0;
  61.                     re.second = 0;
  62.                     return re;
  63.                 }
  64.                 //改行文字が入力を受けた配列にない場合、入力ストリームにごみがある
  65.                 size_t i;
  66.                 for(i = 0; i < 100 && '\0' == s[i]; i++);//strlenもどき
  67.                 if('\n' != s[i - 1]) while(fgetc(stream) != '\n');//入力ストリームを掃除
  68.                 continue;
  69.             }
  70.             if ('\n' == s[0]) continue;
  71.             t = strtol(s, &endptr1, 10);
  72.         } while(0 != errno || (0 == t && endptr1 == s) || t < min || max < t);
  73.         for(; isspace(endptr1[0]); ++endptr1);//空白skip
  74.         if(endptr1[0] != delim) continue;//delimiter check
  75.         for(++endptr1; isspace(endptr1[0]); ++endptr1);//空白skip
  76.         re.first = ((int)(t));
  77.         endptr2 = endptr1;
  78.         t = strtol(endptr1, &endptr2, 10);
  79.     } while(0 != errno || (0 == t && endptr2 == s) || t < min || max < t);
  80.     re.second = ((int)(t));
  81.     return re;
  82. }
  83. int main(void){
  84.     FILE* input;
  85.     FILE* output;
  86. #if defined(_MSC_VER) && 1400 <= _MSC_VER
  87.     if(0 != fopen_s(&input, "input.csv", "rb")) return 1;
  88.     if(0 != fopen_s(&output, "output.csv", "wb")) return 1;
  89. #else
  90.     if(NULL == (input = fopen("input.csv", "rb"))) return 1;
  91.     if(NULL == (output = fopen("output.csv", "wb"))) return 1;
  92. #endif
  93.     pair_int in = finput_int_pair(input, "", ',', INT_MAX, INT_MIN);
  94.     fprintf(output, "%d", in.first + in.second);
  95.     return 0;
  96. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement