게시글
질문&답변
2024.05.13
flag
안녕하세요? 질문&답변 도우미 Soobak 입니다. line_flag 는 '각 줄의 시작을 판별하기' 그리고 '중복 계산 방지하기' 를 위해 사용됩니다. 코드의 흐름을 설명드려보면 다음과 같습니다. 처음에는 line_flag 가 false 로 설정되어, '새로운 줄의 시작을 감지하기 위한 상태' 가 됩니다. 이후, 문자를 입력 받기 시작하며, 입력받은 문자에 대하여 '공백 문자가 아닌 경우' line_flag 가 false 라면 새로운 줄의 시작으로 판별하고, n_lines (줄 수)를 1 증가 시킵니다. 이 때, 위에서 말씀드린 line_flag 의 역할 중 '중복 계산 방지하기' 를 위해서, line_flag 를 true 로 변경해주어 같은 줄에서는 줄 수가 증가하지 않도록 합니다. 이어서, 입력받은 문자가 '\n' (개행 문자)인 경우, 하나의 줄이 끝났음을 의미하므로 line_flag 를 false 로 재설정 하여, 다음 줄의 첫 글자가 입력될 때 새로운 줄로 감지할 수 있도록 합니다. flag 사용 패턴에 대한 이해를 위해서는, 질문자님의 생각대로 기능을 구현해보시고, 여러 줄의 입력을 새로운 줄의 입력으로 정확하게 감지하는지, 한 줄에 여러 글자가 있더라도 줄 수를 한 번만 증가시키는지 등에 대해서 테스트를 진행해보시는 것도 이해에 도움이 되실 것 같습니다. 또한, 이러한 '패턴' 은 한 번 학습하고 난 후에는 이해와 활용이 좀 더 쉬워지므로, 처음에는 조금 불편하시더라도 디버깅을 통해 직접 눈으로 코드의 흐름을 확인해보시는 과정을 경험해보시는 것을 추천 드려봅니다.
- 1
- 1
- 24
질문&답변
2024.05.09
포인터 초기화 질문
안녕하세요? 질문&답변 도우미 Soobak 입니다. 포인터 변수를 특정 주소값으로 초기화하는 것은 기술적으로 가능하지만, 실제 응용 프로그램에서는 권장되지 않습니다. (특정 분야 제외) 예시 ) int *p = (int *)0x10000000; // 특정 주소를 가리키는 포인터를 초기화 if (p != NULL) printf("%d", *p); // 그 주소에 저장된 값을 출력 또한, 해당 메모리 주소가 유효한 메모리 주소인지, 혹은 해당 메모리 영역에 접근할 권한이 있는지 등은 프로그램의 실행 환경에 따라서 달라지게 됩니다. 이에 대해서는, 0x00000000 과 같은 형식의 메모리 주소는 '가상 메모리' 이며, 이를 실제 메모리 주소(물리 메모리 주소)와 매핑하고 관리하는 것은 운영체제가 담당한다는 점, 따라서 위와 같은 접근은 예기치 못한 행동이나 오류가 발생할 수도 있다는 점 또한 알아두시면 학습에 도움이 되실 것 같습니다. 때문에, 대부분의 응용 프로그램에서는 포인터를 특정 메모리 주소로 초기화할 이유가 없고, 대신, malloc() , calloc() 과 같은 메모리 할당 함수를 사용하여 동적으로 메모리를 할당하고, 이 주소를 포인터에 저장하여 사용합니다. 메모리와 관련된 내용은 강의 12.1 메모리 레이아웃 훑어보기 에서 보다 자세하게 학습하시게 되며, 공부에 재미가 생기셨을 때 섹션 0 의 강의들을 잠시 복습해보셔도 도움이 많이 되실 것 같습니다.
- 1
- 1
- 44
질문&답변
2024.05.09
디버깅이 강사님 처럼 나오지가 않아요..
안녕하세요? 질문&답변 도우미 Soobak 입니다. 질문자님께서 말씀하시는 '깔끔하게 나오지 않는다' 가 어떤 의미인지 제가 잘 이해하지 못하였습니다. 조금 더 구체적으로 말씀해주시면 명확한 답변을 드릴 수 있을 것 같습니다. 첨부해주신 3장의 이미지 중, 첫 번째 사진이 질문자님의 화면 사진, 두 번째와 세 번째 사진은 강의 화면인 것으로 생각되어, '디버깅 중인 변수에 대한 정보', '메모리 주소' 에 대한 인터페이스를 어떻게 나타나도록 하는지를 궁금해하시는 것으로 생각하고 답변을 드려봅니다. 강의 화면 아래에 나타나는 변수의 이름과 값, 자료형이 나타나는 창은 디버깅을 위한 중단점을 찍으신 후, 상단의 메뉴바에서 Debug 메뉴를 누르신 후, Window 카테고리에서 Local 을, 메모리 주소가 나타나는 창은 Debug > Window > Memory 를 눌러보세요. 혹시나 원하시는 답변이 아니시라면, 궁금해하시는 부분에 대하여 조금 더 구체적으로, 편하게 댓글 남겨주세요.
- 1
- 1
- 37
질문&답변
2024.05.09
출력이 이상한데 이유를 모르겠어요
안녕하세요? 질문&답변 도우미 Soobak 입니다. 코드를 살펴보니, 마지막 while() 반복문 부분에 오타가 발생하셨네요. head 문자열에는 '\n' 문자가 없으므로, 반복문이 종료되지 못하고 계속 실행되다가 잘못된 메모리 접근을 하게 되어 이상한 문자들이 출력되는 것입니다. (예기치 못한 동작) 강의에서의 코드처럼 '\0' 과의 비교로 조건문을 수정해보세요. while (*(head) != '\0') putchar(*(head++));
- 1
- 1
- 42
질문&답변
2024.05.08
코드
안녕하세요? 질문&답변 도우미 Soobak 입니다. 질문자님의 코드가 의도대로 작동하지 않는 가장 큰 문제 중 하나는, 반복문 내에서 getchar() 함수를 반복적으로 호출하고 있기 때문입니다. getchar() 함수는 호출될 때마다 새로운 문자를 입력 스트림에서 읽어옵니다. 따라서, 같은 반복문 안에서 getchar() 을 여러번 호출하면 서로 다른 문자에 대해서 작업을 수행하게 됩니다. 예를 들어, while ((c = getchar()) != STOP) { if (getchar() != ' ') n_chars++; if (getchar() != ' ') n_words++; if (getchar() == '\n') n_lines++; } : 위의 코드의 while() 반복문 내의 3 개의 if() 조건문과 getchar() 함수 부분을 살펴보면, 첫 번째 if (getchar() != ' ') 에서 문자를 읽은 후 공백이 아니면 n_chars 를 증가시킵니다. 두 번째 if (getchar() != ' ') 에서는 새로운 문자 를 읽은 후, 공백이 아니면 n_words 를 증가시킵니다. 세 번째 if (getchar() != '\n') 역시 새로운 문자를 읽은 후, 개행 문자가 아니라면 n_lines 를 증가시킵니다. 따라서, 각 호출에서 다른 문자를 처리하기 때문에 의도한대로 문자, 단어, 줄 수를 세지 못하게 됩니다. bool 자료형 line_flag 와 같은 변수의 주된 목적은 문자가 나타날 때마다 줄 수를 여러 번 세지 않도록 하는 것입니다. line_flag 는 초기에 false 로 설정됩니다. 문자가 공백이 아닌 경우( !isspace(c) ) 처럼 처음 문자가 나타나면 line_flag 가 false 에서 true 로 바뀌고 줄 수가 1 증가합니다. c == '\n' 조건을 만족하면, line_flag 는 다시 false 로 설정됩니다. 즉, line_flag 는 한 줄에 처음 나타나는 공백이 아닌 문자에 대해서만 줄 수를 셀 수 있도록 하며, 그 다음 줄바꿈 문자가 나타날 때까지는 줄 수를 증가시키지 않습니다. 이러한 flag 의 사용에 대해서는 적극적으로 디버깅을 해보시면서 과정 전체를 한 번 눈으로 확인해보시는 과정을 거쳐보시는 것을 권장드려봅니다.
- 1
- 1
- 47
질문&답변
2024.05.07
디버깅 중 루프탈출
안녕하세요? 질문&답변 도우미 Soobak 입니다. 저 같은 경우에는, F9 단축키를 이용해서 반복문 바로 바깥에 새로운 중단점을 찍고 F5 단축키로 이어서 실행합니다. 혹은, 위 과정을 원하는 지점에 마우스 커서를 위치시키고(반복문 바깥 지점) Ctrl + F10 단축키로 커서의 위치까지 디버깅을 실행하고 멈추도록 합니다.
- 1
- 1
- 61
질문&답변
2024.04.29
pixel_color 에서 앞에 0x를 붙이는 이유
안녕하세요, 질문&답변 도우미 Soobak 입니다. 0x 접두사는 해당 숫자가 16진수 형식임을 나타내기 위해서 사용합니다. 언급해주신 부분에서 RGP 색상 값의 Hex Code 는 16진수로 표현되므로, 이를 위해서 앞에 0x 를 붙여주는 것입니다.
- 1
- 1
- 56
질문&답변
2024.04.27
using namespace std;
안녕하세요, 질문&답변 도우미 Soobak 입니다. 명칭 공간을 보다 명확하게 명시하기 위함입니다. using namespace std; 구문은 C++ 표준라이브러리 명칭 공간에 있는 모든 기능들을 해당 범위에 추가합니다. 작은 프로그램이나 예제에서는 std:: 를 명시하는 것이 큰 차이가 없을 수 있지만, 코드가 많아지고 여러 개발자와 함께 작업을 할 때, 명칭 공간을 명확히 명시하는 것은 코드의 이해와 유지보수 등에 도움이 되며, 혹시 발생할 수 있는 명칭 공간 간의 충돌 위험을 피할 수 있는 좋은 습관이라고 생각합니다. 하지만, std:: 를 명시하지 않으면 코드를 간결하게 만들어준다는 장점 또한 있으니, 항상 코드를 작성하는 상황과 환경 등에 따라서 고민을 하고, 적절한 선택을 하는 것이 중요하다고 생각합니다. 이러한 관점에서, 학습 단계에서부터 다양한 가능성들을 경험해보시는 것으로 이해하시면 도움이 되실 것 같습니다.
- 1
- 1
- 54
질문&답변
2024.04.25
14.3 / 3:50 질문있습니다
안녕하세요, 질문&답변 도우미 Soobak 입니다. 예외 처리에서 예외가 던져질 때 생성되는 익명 객체의 생명은 catch 블록에서 참조로 받고, catch 블록이 종료될 때까지 연장됩니다. 이는 C++ 표준에 따른 예외 처리 중 익명 객체에 대한 규칙입니다. 즉, 예외를 던질 때 익명 객체를 사용하는 경우, 이 객체를 임시적으로 메모리에 저장하고, catch 블록에서 해당 객체를 참조하여 예외를 처리할 수 있도록 합니다. 첨부드리는 링크의 14번 주석을 참고해보시면 도움이 되실 것 같습니다. https://timsong-cpp.github.io/cppwp/except#handle-14
- 1
- 1
- 54
질문&답변
2024.04.25
코드 작동이 잘 안되요
안녕하세요, 질문&답변 도우미 Soobak 입니다. 첨부해주신 코드를 자세히 보니, scanf() 함수가 아닌, scanf_s() 함수를 사용하셨네요. scanf_s() 함수는 scanf() 함수와 유사하지만, 문자열 입력에 대해서 버퍼의 크기를 인수로 추가해주어야 합니다. 이러한 문자열의 크기를 구하기 위해서 sizeof() 연산자가 사용되기도 하는데요, 질문자님께서 인터넷에 검색해보셨을 때, 말씀해주신 sizeof() 연산자 사용에 대한 내용이 검색된 것은 이러한 이유 때문인 것입니다. 한 번, scanf_s() .함수 대신, scanf() 함수를 사용하셔서 컴파일 후 실행해보세요.
- 1
- 2
- 86