
2025.04.11
[ 키보드 입력 ]
↓
[ 입력 버퍼 (stdin) ]
↓
[ scanf / fgets 등 ]
↓
[ 변수에 저장 ]
| 함수명 | 용도 | 특징 | 공백 포함 | 줄바꿈 처리 | 보안 |
|---|---|---|---|---|---|
scanf() | 형식 기반 입력 | 타입 명시 (%d, %s 등) | ❌ (공백 전까지만 %s) | 줄바꿈 안먹음 (남음) | 중간 |
fgets() | 한 줄 입력 | 공백 포함 가능, 버퍼 사이즈 지정 | ✅ | 줄바꿈 \n 포함됨 | ✅ |
gets() | 한 줄 입력 | 과거에 쓰이던 함수, 위험함 | ✅ | ✅ | ❌ (버퍼 오버플로우 위험) |
getchar() | 한 문자 입력 | 문자 1개 읽음 | - | 엔터 입력도 문자로 처리 | ✅ |
getch() / getche() | 콘솔에서 입력 (키 눌림) | 즉시 입력 받음 (에코 차이 있음) | - | - | 플랫폼 종속 (Windows) |
fgets()와 scanf()의 차이점fgets()
#include <stdio.h>
char *fgets(char *s, int size, FILE *stream);
> char *s : 문자열을 저장할 버퍼(저장할 곳)
> int size : 입력 받을 최대크기(size -1개 +\0)
> FILE *stream
: stdin 사용가능
: 입출력 대상과 연결된 추상화된 "스트림 객체"
EX)
char str[100];
fgets(str, sizeof(str), stdin);// 공백 포함, 개행 포함
scanf()
#includ <stdin.h>
int scanf(const char *format, ...);
EX)
char str[100];
scanf("%s", str); // 공백 전까지만 입력됨
%d, %f, %u, ...)은 입력 후 엔터를 쳐도 scanf()가 \n을 무시하고 처리%c)은 \n도 문자로 취급하기 때문에 문제가 생기는 것strlen(”입력받은 문자열”) 하면 ‘\0’을 제외한 길이 리턴
[ printf("Hello") ]
↓
[ 출력 버퍼 (stdout) ]
↓ (줄바꿈 or fflush or 버퍼 가득 참)
[ 실제 화면에 출력됨 ]
| 함수명 | 용도 | 특징 | 줄바꿈 자동 |
|---|---|---|---|
printf() | 형식 기반 출력 | %d, %s, %f 등 사용 | ❌ |
puts() | 문자열 출력 | 문자열 출력 + \n 자동 | ✅ |
putchar() | 문자 1개 출력 | char 하나 출력 | ❌ |
void func(int x) {
x = x + 1;
}
int main() {
int a = 10;
func(a);
printf("%d\n", a); // 결과: 10
}
func(a)를 호출하면 a의 값이 복사돼서 x에 들어감x를 바꿔도 원본 a는 변하지 않음✔️ C는 항상 값을 복사해서 넘긴다 → call by value
void func(int *x) {
*x = *x + 1;
}
int main() {
int a = 10;
func(&a);
printf("%d\n", a); // 결과: 11
}
void process(struct BigData data);
struct BigData가 크기가 수십~수백 바이트일 경우,void process(struct BigData *data);
| 방식 | 설명 | 복사량 | 성능 |
|---|---|---|---|
| call by value (값 복사) | 값 전체를 복사해서 전달 | 많을 수 있음 | 느릴 수 있음 |
| call by reference (주소 복사) | 주소(포인터)만 복사 | 4~8바이트 | 보통 더 빠름 |
int a = 13; → 그냥 정수int* p = &a; → 정수를 가리키는 포인터int** pp = &p; → 포인터를 가리키는 포인터 (이중 포인터)
typedef struct _listnode{
int item;
struct _listnode *next;
} ListNode; // You should not change the definition of ListNode
typedef struct _linkedlist{
int size;
ListNode *head;
} LinkedList; // You should not change the definition of LinkedList
malloc 써야 할까?연결 리스트는 노드를 동적으로 생성해서 언제든 붙이거나 빼는 구조.
ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
newNode->item = 10;
newNode->next = NULL;
malloc 앞에 형변환은 왜 해주는가?void → 모든 자료형에 대응될 수 있게free 잘 해주자| 선언 방식 | 메모리 위치 | free() 필요 여부 |
|---|---|---|
ListNode maxL; | 스택(stack) | ❌ 아니요 (자동 해제) |
ListNode* maxL = malloc(...); | 힙(heap) | ✅ 꼭 필요함 |
Segmentation Fault : 허용되지 않은 메모리(주소)를 접근하려고 할 때 발생하는 에러오랜만에 C언어 공부를 하니 재밌었다.
예전 기억이 새록새록 나면서 새로운 사실들 배우니까 깨달음을 얻는 것 같다.
교수님이 분명히 알려줬더라. 내 뇌가 일을 잘 못하나 보다.