F.R.I.D.A.Y.

지식인 : 성적을 xls(엑셀)로 출력하기 본문

외부활동/지식in

지식인 : 성적을 xls(엑셀)로 출력하기

F.R.I.D.A.Y. 2019. 1. 16. 21:15
반응형

Q.성적을 xls 파일로 출력하기

 https://kin.naver.com/qna/detail.nhn?d1id=1&dirId=1040101&docId=318998069

 ※ xls 파일은 현대의 xlsx 포맷과 달리 바이트 코드로 이루어져 있기 때문에 탭문자와 줄바꿈 문자를 통해 만들 수 있다고 한다.



A.

 일단 문제 확인을 위해 빌드를 진행한 결과 아래와 같은 12개의 경고와 2개의 오류가 발생했습니다.

 경고의 경우 빌드하는데 있어 큰 문제가 없지만 잠재적인 위협/문제가 될 수 있으니 가급적이면 경고도 없애는 편이 좋겠군요.

 경고와 달리 오류는 존재하면 빌드를 진행하지 못합니다. 프로그램 실행에 있어 문법적인 문제가 발생한것이기 때문이죠.


오류 두 개가 존재하는 모습. 경고는 간편성을 위해 해제 해놓은 상태.


 확인 해보니 print_subject_output() 함수는 사용되는 위치보다 아래에 위치합니다. 따라서 원패스 컴파일러[각주:1]인 MSVC에서는 문제가 발생합니다. 따라서 사용되는 부분보다 위에 선언을 하던지, 아니면 함수 원형을 소스코드 상단에 작성하는 방법으로 문제를 해결할 수 있습니다.


void print_subject_output(float* Kor, float * Eng, float* Math, int Sum[], FILE* fp);



 두번째 오류 역시 마찬가지의 이유로 발생한 오류이고 같은 방법으로 해결할 수 있습니다.




 다음으로 subject_output() 함수입니다. 함수네임으로 유추해보았을 때, 이곳을 통해 관련 데이터를 처리하는 듯 싶습니다.


 이렇게 작성하신 분께는 구조를 잘못 세웠다고 말씀드리고 싶습니다. 최대크기는 최대 크기대로, 최소크기는 최소크기대로 묶어 처리하는 것이 좋고, 과목별로 처리하면 굉장히 불필요한 코드가 늘어나게 됩니다.


void subject_output(student Student[], int cnt, FILE*fp) {
	const int KOREAN = 0;
	const int ENGLISH = 1;
	const int MATH = 2;

 	float max[3], min[3], total[3];
	for (int i = 0; i < 3; ++i) {
		max[i] = 0.0f;
		total[i] = 0.0f;
		min[i] = 1000.0f; // 1000 이상인 점수가 나올 수는 없기 때문에 값 비교를 위해 1,000 넣음.
	}

	for (int i = 0; i < cnt; ++i) {
		// 각 subject의 최대 값 구하기
		if (Student[i].Kor > max[KOREAN]) max[KOREAN] = Student[i].Kor;
		if (Student[i].Eng > max[ENGLISH]) max[ENGLISH] = Student[i].Eng;
		if (Student[i].Math > max[MATH]) max[MATH] = Student[i].Math;

		// 각 subject의 최소 값 구하기
		if (Student[i].Kor < min[KOREAN]) min[KOREAN] = Student[i].Kor;
		if (Student[i].Eng < min[ENGLISH]) min[ENGLISH] = Student[i].Eng;
		if (Student[i].Math < min[MATH]) min[MATH] = Student[i].Math;

		total[KOREAN] += Student[i].Kor;
		total[ENGLISH] += Student[i].Eng;
		total[MATH] += Student[i].Math;
	}

	print_subject_output(KOR, ENG, MATH, SUM, fp);
}



 수정 결과는 위와 같습니다. 그런데 이젠 print_subject_output() 함수와 호환이 되지 않는군요. 이젠 이  print_subject_output() 함수를 건드려봅시다. 기존 코드는 다음과 같습니다.


void print_subject_output(float* Kor, float * Eng, float* Math, int Sum[], FILE* fp)// 전달받은 과목별 최대, 최소, 합계 배열을 이용하여 결과를 화면과 파일에 출력 
{ 
  fprintf(fp,"과목\t최고\tw최저\t평균\n"); 
  fprintf(fp, "국어\t%d\t%d\t%.1f\n", Kor[0], Kor[1], Sum[0] / 3.0); 
  fprintf(fp, "영어\t%d\t%d\t%.1f\n", Eng[0], Eng[1], Sum[1] / 3.0); 
  fprintf(fp, "국어\t%d\t%d\t%.1f\n", Math[0], Math[1], Sum[2] / 3.0); 
} 



이렇게 작성이 되어있으니 호환에 맞도록 print_subject_output() 함수를 고쳐봅니다.


void print_subject_output(float* max, float *min, float* total,FILE* fp)// 전달받은 과목별 최대, 최소, 합계 배열을 이용하여 결과를 화면과 파일에 출력 
{
	// 0 : 국어
	// 1 : 영어
	// 2 : 수학
	fprintf(fp, "과목\t최고\tw최저\t평균\n");
	fprintf(fp, "국어\t%d\t%d\t%.1f\n", max[0], min[0], total[0] / 3.0);
	fprintf(fp, "영어\t%d\t%d\t%.1f\n", max[1], min[1], total[1] / 3.0);
	fprintf(fp, "수학\t%d\t%d\t%.1f\n", max[2], min[2], total[2] / 3.0);
}



 인자의 형태가 변경되었으니 함수 원형도 따라서 바꿔줘야겠죠?



 위 작업을 모두 했다면 정상적으로 출력이 되어야 합니다. 테스트를 진행한 후 파일을 열어보니 다음과 같이 엉망이 되어있습니다.

어째서일까요? 


 처음 오류 목록을 볼까요? 12개의 경고 항목이 있습니다. 해당 경고 항목들을 보면 전부 C4477 오류들입니다. 이 오류들은 간단히 출력하는 대상과 출력방식의 차이, 즉 자료형의 차이로 인해 발생합니다. 코드들을 보면 데이터는 float 자료형으로 이루어진데 반해 출력할 때는 %d, int 정수 자료형으로 출력하라고 합니다. 그래서 발생하는 문제들입니다. 이제 이 문제를 해결하기 위해 잘못된 부분을 고칩니다.



 그런데 이상합니다. 다 잘 나오는데 평균 부분이 말이 안됩니다. 그래서 평균을 구하는 코드를 봤습니다.



 이제보니 (float)cnt. 즉 사람 수로 나누고 있던겁니다. 평균이라 함은 과목수로 나누어야 하는데 귀여운 실수를 했군요. 과목 수 3으로 나누어줍니다.

 이제 잘 만들어졌군요.



 프로그램을 배우며 여러 시도를 하는 것은 좋은 습관입니다. 그러나 기본기가 갖춰지지 않은 상황에서 무작정 만들려고 하면 좋은 습관을 들일 수 없을 뿐더러 문제를 야기하고 새로운 것을 배우는 데도 힘이 듭니다. 배울 때는 힘들겠지만 하나하나 제대로 배워야합니다. 어떻게 사용해야하는지를 꼭 참고하고 문법을 꼭 숙지하는 것이 좋습니다. 문법을 피해서 프로그램을 짜는 것은 문법을 모두 알고 능수능란하게 다룬 뒤의 일입니다.


 아래는 모든 수정을 거친 완성된 코드입니다.



  1. 현존하는 대부분의 컴파일러가 성능 문제로 원패스 컴파일을 진행합니다. [본문으로]
728x90
반응형
Comments