Created
September 28, 2016 19:17
-
-
Save yumetodo/8e1faac4f673adfe8d8ec80851dd4b9b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
注意
input.csv
はBOMがついていると読み込めないので注意。今回は面倒なのでBOM skipするコードは書かなかった。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12164937777