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

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


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 투명테잎