Skip to content

Instantly share code, notes, and snippets.

@yumetodo
Created September 28, 2016 19:17
Show Gist options
  • Save yumetodo/8e1faac4f673adfe8d8ec80851dd4b9b to your computer and use it in GitHub Desktop.
Save yumetodo/8e1faac4f673adfe8d8ec80851dd4b9b to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>//in gcc
#include <errno.h>//in gcc
#include <stdbool.h>
#include <ctype.h>
#ifdef _MSC_VER
# define RESTRICT
#else
# define RESTRICT restrict
#endif
/**
* @brief 文字列が文字を持っているか調べます。
* @param str 対象文字列へのポインタ
* @return false: nullptrか空白文字のみの文字列 true:それ以外
*/
static inline bool str_has_char(const char *str) {
bool ret = false;
for (; !ret && *str != '\0'; str++) ret = (*str != ' ');
return ret;
}
/**
* @brief 文字列が文字を持っているか調べます。
* @param io 書き換えるbool型変数へのポインタ、呼び出し後はポインタが指す変数にnew_valueが代入される
* @param new_value 新しい値
* @return ioが指すbool変数がもともと持っていた値
*/
static inline bool exchange_bool(bool* RESTRICT const io, const bool new_value){
const bool tmp = *io;
*io = new_value;
return tmp;
}
typedef struct{
int first;
int second;
} pair_int;
/**
* @brief streamから入力を受け、int型に変換する
* @details fgetsしてstrtolしている。max, minの条件に合わないかエラー時は再帰
* @param stream FILE構造体へのポインタかstdin
* @param message 入力を受ける前にputsに渡す文字列。表示しない場合はnullptrか空白文字のみで構成された文字列へのポインタを渡す
* @param delim 区切り文字
* @param max 入力値を制限する。最大値を指定
* @param min 入力値を制限する。最小値を指定
* @return 入力した2つの数字、EOFのときは{0, 0}なのでfeofを呼んで判断すべし
*/
static inline pair_int finput_int_pair(FILE * RESTRICT stream, const char* message, const char delim, const int max, const int min){
if(str_has_char(message)) puts(message);
char s[100];
long t = 0;
bool first_flg = true;
char* endptr2 = s;
pair_int re = { 0, 0 };
do{
char* endptr1 = s;
do{
if(!exchange_bool(&first_flg, false)) puts("再入力してください");
if (NULL == fgets(s, 100, stream)){
if (feof(stream)){
re.first = 0;
re.second = 0;
return re;
}
//改行文字が入力を受けた配列にない場合、入力ストリームにごみがある
size_t i;
for(i = 0; i < 100 && '\0' == s[i]; i++);//strlenもどき
if('\n' != s[i - 1]) while(fgetc(stream) != '\n');//入力ストリームを掃除
continue;
}
if ('\n' == s[0]) continue;
t = strtol(s, &endptr1, 10);
} while(0 != errno || (0 == t && endptr1 == s) || t < min || max < t);
for(; isspace(endptr1[0]); ++endptr1);//空白skip
if(endptr1[0] != delim) continue;//delimiter check
for(++endptr1; isspace(endptr1[0]); ++endptr1);//空白skip
re.first = ((int)(t));
endptr2 = endptr1;
t = strtol(endptr1, &endptr2, 10);
} while(0 != errno || (0 == t && endptr2 == s) || t < min || max < t);
re.second = ((int)(t));
return re;
}
int main(void){
FILE* input;
FILE* output;
#if defined(_MSC_VER) && 1400 <= _MSC_VER
if(0 != fopen_s(&input, "input.csv", "rb")) return 1;
if(0 != fopen_s(&output, "output.csv", "wb")) return 1;
#else
if(NULL == (input = fopen("input.csv", "rb"))) return 1;
if(NULL == (output = fopen("output.csv", "wb"))) return 1;
#endif
pair_int in = finput_int_pair(input, "", ',', INT_MAX, INT_MIN);
fprintf(output, "%d", in.first + in.second);
return 0;
}
@yumetodo
Copy link
Author

@yumetodo
Copy link
Author

@yumetodo
Copy link
Author

注意

input.csvはBOMがついていると読み込めないので注意。今回は面倒なのでBOM skipするコードは書かなかった。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment