[CS50 2019] 1. C
모두를 위한 컴퓨터 과학
1. C 언어 기초
#include <stdio.h>
int main(void)
{
printf("hello, world\n");
}
>> hello, world
✔ #include <stdio.h>
- 이 프로그램이
stdio.h
라는 파일 안에 들어있는 미리 작성된 함수들에 접근할 수 있도록 함 - 여기에서 함수란, 특정 기능을 수행하기 위한 문장들을 모아놓은 것
- ex. 화면에 문자를 보여주는 역할을 하는
printf
라는 함수
✔ int main(void)
- 프로그램의 시작점을 정의
- 중괄호는 main 함수의 코드를 묶어주는 역할을 함
✔ printf()
- 화면에 보여주고자 하는 문자열을 입력값으로 넣어줄 수 있음
\n
: 줄바꿈 문자- 세미콜론 (;): 프로그램 명령의 마지막이 어디인지를 알려줌
컴파일 (Compile)
- 우리가 만든 소스코드를 컴퓨터가 이해할 수 있게 0과 1로 만드는 작업
- 소스 코드를 일련의 0과 1들로 이루어진 오브젝트 코드(object code) 로 전환해주는 것
✔ 주석이란?
- 문장 중
//
이나/*
와*/
안에 작성된 코드는 컴파일러에 의해 완전히 무시됨- 프로그래머들이 코드에 대한 설명을 기록하는데 주로 사용
2. 문자열
#include <stdio.h>
int main(void)
{
char animal[20];
printf("좋아하는 동물은?");
scanf("%s", animal);
printf("내가 좋아하는 동물은 %s이다.", animal);
return 0;
}
string
(문자열): 단어나 구절, 문장 등과 같이 문자의 나열로 이루어진 데이터 종류=
(할당 연산자): 오른쪽에 있는 것을 왼쪽에 지정한다.%
를 이용하여 사용자가 입력한 변수 출력
3. 조건문과 루프
✔ 부울 연산자
- 참(True)과 거짓(False)을 판단하는 연산자
- ex.
<
(더 작다),>
(더 크다),==
(같다),<=
(작거나 같다),>=
(크거나 같다),!=
(같지 않다) - 두 부울 값을 비교하는 연산도 가능 ex.
&&
(and),||
(or),,
조건문
- 조건 분기: 다른 상황에 따라 다른 코드가 실행되어야 한다는 개념
✔ if 문
if (number > 0)
{
printf("The number is positive.\n");
}
else if (number == 0)
{
printf("The number is zero.\n");
}
else
{
printf("The number is negative.\n");
}
- if 문은 조건을 검사하고 해당 조건이 참인 경우에만 특정 블록의 코드를 실행
- 만약 조건이 거짓이라면,
else if
나else
블록으로 넘어간다.
✔ switch 문
switch (day)
{
case 1:
printf("Monday\n");
break;
case 2:
printf("Tuesday\n");
break;
case 3:
printf("Wednesday\n");
break;
default:
printf("Other day\n");
break;
}
조건식의 결과값에 따라 매칭되는 case의 코드를 실행
✔ 3항 연산자
int y = (x > 3) ? 2: 1;
식이 참이면
:
기호 왼편의 값으로 계산되고, 거짓이면 오른편의 값으로 계산
루프 (반복 순환)
✔ while 문
while (i <= 5) {
printf("%d\n", i);
i++;
}
주어진 조건이 참일 동안 반복적으로 코드 블록을 실행
✔ for 문
for (int i = 1; i <= 5; i++) {
printf("%d\n", i);
}
for(변수 초기화; 변수 조건; 증감식)
을 통해 반복의 흐름 정의- 반복 횟수나 특정 범위의 값을 순회하는데 매우 편리하다.
4. 자료형, 형식 지정자
✔ 실수를 입력받아 출력하는 코드
#include <stdio.h>
int main() {
double inputValue;
// 사용자로부터 실수 입력 받기
printf("실수 값을 입력하세요: ");
scanf("%lf", &inputValue);
// %.2f로 입력받은 실수 값을 소수점 둘째 자리까지 출력
printf("입력한 실수 값: %.2f\n", inputValue);
return 0;
}
데이터 타입
bool
: 불리언 표현 ex) True, False, 1, 0char
: 문자 하나 ex) ‘a’, ‘B’, ‘?’string
: 문자열int
: 특정 크기 또는 비트까지의 정수 (40억까지 셀 수 있음)long
: 더 큰 크기의 정수float
: 부동 소수점을 갖는 실수 ex) 3.14, -28.56double
: 부동 소수점을 포함한 더 큰 실수
✔ float
vs double
float
는 보통 4byte,double
은 보통 8byte의 크기를 가짐float
보다double
이 더 높은 정밀도를 제공하기에 더 많은 메모리를 사용하고 상대적으로 연산이 느리다.float
는 메모리가 제한적인 상황, 예를 들어 그래픽 처리 장치에서 주로 사용double
은 더 높은 정밀도가 필요한 계산에서 사용- 대부분의 경우,
double
의 사용이 메모리나 성능 면에서 큰 차이를 만들지 않으면서 더 높은 정밀도를 제공하기에double
이 더 널리 사용됨
형식 지정자
프로그래밍 언어에서 변수를 출력할 때나 입력받을 때, 해당 변수의 데이터 타입과 출력 형식을 지정하는 데 사용되는 기호
%c
: char%f
: float, double%lf
: double%i
: int%li
: long%s
: string
5. 사용자 정의 함수, 중첩 루프
사용자 정의 함수
- 사용자 정의 함수를 이용하면 동일한 작업을 반복하는 것을 단순화할 수 있음
- 함수의 이름 왼쪽에는 출력의 종류 / 오른쪽에는 입력의 종류를 지정
출력의 종류 + 함수 이름 + (입력의 종류)
// 매개변수를 받지 않는 함수
int simpleFunction(void) {
return 42; // 임의의 정수 반환
}
✔ void
타입
void
란 함수의 매개변수가 없음을 나타냄- 즉, 입출력이 없을 때
void
타입으로 지정int simpleFunction()
과 같이void
생략 가능
중첩 루프
- 하나 이상의 루프가 다른 루프 안에 포함된 형태
- 외부 루프와 내부 루프로 이루어져 있으며, 외부 루프가 한 번 반복될 때마다 내부 루프가 여러번 반복
- 다양한 패턴이나 복잡한 작업 수행을 위해 쓰임
✔ 예시 코드
#include <stdio.h>
int main(void)
{
int n;
do
{
printf("Size: ");
scanf("%d", &n);
}
while (n < 1);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("#");
}
printf("\n");
}
return 0;
}
>> Size: 3
###
###
###
do-while
루프
do-while
루프는 루프 내부의 코드를 최소한 한 번 실행한 후에 조건을 검사while()
의 조건이true
일 동안 루프가 계속 실행- 즉, 사용자가 양의 정수를 입력할 때까지 계속해서 ‘Size: ‘를 출력
- 중첩된
for
루프
- 사용자로부터 양의 정수를 입력받은 후, 이 크기에 따라 중첩된
for
루프를 사용하여 정사각형 출력
6. 하드웨어의 한계
- 컴퓨터는 RAM이라는 물리적 저장장치를 포함하고 있음
- 사용자가 작성한 프로그램은 구동 중에 RAM에 저장되는데, 유한한 크기의 비트만 저장할 수 있기 때문에 부정확한 결과를 내기도 한다.
부동 소수점 부정확성
#include <stdio.h>
int main() {
float sum = 0.0;
for (int i = 0; i < 10; ++i) {
sum += 0.1;
}
printf("0.1을 10번 더한 결과: %.10f\n", sum);
return 0;
}
>> 0.1을 10번 더한 결과: 1.0000000149
정확한 결과는 1이 되어야 하지만,
float
에서 저장 가능한 비트 수가 유한하기 때문에 다소 부정확한 결과를 내게 되는 것
정수 오버플로우
#include <stdio.h>
int main() {
int maxInt = 2147483647; // int 자료형의 최댓값
printf("최댓값: %d\n", maxInt);
printf("최댓값 + 1: %d\n", maxInt + 1);
return 0;
}
>>
최댓값: 2147483647
최댓값 + 1: -2147483648
int
자료형의 최댓값을 초과한 값을 저장하려고 하면 정수 오버플로우가 발생하여 최소값으로 감소- 정수 자료형이 표현할 수 있는 범위를 벗어나서 생기는 문제