C

C기초 플러스 chap.5 연산자, 표현식, 문자

Barbarian developer 2024. 8. 8. 18:22

자동목차

연산자,  표현식, 문장

5장에서는 다음과 같은 사항을 배울거다!!

  • 키워드 : while, typedef
  • 연산자 : =  -  *  /  %  ++  --  (type)
  • C의 여러 연산자
  • 연산자 우선순위, 문장과표현식의 의미
  • while 루프
  • 복합문, 데이터형 자동 변환, 데이터형 캐스트
  • 전달인자를 사용하는 함수의 작성법

그럼 베엘라!!


루프에 대한  간단한 소개

이제부턴 출력문도 같이 보여준다! 나는 성장형 바바리안! 우린 같이 성장한다!

늘 그랬든 코드 먼저 봐라!

//5.1

// shoes1.c --사이즈 단위를 인치 단위로 변환한다.
#include <stdio.h>
#define ADJUST 7.31 //기호 상수의 한 종류

int main(void)
{
const double SACALE=0.333; //기호 상수의 다른 종류
double shoe, foot;

shoe = 9.0;
foot = SACALE * shoe + ADJUST;
printf("신발 사이즈(남자용) 발길이\n");
printf("%10.1lf %15.2lf 인치\n", shoe, foot);

return 0;
 
}

 
  • 이건 루프를 쓰지 않았을 때다!
  • 우린 100명의 바바리안 모두에게 신발을 신겨야한다!
  • 바바리안 100명 모두 신발 사이즈 다르다!
  • 루프가 없는 상황에선 아래 항과 같은 코드를 여러개를 작성해야 한다!
  • 그럼 너무 복잡하고 귀찮다! 우린 복잡한거 어렵다!
  • 간단하게 만든다!
//5.2

/*shoes2.c --여러개의 신발 사이즈를 인치 단위로 계산한다.*/
#include<stdio.h>
#define ADJUST 7.31 //기호 상수의 다른 종류

int main(void)
{
const double SCALE = 0.333; //기호 상소의 다른 종류
double shoe, foot;

printf("신발사이즈(남자용) 발길이\n");
shoe = 3.0;
while (shoe < 18.5) //while 루프의 시작
{

foot = SCALE * shoe + ADJUST; //블록의 시작
printf("%10.1f %15.2f 인치\n", shoe, foot);
shoe = shoe + 1.0;


} //블록의 끝
printf("그 신발이 발에 맞다면, 그것을 신으세요.\n");

return 0;
}
  • 루프 쓰면 이렇게 한번에 다 나온다!
  • 이제 자기 발길이를 재서 맞는 사이즈 주면 끝이다!! 차례대로 발길이 재서 말해라! 새 신발 준다!
  • shoe의 값이 18.5가 될 때까지 블록에 shoe의 값을 대입한다!
  • 그 다음 출력되면 shoe에 +1을 더하고 while로 다시 돌아간다!
  • shoe가 while 조건에 부합하지 않으면, 다시 블록에 shoe의 값을 대입한다!
  • 이걸 계속하다가 어느 순간 while의 조건에 부합한 순간 루프에서 탈출한다!
  • 우--랴!!!!!!!
  • 어차피 나중에 또 다룰거다!! 이것만 알면 된다!! 베엘라!!

기본연산자

우린 지금부터 연산에 대해 알아본다!!

문제 풀기에 앞서 중요한 사실 몇가지만 보고 간다!

나중에 포인터에 대해 배울건데 이거 모르면 바보된다!

이건 좀 어려워도 최대한 쉽게 가르쳐 줄테니 포기하면 안된다!

대입 연산자 : ' = '

  • C언어에서, 등호는 "같다"가 아니다! 얘는 값을 대입한다는 연산자이다!
bmw=2002;
  • 왼쪽은 변수의 이름! 오른쪽은 저장될 데이터, 즉 값이다!!
  • bmw는 여기서 창고! 2002는 물건이다!

 

  • "="를 기준으로, 왼쪽은 항상 물건을 저장하는 창고명을 적고 오른쪽은 항상 저장하는 물건을 적는다!
  • 여기서 창고역할을 하는 bmw는, C언어에서는 변수. 즉, 좌변값이라고 지칭한다!
  • 좌변값이란 그 저장공간을 위치하는데 사용되는 레이블이라고 한다! 레이블은 뭔지 나도 모른다! 그냥 넘어가라!
  • 좌변값은 변경할 수 있는 좌변값이 있고, 변경할수 없는 좌변값이 있다! 조금있다가 다시 설명한다!

 

  • 창고에 저장하는 물건인 2002를 우리는 우변값이라고 할거다!
  • 우변값은 변경할 수 있는 좌변값에 대입할 수 있는 수량을 지칭한다! 2002인거다!
  • 자, 다 왔다! 
  • 컴퓨터는 메모리에 2002라는 상수를 저장한 주소가 있다. 좌변값인 bmw가 2002가 있는 주소를 찾아 간다!
  • 2002가 2003으로 바뀌면, bmw가 2003이 저장된 주소를 찾아간다!
  • 헷갈리면 안된다! 우리가 보기엔 좌변값이 고정이고, 우변값이 변하는 걸로 보이지만, 실제로 컴퓨터 작동은 반대다!
  • 이게 포인터의 핵심이다! 중요한거니 다시 보자!
int ex;
int why;
int zee;
const int TWO = 2;
why = 42;
ex = TWO * (why + zee);
  • 자, 이제 어느정도 알겠는가??
  • ex, why, zee는 여기서 변경할 수 있는 좌변 값이다!! 얘네는 우리가 우변값을 입력하면 걔 여깄다!! 하면서 찾아서 끌고 온다!
  • 그리고 언제든지 다시 다른 우변값을 찾아와라!! 하면서 보낼수 있다! 그래, 마약탐지견 같은거다!!
  • 단, const int Two에 있는 Two는 묶여 있는 시골개 같은거다! 위의 소스코드 중에서 Two는 우변값 2가 있는 주소에 갇혀있다! const가 Two의 목에 목줄을 매놔서 다른 우변값을 찾으로 갈 수 없다!

 

  • 미안하다. 말이 길다! 끝이다! 마지막으로 피연산자에 대해 배운다!
  • 쉽다! 피연산자는 연산자가 연산을 하는 대상이다!
  • 마지막 ex에서 연산자는 자기들끼리 들고 볶는 Two, why, zee다!!
  • 자기들끼리 뭘 막 하더니 ex한테 우리가 어디있는지 찾아!라고 한다!
  • ex는 가만히 쉬고 싶었는데, 움직여야 하는 피해를 본다! 그래서 피연산자다!
  • "=" 왼쪽에 있는 항목은 피연산자!라고 생각하면 된다! 불쌍한 친구들이니 잘 해주자!
//5.3
//golf.c--골프 토너먼트 점수판

#include<stdio.h>
int main(void)
{
int jane, tarzan, cheeta;

cheeta = tarzan =jane = 68;
printf(" 치타 타잔 제인 \n");
printf("1라운드 점수 %4d %8d %8d\n", cheeta, tarzan, jane);

return 0;
}
 
  • 대입을 사용해서 작성한 예제다!
  • 대입은 오른쪽부터 왼쪽으로 간다!
  • 그럼 68이 jane, tarzan, cheeta순으로 대입된다!
  • 대부분의 컴퓨터 언어는 삼중 대입을 허용하지 않지만 C언어는 허용한다!
  • 쉽다!

곱셈연산자 : ' * '

  • C언어에서는 제곱 함수를 제공하지 않는다!
  • 그래서 아래와 같이 제곱표를 만들어서 사용해야한다!
  • 별도의 설명은 필요 없을 것 같다 보고 따라 쳐라! 패스!
//5.4
//squares.c -- 처음 20까지의 제곱표를 만든다.
#include<stdio.h>
int main(void)
{
int num=1;

while (num<21)

{
printf("%4d %6d\n", num, num*num);
num=num+1;

}
return 0;

}
 

나눗셈 연산자: ' / '

  • 정수는 소수를 표현하지 않는다! 그래서 정수까지만 몫을 구하고, 소수는 모두 버린다!
  • 반올림 아니다! 그냥 버리는 거다!! 우수리 뗀다! 타짜다!!
//5.6
//divide.c--정수형 나눗셈과 부동소수점형 나눗셈

#include<stdio.h>
int main(void)
{

printf("정수형 나눗셈 : 5/4 %d\n", 5/4);
printf("정수형 나눗셈 : 6/3 %d\n", 6/3);
printf("정수형 나눗셈 : 7/4 %d\n", 7/4);
printf("부동소수점형 나눗셈: 7./4. %1.2f \n", 7./4.);
printf("혼합된 나눗셈 : 7./4 %1.2f \n", 7./4);

return 0;
}

//정수는 소수를 표현하지 않는다! 그래서 몫이 소수라면 소수는 과감하게 버린다!
//하지만 실수는 소수를 포함한 값이다! 그래서 몫이 소수라도 지정된 값까지는 끝까지 책임진다!

그 밖의 연산자

C언어는 약 40개의 언어를 가지고 있다! 앞에서 설명한 연산자들이 우리가 주로 사용하는 연산자다! 여기서 우리는 필요한 연산자 몇개만 간단하게 보고간다!

 

sizeof 연산자와 size_t형

  • sizeof()는 변수 혹은 데이터 형 자체를 가져다()안에 가둬야만 사용 가능했다.
  • 하지만 size_t는 데이터 형처럼 사용하여 변수나 특정 데이터 객체를 sizeof()처럼 쓸수 있다.
  • 단, 양수만 가능하다!
  • 얘의 반환 지정자는 sizeof와 동일하게 %zd를 쓰면 된다!
//5.8
//sizeof.c --sizeof 연산자를 사용한다.
//c99의 %z 변경자를 사용한다. --%zd가 지원되지 않는다면 %u나 %lu를 사용하라.

#include<stdio.h>
int main(void)
{
int n =0;
size_t intsize;

intsize = sizeof (int);
printf("n=%d, n은 %zd바이트이다.; 모든 int형 값은 %zd바이트이다.\n", n, sizeof n, intsize );

return 0;
}
 

 


나눗셈 연산자 : % (모듈로)

  • 변환 지정자 아니다! 연산할때 쓰는 거다! 몫으로 나눈 후 나머지를 알고 싶을 때 쓰는거다!
  • 예제 보면 바로 어떻게 쓰는지 알거다
  • 100초를 60초로 나누면 몫은 1이고 나머지는 40이다! 그럼 1분 50초가 되는거다!
  • 그걸 구현한 예제다 바로 알아본다!!
//5.9
//min_sec.c-- 초 수로 주어지는 시간을 분과 초로변환한다.
#include <stdio.h>
#define SEC_PER_MIN 60 //1qnsdms 60초
int main(void)
{
int sec, min, left;

printf("초 수로 주어지는 시간을 분과 초로 변환합니다!\n");
printf("초 수를 입력하시오(<=0이면 끝):\n");
scanf("%d", &sec); //초 수를 읽는다.
while (sec>0)
{
min=sec/ SEC_PER_MIN; // 나머지를 버린 분 수
left = sec % SEC_PER_MIN; //나머지 초 수
printf("%d 초는 %d분, %d초입니다. \n", sec, min, left);
printf("다음 초 수를 입력하시오(<=이면 끝):\n");
scanf("%d", &sec);
}
printf("끝!\n");

return 0;
}


  • while을 써서 내가 입력하고 싶은 값을 원하는 만큼 입력할수 있게 했다.
  • 0이 되면 탈출한다!
  • 끝!

증가 연산자(감소 연산자): ++

  • 증가 연산자는 두가지 방식으로 사용된다!
  • 하나는 피 연산자 앞에 쓴다 이걸 전위모드라고 하고, 또 하나는 피연산자 뒤에 쓴다! 그걸 후위모드라고 한다!
  • 우리가 전투를 치를때 전위 앞으로 돌격! 후위는 우회하여 적진의 허리를 가른다! 할때 그거다!
  • 차이는 조금 뒤에 설명한다! 일단 예제를 살펴보자! 
//5.10
// add_one.c --증가 연산자:전위 모드와 후위 모드
#include<stdio.h>
int main(void)
{
int ultra = 0, super = 0;
while(super<5)
{
super++; //후위모드
++ultra; //전위모드
printf("super = %d, ultra = %d\n", super, ultra);
}

return 0;
}
 
  • 이렇게 쓰는거다!! 친절하게 주석 까지 달아서 구분해놨으니 보고 이해하면 된다!
  • 자, 값은 똑같은데 어떤게 다른 거냐고? 따라와라! 

베에에에에엘라아아아아아!


//5.11
//post_pre.c--후위 모드와 전위모드
#include <stdio.h>
int main(void)
{
int a =1,b=1;
int a_post, pre_b;

a_post = a++; //대입 단계 동안의 a++값
pre_b = ++b; //대입 단계 동안의 ++b값
printf("a a_post b pre_b \n");
printf("%1d %5d %5d %5d\n", a, a_post, b, pre_b);

return 0;

}
  • a에는 후위모드를 사용했고, b에는 전위 모드를 사용했다!
  • 근데 값이 다르다!! 어떻게 된건지 궁금한가?
  • 후위모드를 사용하면 a에 먼저 저장되어 있던 값이 좌변값에 저장 된뒤에 증가한다!
  • 전위모드를 사용하면 b를 먼저 증가 시키고 사용하는 것이다!! 이거 몰라도 된다! 지나간다!

표현식과 문장

우리가 지금까지 사용했던 표현식과 문장에 대해 심도 있게 알아본다!

 

표현

  • Expression은 ‘수식’이라는 뜻으로 하나 이상의 값으로 표현(reduce)될 수 있는 코드를 말한다. 수식이라는 뜻에 맞게 우리가 일상생활에서 하는 사칙연산식이 곧 expression이다. 가령 ‘1+1’, ‘2+5’ 등등.

문장

레이블 문 (labeled-statement)

    • (표현)식 문 (expression-statement)
    • 복합 문 (compound-statement) : if문이 여러 구문을 제어하게 만들고 싶을 때
    • 선택문 (selection-statement)
    • 반복문 (iteration-statement)
    • 점프 문 (jump-statement)
    • 선언문 : int toes;
    • 대입문 : toes = 12;
    • 함수 호출문 : printf("%d\n", toes);
    • 구조화문 : while (toes < 20) toes = toes + 2;
    • Return문 : return 0;
    • null 문 :   ; // 아무것도 하지 않는다.문장에는 여러 종류가 존재한다.
//5.13
// addemup.c --다섯 가지 문장
#include <stdio.h>
int main(void) //처음 20까지 정수들의 합을 구한다.
{

int count, sum; //선언문

count = 0; //대입문
sum = 0; //대입문
while (count++ < 20) //while문
sum=sum + count; //문장(while문)
printf("합 = %d\n", sum); //함수문

return 0; //return문
}
 
  • 선언문 : 변수의 이름과 데이터 형을 설정하여 변수들을 위한 기억 공간을 할당함. 바바리안이 지낼 집 평수를 고르고 이름을 짓는거다!
  • 대입문 : 변수에 어떤 값을 대입하는 것. 바바리안을 몇명을 집어 넣을 건지 정한다! 촌장 같은거!
  • 문장 : while, for, if 같은 조건문 같은 모든 것을 통틀어 말함!
  • 함수문 : 함수에게 어떤 기능을 할 것인지 지시 하는 것.

데이터형 변환

//5.14
// convert.c --자동 데이터형 변환
#include <stdio.h>

int main(void)
{

char ch;
int i;
float fl;

fl = i = ch = 'C'; //라인 9 fl = 67.00, i 67 ch c
printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl); //라인 10
ch= ch +1; //라인 11
i = fl + 2 * ch; //라인12
fl=2.0 * ch +i; //라인13
printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl); //라인 14
ch = 1107; //라인15
printf("이제 ch = %c\n", ch); //라인16
ch = 80.99; //라인17
printf("이제 ch = %c\n", ch); //라인17

return 0;
}

 
  • 일부로 라인 15에서 오버플로우를일으키는 거다!
  • 아스키 코드는 256까지 값을 저장 할 수 있으므로, 오버플로우로 인해 넘는 값을 모두 버리는 과정인 1107에서 256을 나눈 나머지 83을 아스키코드 값으로 가져온다!
  • 아스키는 80.99를 80으로 인식한다!! 무수리 땐다!!