Skip to content

Instantly share code, notes, and snippets.

@mumumu
Created February 12, 2011 13:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mumumu/823749 to your computer and use it in GitHub Desktop.
Save mumumu/823749 to your computer and use it in GitHub Desktop.
/**
* 標準入力を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;
}
@pascaljp
Copy link

Line 38: <= ?
What happens if power(1, 200000000); is called?
power関数以外は読んでないけど、scanf使えばいいのではー。

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