개발자
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #define NO_STD 5 #define NO_SUB 4 struct ICT { int num; char name[20]; int score[NO_SUB]; int sum; float arg; int no; float total; char grade; }; int main(void) { int i, j; struct ICT std[NO_STD]; for (i = 0; i < NO_STD; i++) { std[i].sum = 0; printf("학번을 입력하세요 :"); scanf_s("%d", &std[i].num); printf("이름을 입력하세요 :"); scanf_s("%s", &std[i].name, sizeof(std[i].name)); for (j = 0; j < NO_SUB; j++) { printf("%d번째 학생의 %d번째 과목 점수를 입력하세요 :", i + 1, j + 1); scanf_s("%d", &std[i].score[j]); std[i].sum += std[i].score[j]; } std[i].arg = (float)std[i].sum / NO_SUB; printf("결석을 입력하세요 :"); scanf_s("%d", &std[i].no); std[i].total = std[i].arg - std[i].no * 0.5; if (std[i].total > 89) { std[i].grade = 'A'; } else if (std[i].total > 79) { std[i].grade = 'B'; } else if (std[i].total > 69) { std[i].grade = 'C'; } else { std[i].grade = 'F'; } } printf("순서\t학번\t이름\t중간\t중간2\t중간3\t중간4\t합계\t평균\t결석\t최종\t학점\n"); for (i = 0; i < NO_STD; i++) { printf("%d\t%d\t%s\t", i + 1, std[i].num, std[i].name); for (j = 0; j < NO_SUB; j++) { printf("%d\t", std[i].score[j]); } printf("%3d\t%.2f\t%d\t%.2f\t%s\n", std[i].sum, std[i].arg, std[i].no, std[i].total, std[i].grade); } } 에서 F11.로 한단계씩 디버그하기를 하면은 다 잘되는데 마지막 printf에서 예외 발생(0x00007FFFCFBAAC87(ucrtbased.dll), 2차중간고사.exe): 0xC0000005: 0xFFFFFFFFFFFFFFFF 위치를 읽는 동안 액세스 위반이 발생했습니다.. 이라고 뜨면서 합계부터 출력이 안됩니다. 이거 혹시 어떻게 해결해야되는지 아시나요....
답변 2
인기 답변
printf("%3d\t%.2f\t%d\t%.2f\t%s\n", std[i].sum, std[i].arg, std[i].no, std[i].total, std[i].grade); -> printf("%3d\t%.2f\t%d\t%.2f\t%c\n", std[i].sum, std[i].arg, std[i].no, std[i].total, std[i].grade); 로 하시면 됩니다. %s는 string을 찍는 거라서, 1byte(char)씩 움직이면서 0(null)이 나올때 까지 계속합니다. 0~NO_STD-2 까지는 memory layout상, { num, ..., grade } { num, ..., grade }의 형태라서, num에서 몇개 더가면 0이 되는 byte가 나와서 넘어갈 수 도 있는데, std[NO_STD-1] 의 { num, ..., grade } 다음에는 그냥 쓰레기 값입니다. 이경우에는 후속으로 나오는 byte중, 어떤 것이 0이 될지 몰라서 계속 접근하다가, segmentation fault가 나게 됩니다.(운이 좋으면 안 날 수도 있어요 ㅎㅎ) 그래서 data형이 char이니까, %c 를 해주셔야 안전합니다. C는 굉장히 low-level 언어이기 때문에, 어느 영역까지 읽을 것인지에 대한 guard line을 정확히 해주지 않으면, 쉽게 crash 나게되고, 심지어 보안의 허점이 되곤 합니다. 그래서 buffer의 크기를 제한 할 수 없는 strcpy, sprintf 보다 strncpy, snprintf()와 같이 정해진 크기의 buffer안에서 operation 하는 습관을 들이시는 것이 좋습니다.
doublecicken1
작성자
명지전문대학교 정보통신공학과 • 2023년 11월 07일
너무 감사합니다. 프로그래밍이라는게 하나의 단어만 틀려도 안돌아가니 어렵네요.그래도 내가 원하는대로 프로그램이 돌아갈때 정말 기쁜것같습니다. 앞으로 열심히 공부해서 좋은 프로그래머로 성장하겠습니다.
인기 답변
ChatGPT 로 풀어봤어요... ------------ C 언어 코드인데, 마지막에 에러가 뜨는데 수정해 줘 ..... 코드 고대로.... ------------ ==> 주어진 C 언어 코드에서 마지막 줄에 에러가 발생하는 이유는, printf 문장의 형식 지정자와 실제 인수의 타입이 일치하지 않기 때문입니다. 구체적으로, "%s\n" 형식 지정자를 사용하여 문자열을 출력하려고 하지만, 실제로는 문자 하나('A', 'B', 'C', 'F')만을 출력하려고 합니다. 따라서, 아래와 같이 수정하면 됩니다. printf("%d\t%d\t%s\t", i + 1, std[i].num, std[i].name); for (j = 0; j < NO_SUB; j++) { printf("%d\t", std[i].score[j]); } printf("%3d\t%.2f\t%d\t%.2f\t%c\n", std[i].sum, std[i].arg, std[i].no, std[i].total, std[i].grade); 위 코드에서는 마지막 줄의 printf 문장에서 "%s\n"을 "%c\n"으로 수정하여 문자 하나를 출력하도록 변경하였습니다. 이제 코드를 실행하면 에러 없이 원하는 결과를 출력할 수 있을 것입니다. ------------ 정확히 이승현님이 말씀하신 부분을 지적하고 있네요.. ㅎㅎ
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직자들의 명쾌한 답변을 얻을 수 있어요.
이미 회원이신가요?
커리어리 AI 봇
GPT가 달아주는 답변입니다.
2023년 11월 07일
마지막 `printf`함수에서 포맷 스펙피커 `%s\n`를 사용하여 학점을 출력하고 있습니다. 하지만 이는 문자열을 가리키기 때문에 오류가 발생합니다. `std[i].grade`는 단일 문자이므로, 해당 부분의 포맷 스펙피커를 `%c\n`으로 변경해야 합니다. 그러므로, 마지막 `printf` 함수 호출은 다음과 같아야 합니다: ```c printf("%d\t%d\t%s\t", i + 1, std[i].num, std[i].name); for (j = 0; j < NO_SUB; j++) { printf("%d\t", std[i].score[j]); } printf("%3d\t%.2f\t%d\t%.2f\t%c\n", std[i].sum, std[i].arg, std[i].no, std[i].total, std[i].grade); ``` 이렇게 수정하면 코드가 정상적으로 실행되어야 합니다.
지금 가입하면 모든 질문의 답변을 볼 수 있어요!