Created
February 12, 2011 13:05
-
-
Save mumumu/823749 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
/** | |
* 標準入力を1文字ずつ受け取り、それらを繋ぎ合わせて | |
* 整数として出力するプログラム 実行例は以下のとおり。 | |
* | |
* $ gcc convert_stdin_tointeger.c -o input2int | |
* $ ./input2int | |
* input one number (space to exit):- <= 最初の桁は + と - の入力可(数値でもよい) | |
* input one number (space to exit):1 | |
* input one number (space to exit):2 | |
* input one number (space to exit): <= input space | |
* input number is -21 | |
*/ | |
#include <stdio.h> | |
#include <string.h> | |
#include <limits.h> | |
/* | |
* param を num 乗した数を返します。 | |
* math.h に pow 関数が存在することを知っていて再発明している | |
* この関数は以下の2点で非常に残念な関数である。 | |
* | |
* TODO: num が極端に大きな数になったとき(例:1億とか) に | |
* このコードは非常に残念なことになるので改善せよ | |
* TODO: オーバーフローを検知したときの戻り値が -1 である | |
* 点。param が -1 であるときに -1 が戻り値として | |
* 返る可能性がある。 | |
*/ | |
static int power(int param, int num) | |
{ | |
int i; | |
int ret = 1; | |
if (num == 0) { | |
return 1; | |
} | |
for (i = 0; i < num; i++) { | |
// overflow check | |
if (INT_MAX / param < ret) { | |
return -1; | |
} | |
ret = ret * param; | |
} | |
return ret; | |
} | |
/* | |
* fgets(3) が受け取っている内部バッファをクリアする | |
*/ | |
static void clearbuf(char *input_buf) | |
{ | |
// clear input buffer. | |
if (strchr(input_buf, '\n') != NULL) { | |
input_buf[strlen(input_buf) - 1] = '\0'; | |
} else { | |
while(getchar() != '\n'); | |
} | |
} | |
/* | |
* int 型の最大数の桁数を返します | |
*/ | |
static int max_number_of_digit() | |
{ | |
int ret = 0; | |
int tmp = INT_MAX; | |
printf("%d", tmp); | |
while (1) { | |
tmp = tmp / 10; | |
ret++; | |
if (tmp < 10) { break; } | |
} | |
return ret + 1; | |
} | |
/* | |
* 標準入力を1文字ずつ受け取り、それらを繋ぎ合わせて | |
* int型に変換して返す | |
*/ | |
static int convert() | |
{ | |
char input_buf[1] = {0}; | |
char input; | |
int count = 0; | |
int is_negative = 0; | |
int multiply_number = 0; | |
int plus_number = 0; | |
int output = 0; | |
// int 型が扱える最大桁数 | |
int num_of_digit = max_number_of_digit(); | |
while (count < num_of_digit) { | |
printf("input one number (space to exit):"); | |
if (fgets(input_buf, 2, stdin) == NULL) { | |
printf("input error\n"); | |
goto clearbuf; | |
} | |
input = input_buf[0]; | |
if (input == ' ') { break; } | |
// input check | |
if ((input < '0' || input > '9') | |
&& (input != '+' && input != '-')) { | |
printf("invalid input\n"); | |
goto clearbuf; | |
} | |
if (count != 0 && input == '+' | |
|| count != 0 && input == '-') { | |
printf("invalid input\n"); | |
goto clearbuf; | |
} | |
// negative flag | |
if (count == 0 && input == '-') { | |
is_negative = 1; | |
goto clearbuf; | |
} | |
// ignore first '+' | |
if (count == 0 && input == '+') { | |
goto clearbuf; | |
} | |
// overflow check | |
multiply_number = power(10, count); | |
if (multiply_number == -1) { | |
printf("error: your input will be overflow the output integer size\n"); | |
goto clearbuf; | |
} | |
if ((INT_MAX / (input - 0x30)) < multiply_number) { | |
printf("error: your input will be overflow the output integer size(1)\n"); | |
goto clearbuf; | |
} | |
plus_number = ((input - 0x30) * power(10, count)); | |
if ((INT_MAX - output) < plus_number) { | |
printf("error: your input will be overflow the output integer size(2)\n"); | |
goto clearbuf; | |
} | |
output += ((input - 0x30) * power(10, count)); | |
count++; | |
clearbuf: | |
clearbuf(input_buf); | |
} | |
return (is_negative) ? (output * -1) : output; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int input = convert(); | |
printf("input number is %d\n", input); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Line 38: <= ?
What happens if power(1, 200000000); is called?
power関数以外は読んでないけど、scanf使えばいいのではー。