문제
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 A와 B가 주어진다. (0 < A, B < 10의 만승)
출력
첫째 줄에 A+B를 출력한다.
#include<stdio.h>
#include<string.h>
void reverse (char arr[])
{
int len = strlen(arr);
for (int i = 0; i < len / 2; i++) {
char temp = arr[i];
arr[i] = arr[len - i - 1];
arr[len - i - 1] = temp;
}
}
int main(void) {
char A[10002] = { 0 };
char B[10002] = { 0 };
char res[10003] = { 0 };
int carry = 0, i;
scanf("%s %s", A, B);
reverse(A);
reverse(B);
int len = strlen(A) > strlen(B) ? strlen(A) : strlen(B);
for (i = 0; i < len; i++)
{
int sum = A[i] - '0' + B[i] - '0' + carry;
while (sum < 0) sum += '0';
if (sum > 9) carry = 1;
else carry = 0;
res[i] = sum % 10 + '0';
}
if (carry == 1) res[len] = '1';
reverse(res);
printf("%s", res);
return 0;
}
#include<string.h> : 문자열 기반함수를 사용할 수 있게끔 헤더선언.
void reverse (char arr[ ]) : 배열을 함수의 인자로 전달 받을때 사용 char arr[ ] (매개변수 선언 에서는 char * arr과 동일) <주의> 문자열을 인자로 받는데, int형을 쓰지 않도록 주의 하자!
char A[10002] = { 0 }; : 널문자까지 포함해서 배열의 길이는 10002 ( 왜냐! 10의 1승은 2자리, 10의 3승은 4자리소요, 그래서 10의 만승은 10001자리 수가 나오고, 널문자까지 포함하여서 10002가 배열의 길이)
그리고 널문자(0값으로) 초기화
char res[10003] = { 0 }; : 999 더하기 999 하면, 4자리 출력값이 나오고, 9999더하기 9999하면 5자리 출력결과 값이 나옴. 이 res배열은 계산 결과를 저장해줄 배열이므로 10003자리로 길이 설정을 해준다.
int carry = 0; : carry는 자리올림
int len = strlen(A) > strlen(B) ? strlen(A) : strlen(B); : 조건연산자를 사용하였는데, 어느자리 숫자까지 더해야하는지는 큰수의 자릿수 만큼 덧셈이 이루어져야 한다. 예를들어 123 하고 9가 있는데 한자릿수 만큼만 덧셈이 이루어 질수는 없는 노릇이기 때문이다.
A[ i ] - '0' 의 형태는 :문자는 아스키코드로 인해 십진수로 변형될 수 있는데, 각자리(A[ ], B[ ])에 문자 0을 빼주고 그것을 int형 으로 저장해 줌으로써 문자에서 숫자로 저장을 할 수있는것이다.
if (sum > 9) carry = 1; : carry는 자리 올림이니 다음 반복문 돌때 1 더해주면 된다...(즉, 자리올림이니까 다음연산에서 1더해주는 것임)
res[i] = sum % 10 + '0'; : 예를 들어 9랑 3을 더할때 12란 결과가 나오는데, 이 12를 10으로 나눈 나머지는 2이므로 그자리(그 해당하는 인덱스 넘버)에 들어가야 할 수가 나온다.
reverse(res); : 뒤집혔던 수를 다시 뒤집어줘 원래 상태로 돌려준다.
if (carry == 1) res[len] = '1'; : 다시 문제를 풀던 중 틀린 부분인데, 만약 반복문이 끝날때에 carry의 값이 1이였다면, 자리올림에 의해 가장 앞자리가 1이 되야 한다는 것이다. 그런데 문자열의 앞자리 이므로 숫자 1 이 아닌, '1' 문자 1로 문장을 작성 하여 주는게 옳다.
void reverse (char arr[ ]) 이 함수를 만들어준 이유는
예를 들어
1, 2, 3, 4...........번째의 배열 자리라 하고,
arr1[5]:7 5 3,
arr2[5]:7 3 4 을 더한다 했을 때,
결과값: 1 4 8 7 처럼, 자릿수가 증가 하면 배열의 인덱스들이 뒤로 한칸씩 밀려나는 걸 볼 수있다.
이러한 이유때문에, 배열요소의 앞과 뒤를 뒤집어줘 이런 불편함 없이 조금 더 편하게 연산과정을 진행 해주려 하고있다.
(거꾸로 뒤집어 연산을 해주면 자리 올림을 통해 조금더 자연스러운 연산을 진행할 수있다.)
<오래 생각했던 것>
res[i] = sum % 10 + '0'; 의 문장에서 '0'을 왜 더해 줄까를 예상보다 조금 오래 생각하였다. 아무렇지 않게 넘어가듯 이해하면 자연스럽게 이해되는듯 했지만, 뭔가 좀 아쉬워 생각을 조금 더 해보았다.
우선, 예를 들어서 sum % 10의 값이 4라고 해보자. 그럼 이 4라는 숫자는 문자가 아닌 십진수라는것을 위 코드들을 보면 알 수 있을 것이다.
그럼, res[i] = 4+'0'인데 이값은 십진수 상으로는 52이고 문자상으로는 4라고 표현이된다.
처음에는 왜 52라는 십진수를 왜 넣어줄까? 라는 생각을 좀 하였었는데, 우리가 처음 A[i] - '0' 을 통해 숫자형태의 문자에 문자0을 빼줌으로써 그 형태에 해당하는 숫자를 십진수로 얻을 수 있었다.
지금은 그와 반대로 십진수 형태의 숫자를 숫자형태의 문자로 변환해주어야 한다. 그러므로 48('0')을 더해줌으로써 다시 십진수에서 숫자형태의 문자로 돌아간것이라 생각할 수있다. '0'을 더해줌으로써 이 문자열안에서 문자 4로 존재할 수 있는것이다. 만약 십진수 4가 그대로 문자로 변환되게 된다면 ^D(EOT)와 같은 표식의 문자가 출력시 나오게 될것이다.
<참고>
#include<stdio.h>
#include<string.h>
int main(void)
{
int arr[6] = { 0 };
printf("%d\n", sizeof(arr) / sizeof(int));
char arr2[7] = { 'G','H'};
printf("%d\n", sizeof(arr2) / sizeof(char));
char arr3[7] ={'a','ppe'};
printf("%d", strlen(arr3));
return 0;
}
char arr2[7] = { 'G','H'};
printf("%d\n", sizeof(arr2) / sizeof(char)); 의 출력값은? 7이다. 이는 그냥 단순! 배열의 길이를 나타내는것이고,
char arr3[7] ={'a','ppe'};
printf("%d", strlen(arr3)); 의 코드는 문자열의 길이를 나타내는것!
즉 apple영단어(알파벳 하나하나 구분되어있는)가있다면 5가 문자열의 길이로 나올것이다.
책으로 공부를 하던도중 함수내에서는 인자로 전달된 배열의 길이를 계산할 수 없다. 라는 사실을 알게되었고, 첫번째 코드블록에서 문자열을 인자로 받고 그에 해당하는 문자열의 길이를 계산하는 것을 볼 수 있는데, 바로 여기서 책과는 조금 다르다 라는 생각을 하였고, 스스로 정리를 조금 해보고자 바로위의 코드를 작성해 보았다.
그 결과 배열의 길이와 문자열의 길이는 다른 개념이다라는 것을 다시 확립하였고,
정답코드가 이상이 없다는것을 알 수있었다.