왜 runtime error가 뜨는지 모르겠습니다.

hjhj5078 Reply 9 years 30 weeks ago
ㅠㅠ
booksky Reply 9 years 30 weeks ago
문제가 여러군데 존재하네요. 1. 잘못된 array 초기화. arr[1000]=0; 잘못된 초기화 방법입니다. 컴파일러에 따라서 오류를 일으키게 될 것입니다. 2. 잘못된 while 구문 while((a=getchar())!='\n') 마지막줄은 EOF로 끝나게 됩니다. 이렇게 while을 작성하면 마지막 줄은 끝나지 않고 계속 돌다가 결국 접근불가능한 배열 영역에 접근을 하고 segmentation error가 뜨겠죠. 일단 runtime error의 원인은 이거입니다. 3. 잘못된 변수값 int를 가지고는 이 문제를 풀지 못합니다. int는 32비트의 크기를 갖는 변수기때문에, 64비트의 값을 값게되는 int64는 표현할 수 없습니다.
pichulia Reply 9 years 30 weeks ago
하나의 코드에 도대체 몆가지 문제점이 있는건지 모르겠네요ㅋㅋㅋㅋㅋ 하나하나 따져봅시다. 1. 런타임에러의 직접적인 원인은 while((a=getchar()) != '\n') 이 부분입니다. 왜냐하면 입력의 마지막줄은 EOF로 들어올테니까요.. '\n'이 나오지 않기 때문에 저 반복문을 무한정 돌게 됩니다. 2. a=arr[i++]; 이라고 쓰셨는데 arr[i++] = a; 일거같네요. 전자의 경우는 a라는 변수에 arr[i]의 값을 넣겠다는 의미인데..지금 arr 배열에는 아무런 값이 없습니다. 3. 컴퓨터에서 2^3은 "2를 3번 곱한 값"을 의미하는 것이 아닙니다. 2와 3의 bitwise xor 결과값을 출력합니다. 2^3 같은경우는 1을 출력하겠네요. 그러니까 for(c=i;c<=0;c--){ b=b+((10^c)*arr[c]); } 위와 같은 코드는 의도한 것과는 다르게 동작할 것입니다. 4. 위의 반복문... for(c=i; c<=0;c--){ 이렇게 되있는데.. 이 조건을 말로 풀어써보면 "일단 c에다가 i값을 넣고, c가 0보다 작거나 같은 동안 아래의 소스코드를 실행하고, 소스코드 실행이 끝날 때마다 c를 1씩 빼준다." 인데..현재 i가 숫자의 길이? 를 의미할텐데.. 뭔가 이상하죠? i가 0 이상일 때는 아래 반복문을 실행 안하고 그냥 지나가고, i가 0일 때, 그러니까 입력으로 아무 문자도 없을때만 아래 반복문을 "무한번" 실행하게 됩니다. 이게 의도한 동작으로는 보이지 않네요. for(c=i; c>=0; c--) 가 의도하셨던 방향인거 같습니다. 5. 컴퓨터에서 "숫자"를 나타내는 문자의 값은 따로 할당되있습니다. 이를 ASCII Code 값에 의해서 결정되는데.. 예를 들어 숫자 0 을 나타내는 문자는 0 이 아니라 '48'이라는 숫자가 배열의 값에 들어가게 됩니다. 그래서 만약 arr[2] = '3' 이라면..(exp(10,2))*arr[2]; 는 300 이 아니라 5000 이라는 숫자를 나타내게 되네요... 6. 현제 arr[i++] = a; 이렇게 문자를 넣고 계시는데..그럼 arr에 들어가는 숫자의 순서를 볼까요? 얘를 들어 142이 들어갔다고 치면.. arr[0] = '1'; arr[1] = '4'; arr[2] = '2'; 가 되겠네요. 그럼 for(c=2;c>=0;c--)b=b+(exp(10,c))*(arr[c]-'0'); 을 실행시키면 b에는 어떤 값이 들어갈까요? 142를 넣으시려고 했을텐데 안타깝께도 241이 들어가게 됩니다. arr[i-c] 를 곱하던지, 아니면 exp(10, i-c)를 곱해야 입력으로 들어온 숫자가 b에 저장되겠네요... 7. 뭐, 저게 의도했던 동작이라고 치고... 저렇게 하면 음수는 어떻게 표현될까요? 입력값이 음수인 경우 arr[0]에 숫자가 아닌 '-'가 들어가있을테니까 b는 완전 요상한 값이 되서 나오겠네요... 8. 뭐 이래저래 코드 고치고 음수도 고려하고 난리 부르스를 쳤다 해도 문제는 생깁니다. 왜냐하면 현제 b의 자료형은 int인데 int는 값을 저장할 수 있는 범위게 제한되있습니다. 그러니까 9223372036854775807 같은 int64형 숫자는 b에 이상하게 저장이 되서 자료형을 제대로 파악 못하게 될 것입니다. 9. signed byte의 범위는 -255부터 -1까지가 아닙니다. -128부터 127까지이지요....unsigned byte의 범위는 0부터 256까지가 아니라 0부터 255까지입니다. 마찬가지로...다른 signed 변수들의 범위가 다 틀렸어요ㅋㅋㅋ 10. unsigned 로 표현이 가능한 자료형은 unsigned로 표현하는 것을 우선적으로 해달라고 했는데.. 지금같은 경우(그러니까 9번 오류를 수정한 경우) 24 같은 숫자가 들어오면 unsigned byte가 아니라 signed byte라고 출력하겠네요.. 후...힘들었네요.. 음....제가 수업조교가 아니라서 진도가 어떻게 나왔는지 모르겠지만...복습좀 하시고..다른 문제들도 풀어보시고...그리고 예제가 돌아가는지좀 확인해주세요ㅋㅋㅋ 이상입니다.
pichulia Reply 9 years 30 weeks ago
솔직해 말해봐요...이거 저희 조교들 괴롭히려고 질문하신거죠?
hjhj5078 Reply 9 years 30 weeks ago
말씀하신 부분 다 고쳐봤는데 또 런타임 에러뜨네요 ㅋㅋㅋㅋ
booksky Reply 9 years 30 weeks ago
코드에 문제가 참 많아서 이번에도 어디서부터 설명드려야할지 참 난해야네요. 1. 일단 segmentation error가 나는 부분은 for(e=0;e<20;e++) { printf("%s",dec[e]); } 이 부분입니다. 근데 이 부분이 왜 에러가나는지 설명을 드리려면 긴긴 설명충이 등판해야할 거 같습니다. char dec[20]; 이렇게 정의를 내렸으면 dec라는 배열에 19칸(마지막 1칸은 null value가 들어가야하니까)문자열을 넣겠다는 의미입니다. dec[0], dec[1], dec[2] 등등...에 문자열이 들어가는게 아니라, dec[0], dec[1], dec[2] 등에 들어가있는 문자가 뭉쳐서 dec이라는 하나의 문자열을 이루게 되는 것입니다. dec[e]="signed byte/n"; 그렇기 때문에 이런 식으로 문자에 문자열을 넣으려는 시도 자체가 잘못되었습니다. 그렇다고 해서 dec="signed byte/n"; 가 되는 것도 아닙니다. 맨 처음 배열을 선언할 때는 저런 식으로 초기화해 줄 수 있지만, 한번 선언 된 배열은 저런 식으로 값을 집어넣을 수 없습니다.(C언어에서는 그렇습니다. 요즘 나오는 최신 언어는 가능합니다.) 저런 식으로 넣어주려면 string.h에 있는 strcpy라는 함수를 사용해야합니다 2.설명 위의 문제를 해결했다고 할지라도 이 문제를 풀 수 없습니다. double은 64비트 연산자이지만 실제 숫자를 나타내는데 사용하는 비트는 52비트이고 1비트는 부호, 11비트는 자릿수를 나타냅니다. 52비트로 숫자를 표현하기 때문에 int64보다 숫자 표현 범위는 넓지만 표현하는 값을 정확히 표현할 수는 없습니다. 개인적인 사견이지만 지금 어려운 challenge문제에 무리해서 도전하기보다는 C 프로그래밍 기본 지식부터 갈고 닦는게 먼저아닐까 생각됩니다.
hjhj5078 Reply 9 years 30 weeks ago
네 감사합니다. 첨에 2.1이라길래 챌린지 아닌줄 알았어요ㅠㅠ