[C#][03] 변수와 상수, 사용자 입력
이번에는 변수와 상수, 리터럴, 타입 추론, 사용자 입력 등 기본적인 문법을 다시 살펴보았다.
1. 변수(Variable)
변수는 프로그램에서 사용하는 값을 저장하고, 이름을 통해 접근할 수 있도록 하는 수단이다.
예를 들어 다음 코드를 살펴보자.
Console.WriteLine(100);
Console.WriteLine(100 + 50);
Console.WriteLine(100 * 2);
이 코드에서 기준값 100을 변경하려면 세 곳을 모두 수정해야 한다.
하지만 변수를 사용하면 다음과 같이 작성할 수 있다.
int price = 100;
Console.WriteLine(price);
Console.WriteLine(price + 50);
Console.WriteLine(price * 2);
이제 price에 저장된 값만 변경하면 나머지 코드에도 반영된다.
변수는 단순히 값을 저장하는 것뿐만 아니라 값에 이름을 부여하고 한곳에서 관리할 수 있다는 장점이 있다.
변수의 선언, 할당, 초기화
변수를 사용할 때는 선언, 할당, 초기화라는 개념을 구분해야 한다.
int number; // 선언
number = 7; // 할당
int count = 10; // 선언과 동시에 초기화
| 개념 | 의미 |
|---|---|
| 선언(Declaration) | 변수의 타입과 이름을 지정 |
| 할당(Assignment) | 변수에 값을 대입 |
| 초기화(Initialization) | 변수에 처음 값을 부여 |
특히 C#에서 =는 수학에서 사용하는 등호가 아니라 오른쪽 값을 왼쪽 변수에 대입(할당)하는 연산자이다.
int count = 5;
count = count + 1;
처리 과정은 다음과 같다.
- 현재
count의 값인5를 읽는다. 5 + 1을 계산한다.- 결과인
6을 다시count에 저장한다.
따라서 최종적으로 count는 6이 된다.
초기화하지 않은 변수
C#에서는 초기화하지 않은 지역 변수를 읽으려고 하면 컴파일 오류가 발생한다.
int number;
Console.WriteLine(number); // CS0165
컴파일러가 변수가 사용되기 전에 값이 할당되었는지 검사하기 때문이다.
따라서 특별한 이유가 없다면 선언과 동시에 초기화하는 편이 좋다.
2. 데이터 타입과 리터럴
C#은 정적 타입 언어이므로 변수마다 저장할 값의 타입이 정해져 있다.
대표적인 데이터 타입은 다음과 같다.
| 타입 | 의미 | 예시 |
|---|---|---|
int | 정수 | 100 |
float | 단정밀도 실수 | 3.14f |
double | 배정밀도 실수 | 3.14 |
char | 문자 | 'A' |
string | 문자열 | "Hello" |
bool | 참 또는 거짓 | true |
이때 코드에 직접 작성한 값 자체를 리터럴(Literal)이라고 한다.
int level = 15;
string name = "Player";
bool isAlive = true;
15, "Player", true가 각각 리터럴이다.
특히 같은 숫자처럼 보이더라도 따옴표에 따라 타입이 달라진다.
Console.WriteLine(1 + 1);
Console.WriteLine('1');
Console.WriteLine("1" + "1");
실행 결과
2
1
11
숫자는 산술 연산을 수행하지만, 문자열에 +를 사용하면 문자열을 연결한다.
3. 상수(Constant)
변수와 달리 프로그램에서 변경하면 안 되는 값도 존재한다.
이러한 값은 const 키워드를 사용해 상수로 선언할 수 있다.
const int MaxHealth = 100;
int currentHealth = 80;
여기서 MaxHealth는 고정된 최대 체력이고, currentHealth는 변화할 수 있는 현재 체력이다.
currentHealth = 50; // 가능
MaxHealth = 200; // 컴파일 오류
상수는 선언과 동시에 초기화해야 하며, 컴파일 시점에 값이 결정될 수 있어야 한다.
상수를 사용하는 이유
상수를 사용하면 값이 변경되는 것을 방지할 수 있을 뿐만 아니라 코드의 의미도 명확해진다.
int score = 80;
if(score >= 60)
{
Console.WriteLine("합격");
}
여기서 60이라는 숫자만 보면 어떤 기준인지 바로 알기 어렵다.
const int PassScore = 60;
int score = 80;
if(score >= PassScore)
{
Console.WriteLine("합격");
}
이렇게 작성하면 합격 기준이라는 의미가 드러난다.
코드에 직접 작성되어 의미를 파악하기 어려운 숫자를 흔히 매직 넘버(Magic Number)라고 한다.
의미 있는 고정값에 이름을 부여하면 코드의 가독성과 유지보수성이 좋아진다.
변수와 상수 비교
| 구분 | 변수 | 상수 |
|---|---|---|
| 선언 | int hp = 100; | const int MaxHp = 100; |
| 값 변경 | 가능 | 불가능 |
| 초기화 | 선언 후에도 가능 | 선언과 동시에 필수 |
| 사용 예시 | 현재 체력, 점수 | 고정된 최대 체력, 기준값 |
4. var와 타입 추론
C#에서는 변수 선언 시 타입을 직접 작성하지 않고 var를 사용할 수도 있다.
var number = 10;
var name = "Player";
var isAlive = true;
이 경우 컴파일러가 오른쪽 초기값을 보고 타입을 추론한다.
number는intname은stringisAlive는bool
가장 중요한 점은 var를 사용한다고 해서 변수의 타입이 자유롭게 변경되는 것은 아니라는 것이다.
var number = 10;
number = 20; // 가능
number = "Hello"; // 컴파일 오류
처음 초기화할 때 int로 결정되었기 때문에 이후에도 정수 타입으로 사용해야 한다.
또한 컴파일러가 타입을 추론해야 하므로 초기화 없이 선언할 수 없다.
var number; // 컴파일 오류
var는 동적 타입이 아니라 컴파일러에 타입 추론을 맡기는 문법이라는 점을 알 수 있었다.
5. 사용자 입력받기
지금까지는 코드에 값을 직접 작성했지만, Console.ReadLine()을 사용하면 프로그램 실행 중 사용자에게 값을 입력받을 수 있다.
using System;
Console.Write("이름을 입력하세요: ");
string name = Console.ReadLine();
Console.WriteLine($"안녕하세요, {name}님!");
Console.ReadLine()은 사용자가 Enter를 누를 때까지 입력을 읽고 문자열을 반환한다. 입력 스트림이 끝난 경우에는 null을 반환할 수도 있다.
숫자 입력받기
ReadLine()으로 입력받은 값은 숫자를 입력하더라도 문자열로 처리된다.
따라서 숫자 계산을 위해서는 타입 변환이 필요하다.
Console.Write("숫자 입력: ");
string input = Console.ReadLine();
int number = int.Parse(input);
Console.WriteLine(number + 10);
사용자가 20을 입력하면 30이 출력된다.
int.Parse()는 문자열을 정수로 변환하는 메서드이다.
다만 숫자가 아닌 문자를 입력하거나 정수의 범위를 벗어난 값을 입력하면 예외가 발생할 수 있다.
이러한 상황을 안전하게 처리하기 위해서는 int.TryParse()를 사용할 수 있다.
Console.Write("숫자 입력: ");
string input = Console.ReadLine();
if(int.TryParse(input, out int number))
{
Console.WriteLine(number + 10);
}
else
{
Console.WriteLine("올바른 숫자를 입력해주세요.");
}
int.TryParse()는 변환에 성공하면 true, 실패하면 false를 반환한다.
Parse()와 달리 잘못된 입력으로 인한 형식 오류나 범위 초과를 반환값으로 처리할 수 있다는 장점이 있다.
6. 변수 이름 짓기
변수 이름은 문법적으로 올바른 것뿐만 아니라 어떤 값을 저장하는지 쉽게 이해할 수 있도록 작성하는 것이 중요하다.
int a = 100;
int ps = 50;
위 코드보다 다음과 같이 작성하는 편이 의미를 파악하기 쉽다.
int maxHealth = 100;
int playerScore = 50;
C#에서는 일반적으로 다음과 같은 명명 규칙을 사용한다.
| 대상 | 표기법 | 예시 |
|---|---|---|
| 지역 변수 | camelCase | playerScore |
| 상수 | PascalCase | MaxHealth |
camelCase는 첫 단어를 소문자로 시작하고, 이후 단어의 첫 글자를 대문자로 작성한다.
PascalCase는 모든 단어의 첫 글자를 대문자로 작성한다.
이러한 명명 규칙은 문법적으로 강제되는 것은 아니지만, 프로젝트 전체에서 일관되게 유지하는 것이 좋다.
7. 디버깅으로 변수 값 확인하기
변수에 저장된 값이 예상과 다를 때는 Console.WriteLine()으로 출력해서 확인할 수도 있지만, Visual Studio의 디버거를 사용할 수도 있다.
int level = 1;
int health = 100;
level = level + 1;
health = health + 20;
중단점(Breakpoint)을 설정하고 한 줄씩 실행하면 변수가 어떻게 변경되는지 확인할 수 있다.
| 기능 | 단축키 |
|---|---|
| 중단점 설정 | F9 |
| 디버깅 시작 | F5 |
| 한 줄씩 실행 | F10 |
예를 들어 level = level + 1;에 중단점을 설정하면 해당 명령문을 실행하기 직전에 멈춘다.
이때 level은 1이고, F10으로 한 줄을 실행한 뒤에는 2로 변경된다.
프로그램의 실행 흐름을 직접 확인할 수 있다는 점에서 디버깅은 오류의 원인을 찾는 데 유용하다.
마치며
앞으로도 이전에 배웠던 C# 내용을 순서대로 복습하면서 단순한 문법 정리를 하고 스스로 실제 코드를 작성할 때 도움이 되는 내용을 중심으로 기록할 것이다. 다시 보고 금방 개념을 회복할 수 요점적으로 잘 정리할 것이다.

