C언어 6장(4)~10장

이성준·2023년 2월 23일
3

C 자료구조

목록 보기
5/12
post-thumbnail

저번 포스트에서 Preprocessing하는 방법과 헤더파일, 함수원형, 함수구성요소, 소스파일(.c,.obj,.lib)에 관해서 포스팅 했다.
이번에는 printf와 puts, 관계연산자, if문, 반복문, 전역변수와 지역변수에 관해서 포스팅하겠다.

1.Puts()와printf()

puts()는 string을 출력하는 함수이다 먼저 사용하는 방법을 보이자면 다음과 같다

void main(void){
    puts("L");
    puts("A");
}

문자열을 출력하는 함수이고 C언어 표준라이브러리안에 있다.

C언어 표준라이브러리는 저번 포스팅에 설명했다

다음과 같은 경우를 한번 생각해보자

void main(void){
    puts("LeeSungJoon");
}


나는 여기서 Lee Sung Joon을 각기 다른줄에 출력하고 싶다 그러기 위해선 어떻게 해야할까?
바로 다음과 같이 컴퓨터에게
"다음줄로 이동해라"
"한tab만큼 띄워서 써라" 와 같은 명령을 내려야한다.

다음줄로 이동해라 → \n
tab만큼 띄워서 써라 → \t

이외에도 컴퓨터가 문자를 작성하다가 한칸 뒤로가서 overwriting을 하게하는 \b

이외에도 컴퓨터가 문자를 작성하다가 처음으로가서 overwriting을 하게하는 \r 등이 있다.

Tip> 나도 코딩 경력이 그리 길지는 않지만 혼자서 부딪히면서 깨달은점은 절대 모든 코드와 함수를 기억할 수 없다는 것이다. 이것에 관해서 기억이 안난다면 Googling을 적극 활용해라
(요즘엔 Chat gpt가 나와서... 사실 구글링도 별 필요 없다)

다시 돌아와서 위에서 말한 한줄씩 띄워서 쓰는 코드를 작성해보겠다

void main(void){
    puts("Lee\nSung\nJoon");

}  

printf() 에 관해서 이야기 해보겠다. 아마 당신이 파이썬을 공부했다면 printf를 받아들이기 쉬울 것이다 왜냐면 파이썬에서 format함수를 쓰기 전까진 다음과 같이 코딩을 했기 때문이다

print("%s"%"이성준")

이거와 유사하다 단여기선 연결해주는것이 , 로 연결돼있다

우선 먼저 %로 붙은 것(서식지정 키워드)에 관해서 설명하겠다
%d → 10진수 정수를 출력 할거야
%f → 실수를 출력 할거야
%c → 문자를 출력 할거야
%s → 문자열을 출력 할거야
%o → 8진수를 출력 할거야
%x → 16진수를 출력 할거야

우리는 위에서 %d와 %f에 대해서 유의깊게 살펴볼 필요가 있다 %f에 대해서 설명할텐데 이를 토대로 %d에도 한번 적용해보길 바란다.

void main(void){
printf("%010.5f",0.12345678);
}

위에 printf를 간단히 해석해보자면 "나는 0.12345678을 출력하고 싶어"라고 컴퓨터에게 말한 것과 같다
그런데 위에서 말한 %f라고 안쓰고 010.5가 사이에 붙었다

설명해보자면
맨앞에 붙은 0과 . 사이에 10은 10칸안에 출력하고 싶다는 것이다. 위에 그림을 보면 소수점을 포함해서 10칸에 숫자가 들어간것이 보일것이다.

그런데 0.12346이라고 쓰면되지 뭐하러 앞에 0이 추가 됐을까? → 이것이 바로 010.5에서 맨앞에 붙은 0이 의미하는 것이다. 의미하는 바는 다음과 같다.
"너 10칸안에 쓸거야?? 알았어 그러면 공백은 0으로 채울게!"

자 이제 거의 다왔다. 010.5에서 .5가 의미하는 바는 무엇일까 .5는 소수점5자리까지만 쓰겠다는 의미이다. 따라서 0.12345678 에서 6에서 반올림 돼서 0.12346이 출력되게 되는 것이다.

추가로 010.5앞에 -를 붙여서 -010.5로 쓰면 10칸에서 숫자를 왼쪽에 붙여서 쓰고 현재는 아무것도 안썼기 때문에 +로 인식하고 오른쪽에 붙여서 쓰는 것이다.

교재에서는 C언어는 실수형인 상수를 적으면 기본적으로 double로 처리한다고 했다. 하지만 이는 실제론 그렇지 않다 sizeof(변수or자료형) 함수를 쓰면 그 변수or자료형이 몇 byte를 차지하는지 보여주는데 아래와 같은 결과가 나왔다.

void main(void){
    float value = 2.1;
    printf("%d",sizeof(value));
}

7. 연산자

이 블로그를 읽을 수학과인 내 동기들과 중학교 이상의 수학공부를 한 사람들은 산술 연산자가 익숙하게 느껴질 것이다 그러면 설명해보겠다.
우리가 일상생활에서 쓰는 기호를 생각해보면 다음과 같이 있다.

  • 산술연산자

+,-,x,/(나누기)

위에 4칙연산들은 그대로 쓰면 된다.
하나가 추가되는데 %는 나머지 기호이다

5%3=2

또하나 언급해야 할게 있는데
위에서 말한 /(나누기)는 정수에 대해서 쓰면 몫을 출력하게 되고 실수에 대해서 써야지 정상적으로 나누기가 실행된다
예를보자>

void main(void){
 printf("%f",5.0/2.0);
}


(*float는 소수점6자리까지 저장할 수 있음을 이전 포스팅에서 언급했다)

void main(void){
 printf("%d",5/2);
}

참고로 파이썬에서는 //를 하면 몫이 출력되고 /를 하면 정상적으로 나누기가 된다

C언어에서 주석을 달때는 //를 사용한다 다음과 같다
주석을 사용함으로써 코드를 사용하는 사람들끼리 정보를 공유할 수도 있고 긴 코드의 경우 내가 메모하는 용도로도 사용한다

마지막으로 전위형 증감연산자 후위형 증감연산자가 있는데 이는 다음과 같다

void main(void){
    short int a = 1;
    printf("%d\n",a++);
    printf("%d\n",++a);
}


위에 먼저 출력한 연산자는 후위형 연산자로써 a를 먼저 대입하고 +1을 하는 것이다 그러면 위에 printf가 끝난후에는 a의 값이 2일 것이고 아래의 printf는 전위형 연산자로써 먼저 연산을 한 이후에 대입을 하는것이다. 따라서 값이 3으로 나온다.

  • 관계연산자

관계연산자는 말 그대로 관계를 정의해주는 연산자다 다음과 같은 것들이 있다

값은 1(True) or 0(False)를 반환한다!

void main(void){
 printf("%d",5>2); //이건 주석입니다
}

A<B → A가 B보다 작아?
A>B → A가 B보다 커?
A<=B → A가 B보다 작거나 같아?
A>=B → A가 B보다 크거나 같아?
A==B → A가 B와 같아?
A!=B → A가 B와 같지않아?

위와 같이 컴퓨터에게 질문을 던지고 1(True) or 0(False)를 반환 받는다

  • 논리연산자

수학과 학생들은 집합론을 배웠다면
True&False = False
↑위와 같은 관계를 다 알고 있어야한다
따라서 알고 있다는 전제하에 이를 C언어에서 어떻게 표현하는지 알아보겠다.

C언어에서는 and 연산자 or연산자 not연산자가 있다

and 연산자 → &&
or 연산자 → ||
not 연산자 → !

위에서 not 연산자는 True는 False로 False는 True로 만드는 연산자이다 예로써 보여주겠다
예>

void main(void){
 printf("%d\n",(5>2)&&(5<3)); //이건 주석입니다
 printf("%d\n",(5>2)||(5<3));
 printf("%d\n",!((5>2)&&(5<3)));
}

8,9. 조건문과 반복문

  • 조건문

조건문을 어떻게 쓰는지에 관해서 알려주겠다 이론적인 내용은 책을 한번 쭉 읽어보길 바라고 실용적인 관점에서 설명을 진행해보겠다
예로써 먼저 확인하자

void main(void){
    short int score = 90;
    if(score>=90) printf("%s","JiWook Is A Grade");
    else printf("%s","retire");
}

위에 코드를 해석해보자 score라는 변수를 초기화 했고

if(조건수식) 명령문;
else 명령문;

  • 여기서 조건수식이 참(1)이라면 명령문이 실행된다

위와 같이 써줬다.
이를 영어 번역하듯이 하면 편하게 생각할 수 있다.

만약에 score가 90보다 크거나 같으면 "JiWook Is A Grade" 를 출력해주고
아니면 "retire"를 출력해줘! 라고 명령한 것이다.

여기서 만약에 명령문이 길어질 경우 함수를 정의하듯이 뒤에 { }를 써서 감싸준다. 예시는 다음과 같다.


void main(void){
    short int mean_score = 90;
    if(mean_score>=90){
        printf("%s","JiWook Is A Grade\n");
        printf("%s","JongWook Is A Grade\n");
        }
    else{
        printf("%s","jiwook is retire\n");
        printf("%s","jongwook is retire\n");
    }
}

그런데 항상 조건문이 하나만 붙는다면 당연하게도 엄청나게 제약이 걸릴것으로 예상이 된다. 당연하다. 왜냐면 90점 이상이면 A이라고 if를 달아놓으면 90점 미만은 다 재수강행이기 때문이다.
따라서 if를 여러개 써서 학점을 나눠 놓아야하는데 이는 else 안에 if를 써서 해결할 수도 있지만 else if를 쓰곤 한다. 예시는 다음과 같다. 이것도 역시 자연스럽게 해석을하면 당연한 얘기이다.

void main(void){
    short int mean_score = 75;
    if(mean_score>=90){
        printf("%s","JiWook Is A Grade\n");
        printf("%s","JongWook Is A Grade\n");
        }
    else if(mean_score>=80){
        printf("%s","jiwook is BGrade\n");
        printf("%s","jongwook is BGrade\n");
    }
    else if(mean_score>=70){
        printf("%s","jiwook is CGrade\n");
        printf("%s","jongwook is CGrade\n");
    }
    else if(mean_score>=60){
        printf("%s","jiwook is DGrade\n");
        printf("%s","jongwook is DGrade\n");
    }
    else{
        printf("%s","jiwook is FGrade\n");
        printf("%s","jongwook is FGrade\n");
    }
}

이를 해석해 보면 다음과 같다. 지욱과 종욱의 평균을 기준으로 둘의 학점을 매긴다고 해보면, 지욱과 종욱의 평균은 현재 75점인 상태이다.
컴퓨터 입장에서는 이런 형식이다. 90점 이상이야? → 아니구나 → 혹은 그럼 80점 이상이야? → 이것도 아니네? → 혹은 그럼 70점 이상이야? → 70점 이상이구나 그러면 너는 C학점이야 !

위의 코드를 score를 바꿔가면서 시도해 보길 바란다.

  • 반복문

컴퓨터가 어느 특정 명령을 반복해서 수행하고 싶게 할때가 있을 것이다.
반복문은 크게 for과 while이 있다. 먼저 for과 while의 형태를 보겠다

for(시작조건;종결조건;조건변화수식){}
while(종결조건){}

둘다 종결조건이 거짓이 되면 반복문을 탈출 할 수 있게 된다
예는 다음과 같다

void main(void){
    for(short int i = 0;i<5;i++){
        printf("%d\n",i);
    }
}

결과를 해석해보면 다음과 같다.
i=0부터 시작한다 이때 i의 자료형을 써주지 않는다면 오류가 발생한다.(빨간 밑줄)

i=0 부터 시작해서(시작조건) i<5 이전까지(종결조건) 반복문을 시행할건데 한번 돌때마다 i를 하나씩 키울게(조건변화수식)
따라서 맨처음에는 i에 0이 들어가서 print가 되고 그 이후에는 조건변화 수식이 적용돼서 i=1,2,3,4 까지 출력이 되는 것이다.
Q> 조건 변화 수식에 ++i를 쓴다면 어떻게 될까? 한번 시도해보길 바란다

같은 결과를 while문으로 출력해보겠다.

cnt=0으로 초기화를 진행했고 5가 아닌동안에는 while문이 돌아가는 것이다.

그렇다면 무한 loop가 무엇인지 알아보자.
우리는 종종 무한루프를 써야할 경우가 있다.
무한루프가 무엇이냐면 조건을 항상 참이되게 만들어서 반복문을 끝없이 돌아가게 하는 것이다.
무한 루프를 만들기 위해서는 다음과 같이 진행한다.
먼저 for문>

void main(void){
    short int cnt = 0;
    for(;;){
        cnt++;
        if(cnt==5) continue;
        printf("%d\n",cnt);
        if(cnt==10) break;
    }
}


하나씩 해석해보자 for의 종결조건 없기 때문에 무한루프로써의 역할을 한다.
이때 cnt++로 count를 계속 증가시키고 출력을 할 것인데
if(cnt==5) continue;에서 continue의 역할은 continue 이후의 코드는 생략하고 다시 for loop의 처음으로 돌아가라는 의미이다.(이는 while의 경우에도 loop의 처음으로 돌아가라는 의미로써 작용한다.) 따라서 결과를 보면 5가 생략되고 바로 6이 출력됨을 볼 수 있다.
그 이후 if(cnt==10) break;에서 break는 cnt가 10이면 이 for loop를 끝 마치라는 의미이다.(이는 while의 경우에도 loop를 끝마치라는 의미로써 작용한다.)

이제 while문으로 같은 결과를 출력해보겠다.

void main(void){
    short int cnt = 0;
    while(1){
        cnt++;
        if(cnt==5)continue;
        printf("%d\n",cnt);    
        if(cnt==10) break;
    }
}


이를 스스로 해석해 보길 바란다 여기서 while(종결조건)에서 종결조건을 항상 True를 의미하는 1을 적어줌으로써 무한 루프로 만든 것이다.

질문: 구구단을 다음과 출력하고 싶다. 이경우엔 어떻게 해야할까?

이는 하나의 반복문으로 해결될 일이 아니다.
이경우에는 중첩 반복문을 사용해야하는데 말그대로 반복문 안에 반복문을 사용하는 것이다.

while안에 for문을 사용할수도 있고 for문을 두개 사용할 수도 있다.

예시를 보여주겠다>

void main(void){
    short int number =1;
    while(number!=10){
        short int count = 1;
        for(count;count<10;count++){
            printf("%d",number);
            printf("%d",count);
        }
        number++;
    }
}


위와 같은 결과가 나오면 잘 나온 결과이다 어떤 구조로 이런 결과가 나왔는지 확인해 본후 for문을 사용해서 똑같은 결과를 내보길 바란다.

이 정도까지 알려줬으면 지금까지 사용한 결과들을 이용해서 위에 질문을 해결하길 바라겠다 다음 업로드 초반에 정답을 올리겠다.

다음 포스팅은 지역변수와 전역변수 배열 그리고 포인터 조금을 나가겠다.

<10장은 생략>

profile
Time-Series

1개의 댓글

comment-user-thumbnail
2023년 3월 3일

sizeof 는 단항 연산자(unary operator) 입니다. 따라서 이하와 같이 작성이 가능합니다:

int a;
printf("sizeof(a): %zu\n", sizeof a);
답글 달기