명령행 인자는 문자열 목록이므로, 핵심은 argc/argv 문법보다 문자열을 어떻게 검증하고 해석할지에 있습니다.
argv[0],argv[1]의미를 다시 확인하고 싶다- 숫자 인자를
atoi대신 어떻게 안전하게 읽는지 정리하고 싶다 - 옵션과 위치 인자를 어떻게 나눌지 기준이 필요하다
숏컷 코드
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "usage: %s <input>\n", argv[0]);
return 1;
}
return 0;
}문법
argc는 인자 개수, argv는 문자열 포인터 배열입니다. 보통 argv[0]는 프로그램 이름이고, 실제 인자는 argv[1]부터 시작합니다.
int main(int argc, char *argv[]) {
for (int i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}즉 명령행 인자는 타입이 정해진 값 목록이 아니라 문자열 목록이므로, 필요한 타입으로 변환하는 단계가 꼭 필요합니다.
입력 해석
숫자 변환은 atoi보다 strtol이 더 낫습니다.
char *end = NULL;
long value = strtol(argv[1], &end, 10);
if (end == argv[1] || *end != '\0') {
fprintf(stderr, "invalid number: %s\n", argv[1]);
return 1;
}옵션이 적으면 strcmp로 직접 파싱해도 충분합니다.
int verbose = 0;
const char *path = NULL;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-v") == 0) {
verbose = 1;
} else {
path = argv[i];
}
}중요한 건 코드를 짜기 전에 usage 규칙을 먼저 정하는 것입니다. 어떤 것은 플래그인지, 어떤 것은 값이 붙는 옵션인지, 어떤 것은 위치 인자인지 구조를 먼저 정해야 합니다.
체크포인트
argv[0]는 보통 프로그램 이름입니다.argv[1]부터 실제 인자가 시작됩니다.- 필수 인자는 개수 검사부터 해야 합니다.
- 숫자 변환은
atoi보다strtol이 안전합니다. - 옵션과 위치 인자는 규칙을 먼저 정하고 파싱해야 합니다.
- usage와 에러 메시지는
stderr에 출력하는 편이 보통 맞습니다.
주의할 점
명령행 인자 처리 코드는 입력 검증 코드입니다. "내가 실행하니까 대충 받아도 된다"는 식으로 짜면, 잘못된 문자열 하나가 범위 오류, 잘못된 파일 경로 처리, 옵션 해석 오류로 그대로 이어질 수 있습니다.
참고 링크
1 sources