선생님.....또 질문이요......

미해결질문
최윤성 프로필

선생님 자꾸 질문이 너무 많아서 정말 죄송합니다.

열심히 공부하려다 보니 그렇구나로 이해해주시면 정말 감사하겠습니다.

getchar();에 대해서는 이해가 됐습니다. 친절한 설명 정말 감사합니다.

질문 한방에 다 할게요

1. 한글 동시입력에 대해서 답해주셨는데, 말씀하신 다른 부분이란, 제가 어찌 설정할 방법이 없는건가요? 혹여나 설명가능하거나 제가 참고할 만한 글이 있다면 링크라도 달아주시면 정말 감사하겠습니다.

2. 비밀번호 수정에 관한 코드도 정말 감사합니다. 써주신대로 이해가 됐습니다. 하나 더 질문이 있는데, (도통 코드를 짜지 못하겠어서요). 백스페이스바를 계속 입력할수도 있지 않습니까?

i=0이 되더라도 말이죠. 그럴때 오류가 안나게하기 위해서는 어떤 코드를 짜면 좋을까요? (그냥 선생님의 정확한 생각으로 코드를 알려주시면 정말 감사하겠습니다.)

3. 줄바꿈 문자 입력에 관한 내용인데요.

선생님께서 첨부해주신 코드를 사용해도 엔터를 입력하면 쓰레기 값이 입력됩니다. 제 코드를 비교해도 다른 점이 없는데 말이죠....... 어떤것이 문제인지 코드 올릴테니 봐주세용 ㅜㅠㅜㅠ

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define max 1000

// 비밀번호를 입력받아서
// 맞는 경우? 일기를 읽어와서 보여주고, 계속 작성할 수 있도록 합니다.
// 틀린 경우? 경고 메시지를 표시하고, 종료합니다.

int main_4()
{
	char line[max]; // 불러오기를 했을 때, 불러올 내용을 저장할 곳(변수)
	char contents[max]; // 일기장에 입력할 내용.
	char password[20]; // 비밀번호
	int c; // getch 함수의 리턴값을 검사할 변수.

	printf("'비밀일기'에 오신 것을 환영합니다.\n");
	printf("비밀번호를 입력하세요. : ");

	// getchar();와 getch();란? : 한 글자씩 입력하는 함수. 널문자까지 문자로 인식한다.
	// getchar(); : Enter를 입력해야 동작을 한다.
	// getch(); : 키 입력만 하면, 바로바로 동작을 한다.

	int i = 0;
	while (1) { // for 구문을 써도 된다.
		c = getch(); // 입력한 문자들이 getch로 바로바로 입력이 되어, 한 글자씩 변수 c에 저장된다.
		if (c == 13) { // 입력한 문자가 Enter(줄바꿈 : \n)라면.  (Enter의 아스키코드가 13이다.)
			password[i] = '\0'; // i번째에 데이터를 널문자(끝낼수 있도록)를 넣는다.
			/*참고로, getch():는 한 글자씩 입력하는 함수인데, 응용해서 한 줄의 문자를 입력하는 함수지만, 더 응용해서 여러줄을 입력하기도 한다.
			줄바꿈을 할 때 Enter를 입력하고, 여러 줄의 문장을 끝낼 때 ctrl+z를 입력한다.
			Enter로 줄바꿈을 하면 입력될 데이터는 '\0'이지만, ctrl+z로 줄바꿈을 하면 -1을 리턴값으로 가진다. 그래서 -1을 위해서 int형 변수로 선언해야한다.*/
			break; // 비밀번호 입력 종료.
		}
		else if (c == 8) { // 백스페이스바를 입력하면, 즉 비밀번호를 지우면 (백스페이스바의 아스키코드가 8이다.)
			password[i - 1] = '\0'; // i번째에서 Backspace를 입력하는 것이니, 그 전자리인 'i-1'번째 자리의 데이터를 지워야한다.
			printf("\b \b");  /*\b는 현재 데이터를 입력하는 위치에서 왼쪽(전)으로 커서를 이동시켜주는 변환문자.
				그러니, 왼쪽으로 한번 커서 이동후에, 스페이스바를 입력하여 빈칸이 되게 만들어주고, 스페이스바를 입력했으니 다시한번 뒤로 커서가 이동해야한다.*/
			i = i - 2; // 'i-1'번째 데이터를 지웠으니, 'i-2'번째 데이터까지만 입력이 완료된다. 44번줄에 i++이 있으니, 이렇게 입력해주는 것이 옳다.
			
		}
		else { // Enter를 입력하지 않으면.
			password[i] = c; // getch를 써서 계속 입력하여 c에 저장된 글자들이 password 배열에 저장된다.
			printf("*"); // 입력할 때마다, 비밀번호는 감추고, 대신 '*' 요놈을 출력할 것이다.
		}
		i++;
		
	}

	char* fileName = "c:\\Users\\최윤성\\Desktop\\secretdiary.txt";  
	FILE* file = fopen(fileName, "a+b"); // "a+b"는 파일이 없으면 생성하고, 있으면 append(뒤로 내용을 추가)한다는 의미.

	printf("\n\n==== 비밀번호 확인 중.... ====\n\n");
	if (strcmp(password, "skehzheld") == 0) { // 1. 비밀번호가 맞다면 (strcmp는 문자열 함수를 보면 복습할 수 있다.)
		printf("==== 비밀번호 확인 완료 ====\n\n");

		if (file == NULL) {
			printf("*****파일 열기 실패*****\n\n");
			return 1;
		}
		else printf("*****파일 열기 성공*****\n\n"); // 파일 개방.

		while (fgets(line, max, file) != NULL) {
			printf("%s", line);
		} // 파일을 불러온다. 처음 쓰면 아무것도 불러올 것이 없을 것이고, 쓴 문장이 있었다면, 썼던 문장들이 불러오게 될 것이다.
		printf("\n\n내용을 계속 작성하세요. 종료하시려면 \"끝\"을 입력하세요.\n\n");

		while (1) {
			scanf("%[^\n]", contents); // 줄바꿈(\n)이 나오기 전까지, 모든 문자열을 다 입력한다 뜻의 변환 문자이다. 즉, 한 문장씩 저장을 하겠다는 의미.
			getchar(); // 입력한 줄바꿈(Enter:\n)을 Flush(버림) 처리한다.
			if (strcmp(contents, "끝") == 0) {
				printf("비밀일기 입력을 종료합니다.\n\n");
				break;
			}
			// 무한반복이니, scanf로 입력하는 모든 문장들은 "끝"이 나오기 전까지, 한 문장씩 전부 기억한다.
			fputs(contents, file);
			fputs("\n", file); // 입력된 문장들은 바로바로 저장이 된다. "끝"을 입력하여 종료하기 전까지 계속.
		}
	}
	else printf("==== 비밀번호가 틀렸어요. ====\n"); // 2. 비밀번호가 틀리다면. 틀렸다고 말하고. 바로 밑으로 항해서
	
	int res = fclose(file);
	if (res != 0) {
		printf("\n*****파일이 정상적으로 닫히지 않았습니다.*****\n\n");
		return 1;
	}
	else printf("\n*****파일이 정상적으로 닫혔습니다.*****\n\n"); // 결국 파일이 종료된다. 파일 닫기.

	return 0;
}

엔터 입력마다 다른 현상의 오류가 납니다.

나도코딩 프로필
나도코딩 4달 전

안녕하세요?

열심히 하시는 모습 정말 보기 좋아요 ^^

1. 한글로 비밀번호 입력 시 키 입력마다 바로 * 이 표시되는 것은, 한글은 조합형 글자라서 글자가 조합되고 나서야 하나의 문자 (크기는 2byte 일지언정) 로 입력이 되어서요. 몇 가지 방법을 생각해 보았지만 마땅한 방법이 떠오르진 않네요. 하지만 일반적으로는 사용자로부터 입력을 받을 때 scanf 등을 통해 모두 입력을 받고 문자열을 비교하도록 한답니다. 예제에서는 일부러 실제 비밀번호 입력하는 것처럼 보이기 위해 getch 를 사용하여 효과를 준 것일 뿐이라서요 ^^ 학습하시는 것은 좋지만 이 부분에 대해서는 너무 자세하게 들어가지 않으셔도 될거라 생각합니다.

2. 비밀번호 입력 시 백스페이스를 계속 입력할 때는 더 이상 글자가 사라지는 것을 막기 위하여 index 체크를 해줘야겠네요. 기존 코드에 i-- 하는 부분을 추가하면 됩니다.

else if (c == 8) // BackSpace -> 뒤로
{
	if (i >= 1) // 직전 입력한 값을 null 처리
	{
		password[i - 1] = '\0';
		printf("\b \b");
			i -= 2;
	}
	else // 지울 글자가 없는 경우 index 를 맞춰주기 위해 i - 1 처리
	{
		i--;
	}
}

3. 엔터가 입력 안되는 현상은 추적이 필요해 보이네요.

우선 실제 텍스트 파일에 저장이 잘 되는지도 먼저 확인해 보시구요.

https://www.w3resource.com/c-programming-exercises/file-handling/c-file-handling-exercise-3.php

위 링크에 있는 예제 코드로 실행해보시겠어요? 

아래 껍데기 코드에 넣으면 됩니다. 파일 경로는 원하시는 것으로 바꾸시구요.

동작은 5줄을 입력 받아서 5줄을 출력하고 파일에 저장하는 것인데,

실행 후에 파일에 정말 엔터를 포함하여 잘 저장되는지,

그리고 엔터를 포함한 내용이 cmd 창에 잘 표시되는지를 확인하면 됩니다.

잘 된다면 아래 코드를 응용하여 기존 프로젝트에 적용해볼 수 있겠지요.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    .... 링크에 있는 코드.... scanf 는 scanf_s 로 변경...
    return 0;
}

감사합니다.

지식공유자 되기
많은 사람들에게 배움의 기회를 주고,
경제적 보상을 받아보세요.
지식공유참여
기업 교육을 위한 인프런
“인프런 비즈니스” 를 통해 모든 팀원이 인프런의 강의들을
자유롭게 학습하는 환경을 제공하세요.
인프런 비즈니스