C언어 질문있습니다.

2080fresh의 이미지

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef struct student {
	int ID;
	char name[10];
	int score[3];
}INFO;
 
INFO *p;
 
void main()
{
	INFO std[100];
	int n, a = 1;
	p = (INFO*)malloc(sizeof(INFO));
 
	while (1)
	{
		printf("Select option(1.Insert, 2.Search, 3.Exit) : ");
		scanf_s("%d", &n);
 
		if (n == 1) {
 
			p = (INFO*)realloc(p, sizeof(INFO)*a);
			printf("student ID : ");
			scanf_s("%d", &std[a].ID);
 
			printf("student name : ");
			fgets(std[a].name, 11, stdin);
 
			printf("student score<kor eng math> : ");
			scanf_s("%d %d %d", &std[a].score[0], &std[a].score[1], &std[a].score[2]);
 
			a++;
			printf("================================\n");
		}
 
		else if (n == 2) {
 
			int i, finder;
			int ave;
			printf("student ID : ");
			scanf_s("%d", &finder);
 
			for (i = 0; i >= a; i++) {
				if (finder == std[a].ID) {
					ave = (std[a].score[0] + std[a].score[1] + std[a].score[2]) / 3;
					printf("student name : %s\nscore<for eng math> : %d %d %d\naverage : %d", std[a].name, std[a].score[0], std[a].score[1], std[a].score[2], ave);
				}
			}
		}
	}
}
 
n=1일때만 구현했는데요, n=1입력받을때 학생정보를 추가시키는 프로그램입니다. 
문제는 n==1 if문에서 fgets가 씹힙니다. NULL값을 어디선가 빼거나 추가시켜야될 거 같은데 문제가 뭔지 궁금합니다!
세벌의 이미지

질문은 소스코드 태그 밖으로 빼 주셔요. 소스 코드는 code 태그 안에 잘 넣으셨네요.
씹힌다는 표현은 어감이 좀 그러하네요. 무슨 뜻인지 잘 모르겠음.
컴파일할 때 에러 메시지 뿐 아니라 경고도 잘 살펴보셔요. 문제 해결의 힌트를 발견할 수 있습니다.

raymundo의 이미지

scanf 가 %d 포맷을 처리하면서 숫자를 입력받는데 마지막에 엔터를 친 게 입력 버퍼에 남아 있다가,
fgets 가 호출될 때 입력버퍼에 남아 있는 \n 을 보고 거기까지만 읽고 끝나버려서 그렇습니다.
scanf 직후에 getchar()를 한 번 부르든가 해서 입력버퍼에 남은 개행 문자를 삭제해보세요.

좋은 하루 되세요!

익명 사용자의 이미지

가장 깔끔한 방법은 다음처럼 내부적으로 먼저 한 번 체크를 해서 최대 두 번 시도를 하는 함수를 만들어놓고 그걸 불러다가 쓰는 것입니다.

char* my_fgets(char* str, int num, FILE* stream)
{
    char* ret = fgets(str, num, stream);
    if ( !ret || !str || *str ) return ret;

    return fgets(str, num, stream);
}

getchar(); 를 불러 버리는 방식은 숫자를 입력할 때 입력 완료를 엔터가 아닌 Ctrl+D(도스/윈도우에서는 Ctrl+Z 치고 엔터)로 마무리할 경우 문제가 됩니다. 같은 이유로 scanf("%d ", ...); 식으로 버리는 법도 생각해 볼 수 있지만 첫번째와 마찬가지의 문제가 있습니다.

또, fflush(stdin);이나 __fpurge(stdin);을 사용하는 방법은 비표준 방식이기 때문에 컴파일러마다 돌아가지 않을 수 있는 문제가 있습니다. 그래서 현실적으로 고려해 볼 수 있는 방법은 제가 위에서 제시한 방법 뿐입니다.

익명 사용자의 이미지

코드 정정합니다.

char* my_fgets(char* str, int num, FILE* stream)
{
    char* ret = fgets(str, num, stream);
    if ( !ret || num <= 0 || *str > '\n' ) return ret;
 
    return fgets(str, num, stream);
}

테스트해 본 코드: https://ideone.com/SMmC1r

 의 이미지

익명 사용자 wrote:
getchar(); 를 불러 버리는 방식은 숫자를 입력할 때 입력 완료를 엔터가 아닌 Ctrl+D(도스/윈도우에서는 Ctrl+Z 치고 엔터)로 마무리할 경우 문제가 됩니다. 같은 이유로 scanf("%d ", ...); 식으로 버리는 법도 생각해 볼 수 있지만 첫번째와 마찬가지의 문제가 있습니다.

정확히 어떤 문제가 생기는 것인지 자세히 설명해주실 수 있으신지요? getchar를 사용했을 때 생길 수 있는 가장 생각하기 쉬운 문제 상황은 사용자가 (프롬프트를 무시하고) "1234name" 이런 식으로 student ID와 name을 연달아 입력하는 것이죠. getchar가 'n'을 먹어 버릴 테니까요. 물론 적절히 ungetc을 하면 되기는 합니다.

부적절하게 입력된 공백 문자를 처리하는 것뿐이라면 fgets 이전의 scanf에서 서식 문자열에 공백 문자를 주는 방식으로 더 간단히 구현할 수 있지요. 주어진 질문의 경우엔 이름이 공백 문자로 시작하는 사람이 없다고 가정할 수 있다면 괜찮은 해결책이라고 생각합니다.

설명해주신 상황은 사용자가 (프로그램이 예상하지 못한 시점에서) EOF를 날리는 상황인 것 같은데, 물론 그렇게 stdin이 예상치 못한 시점에 끊기는 상황을 고려할 수 있다면 좋겠지만 주어진 질문하고는 조금 다른 문제인 것 같습니다. 그냥 fgets의 반환값을 체크하면 되니까요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.