문자열로 입력받는 것은
출력을 반대로 생각해주면 됩니다.

예로 문자열을 10진법으로 출력하기 위해
10으로 나누었다면
입력하기 위해서는
10씩 자리수만큼 곱하여 더하면 됩니다.
즉,
"1234"이라면
4 + 3 * 10 + 2 * (10^2) + 1 * (10^3)
다음과 같이 계산하면 됩니다.
여기서는 이것을 좀 더 확장하여
한번에 radix_a만큼 끊어서 읽으며
radix_b씩 자리수만큼 곱하여 더하는 식으로 하였습니다.
코드를 보시고 무슨 말인지 아실거라 믿습니다. ^^


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
const BigInteger & BigInteger::StringtoBigInteger(const string &str, const int radix/*=10*/)
{
    // 2~36진법 모두로 입력 할 수 있습니다.
    // 단, 입력에서 발생할 수 있는 실수는 점검하지 않습니다!
    // 예로.. 1234a324aa32432a를 10진법으로 입력 한다면
    // atoi 함수에서는 1234가 되지만 여기서는 4가 됩니다.
    if ( !( radix >=2 && radix <=36 ) )
        throw "2 ~ 36진법까지만 가능합니다.";
    // *this를 0으로 초기화 합니다.
    // 0으로 초기화 하지 않으면 const char *
    // const string & 생성자에서 오류가 나며
    // 이 함수를 따로 사용시에도 정확한 값이 나오지 않을 수 있습니다.
    Allocate(1);
    sign = Zero;
    // 문자열을 몇개씩 끊어서 읽을지 정합니다.
    length read_length = radix_a[radix - 2];
    // 입력은 출력을 역으로 생각하면 됩니다.
    // 낮은자리부터 read_length씩 끊어 읽은것에
    // base를 j번 곱해서 차례차례 결과값에 더하면 됩니다.
    BigInteger base(radix_b[radix - 2]);
    // 문자열의 길이를 구합니다.
    unsigned long offset = str.size();
    // 밑의 _Copy_s 함수가 필요로 합니다.
    // 정확한 위치와 갯수를 인수로 넣어야
    // 정확하고 오류없이 작동합니다.
    length blocklen = offset / read_length;
    unsigned long rest = offset % read_length;
    // read_length만큼 읽은것을 잠시 저장합니다.
    char temp[33] = {0,};
    // 문자열에 진법이상의 숫자, 문자가 있는지 점검하기 위해서 사용합니다.
    char *error_ptr;
    BigInteger x;
 
    // 문자열 맨 앞에 부호가 있을 수 있습니다.
    // 부호가 있을 경우를 처리해 줍니다.
    unsigned long signexist = 0;
    if (str[0] == '+')
        // + 부호가 있다고 해서 sign를 대입받지 않습니다.
        signexist = 1;
    else if (str[0] == '-')
    {
        // "-0"과 같은 경우입니다.
        if (str.size() == 2 && str[1] == '0')
            return _Zero;
        // 그 밖에 음수면 부호를 대입합니다.
        signexist = 1;
        sign = Negative;
    }
 
    unsigned long i, j;
    i = 0;
    j = 0;
    // read_length씩 완전하게 끊어 읽을 수 있는 경우
    // while문안으로 들어가게 됩니다.
    while (blocklen--)
    {
        // offset을 문자열의 맨 끝에서
        // read_length만큼 빼줍니다.
        offset -= read_length;
        // offset에서 read_length만큼 읽어서 temp에 저장
        str._Copy_s(temp, 33, read_length, offset);
        // strtoul함수는 진법으로 되있는 문자열을
        // unsigned long형으로 바꿔줍니다.
        // 대입 연산자로 x에 잘 대입됩니다.
        x = strtoul(temp, &error_ptr, radix);
        // x에 base를 j번 곱합니다.
        // 자리수를 생각해야하기 때문입니다.
        while (j--)
            x *= base;
        add(*this, x);
        j = ++i;
        // 문자열에 진법 이상의 숫자,문자가 있으면
        // goto로 함수를 종료시킵니다.
        // throw를 던지지 않습니다.
        if (*error_ptr != 0)
            goto endpoint;
    }
    // read_length에 부족하게 끊어 읽을 수 있는 경우
    if (rest != 0)
    {
        memset(temp, 0, 33);
        offset -= (rest - signexist);
        if (signexist == 1)
            rest--;
        str._Copy_s(temp, 33, rest, offset);
        x = strtoul(temp, &error_ptr, radix);
        if (j != 0)
        {
            while (j--)
                x *= base;
        }
        add(*this, x);
    }
endpoint:
    // 음수라면 부호가 Negative이며
    // 나머지 경우는 모두 Zero로 되있습니다.
    // 그 중, 양수 조건을 만족시키면 부호를 바꿔줍니다.
    if ( !(len == 1 && blk[0] == 0) && sign != Negative)
        sign = Positive;
    return *this;
}


>> 오버로딩 함수로는 10진법으로만 입력이 가능합니다.
10진법 이외로 입력을 받고 싶으시다면
먼저, string 에 입력을 받으신 다음
StringtoBigInteger함수에 첫번째 인수로 string을 넘기면 됩니다.
Posted by 투명테잎