배움 저장소

홍정모의 따라하며 배우는 C언어 7 분기 본문

Programming Language/C

홍정모의 따라하며 배우는 C언어 7 분기

시옷지읏 2021. 11. 15. 00:19

7.1 분기문 IF

if(Expression)
	Statement

이 때 Expression은 0일 때 false 아닐때 true로 간주한다.

 

7.2 표준 입출력 함수

// Case 1
int ch;
do{
    ch = getchar();
    putchar(ch);
} while (ch != '\n');

// Case 2
int ch;
while( (ch=getchar()) != '\n')
{
    putchar(ch);
}

두 번째 예시에서 = 연산자는 우선순위가 낮으므로 ch=getchar()를 먼저 실행시켜주기 위하여 ( ) 를 사용해야 한다.

 

Filtering: Convert Numbers to Asterisks

// Case 1
int ch;
while( (ch=getchar()) != '\n')
{
    // Filtering
    if(ch == 'f' || ch == 'F') 
        ch = 'X';

    for(int i='0'; i<'9'; ++i)
        if(ch==i)
            ch = '*';
    putchar(ch);
}

// Case 2
char ch;
while( (ch=getchar()) != '\n')
{
    // Filtering
    if('0'<= ch && ch <= '9')
        ch = '*';
    putchar(ch);
}

 

소문자  대문자 바꾸기

int ch;
while( (ch=getchar()) != '\n')
{
    if('a' <= ch && ch <= 'z') // a = 97  A = 65
        ch -= 'a' - 'A';
    else if('A' <= ch && ch <= 'Z')
        ch += 'a' - 'A';
    putchar(ch);
}

 

7.3 CTYPE.H 문자 함수

// #include <ctype.h>
int ch;
while( (ch=getchar()) != '\n')
{
    if(islower(ch))
        ch = toupper(ch);
    else if(isupper(ch))
        ch = tolower(ch);
     
    if(isdigit(ch))
        ch = '*';
        
    putchar(ch);
}

https://www.tutorialspoint.com/c_standard_library/ctype_h.htm

 

C Library - <ctype.h>

C Library - The ctype.h header file of the C Standard Library declares several functions that are useful for testing and mapping characters. All the functions accepts int as a parameter, whose value must be EOF or representable as an unsigned char. All the

www.tutorialspoint.com

 

7.4 else if

// Case 1
if ( Expression1 )
	Statement
else if( Expression2 )
	Statement
    
// Case 2
if ( Expression1 )
	Statement
if( !Expression1 && Expression2 )
	Statement

Case1과 Case2는 동일하다.

 

7.6 소수 판단 예제

12가 소수인지 판단하기

12의 약수: 1 2 3 4 6 12

1 x 12 = 12

2 x  6 = 12

3 x  4 = 12 이다.이제 12가 소수인지 판단하기 위해 자신의 약수를 나누어본다. 1,2,3으로 나눈다. 나누어지는 값은 4,6,12로 각각 12의 약수이므로 나누어보지 않아도 확인이 된다.

 

16가 소수인지 판단하기

이를 다른 숫자에도 적용할 수 있다.

16의 약수: 1,2,4,8,16 이다. 4까지만 나누어보아도 판단이 가능하다.

 

일반화

 이러한 약수는 제곱근을 기준으로 서로 짝을 짓고 있다. 이러한 성질을 이용해서 해당 숫자가 소수인지를 판단하면 유용하다. 2부터 그 수의 제곱근까지만 검사해보면 된다. 하나라도 나누어떨어지면 소수가 아니다.

따라서 반복문의 expression에 div * div <= num를 사용할 수 있다.

 

7.7 논리연산자 Logical Operator

!  : not
&& : and
|| : or
char ch
int count = 0;
while( (ch = getchar()) != '.')
{
    //if(ch != '\n')
       count++;
}
printf("%d", count);

getchar( ) 함수는 입력 시 줄바꿈('/n') 문자도 인식하여 "A" Enter "B" Enter "C" " . " 을 입력하면 cout = 5개가 된다. 그래서 if 조건문을 넣어주면 예상대로 count=3이 된다.

 

iso164.h

// #include <iso646.h>
#define not !
#define and &&
#define or ||

// main.c
bool test  = 3 > 2 or 5 == 4;
bool test2 = 3 > 2 || 5 == 4;

- iso646.h 파일을 사용하면 Operator 대신에 or, and, not 를 사용할 수 있다.

- 우선순위   ' ! ' > ' && ' > ' || ' 

https://en.cppreference.com/w/c/language/operator_precedence

 

C Operator Precedence - cppreference.com

The following table lists the precedence and associativity of C operators. Operators are listed top to bottom, in descending precedence. Precedence Operator Description Associativity 1 ++ -- Suffix/postfix increment and decrement Left-to-right () Function

en.cppreference.com

 

Short-circuit Evaluation

int temp = (1+2)*(3+4);
printf("Before : %d\n", temp);   // => 21
if(temp==0 && (++temp == 1024));
printf("After  : %d\n", temp);   // => 21

- 위 코드의 temp 출력값은 둘 다 21이다. && operator 앞에 있는 expression이 false일 때 뒤에 있는 expression은 실행되지 않기 때문에 그냥 넘어간다. 만약 앞의 expression이 true가 되면 두 번째 출력값이 22가 됨을 확인해볼 수 있다.

- ' && '와 ' || '는 Sequence Point 이다.

 

int x = 0, y = 1;
if (x++ == 0 && x + y == 2)
{
    printf("In if statement x=%d\n", x); // >> In if statement x=1
}
printf("x=%d y=%d \n", x, y);            // >> x=1 y=1

&&가 Sequence Point이기 때문에 x++<0 expression이 먼저 계산되고 뒤에 있는 expression을 확인한다.

 

Comparison operator의 잘못된 사용 (10 <= i <= 20)

for(int i=0; i<100; ++i)
    if(10 <= i <= 20)     // if((10 <= i) <= 20)
        printf("%d ", i);

Expression (10 <= i)의 값은 true 또는 false이다. 숫자로 나타내면 0과 1이다.

0과 1은 20보다 항상 작으므로 if 조건문이 항상 true를 얻게된다.

 

 

7.8 단어 세기 예제

#include <ctype.h>

int main()
{
    char ch;
    int n_chars = 0;
    int n_lines = 0; 
    int n_words = 0;
    
    // 첫 라인에 n_line++를 실행시켜줄 수 있다
    // isspace()함수는 띄어쓰기, 줄바꾸기를 모두 Count
    // 그래서 라인바꿔주기를 따로 확인해주어야 한다.
    bool line_flag = false;

	// 첫 문자에 n_word++를 실행시킬 수 있다
    // 공백 or 줄바꾸기 이후 Count를 늘린다.
    bool word_flag = false;

    printf("Enter Text : \n");
    while((ch=getchar()) != '.')
    {
        if(!isspace(ch))
        { n_chars++; }
        
        if( !isspace(ch) && !line_flag)
        {
            n_lines++;
            line_flag = true;
        }

        if(ch == '\n')
        { line_flag = false; }

        if( !isspace(ch) && !word_flag)
        {
            n_words++;
            word_flag = true;
        }
        if( isspace(ch))
        { word_flag = false; }
    }

    printf("n_chars=%d,n_words=%d,  n_lines=%d", n_chars, n_words, n_lines);
    return 0;
}

Refactoring

#include <ctype.h>

int main()
{
    char ch;
    int n_chars = 0;
    int n_lines = 0; 
    int n_words = 0;

    bool word_flag = false;
    bool line_flag = false;

    printf("Enter Text : \n");

    while((ch=getchar()) != '.')
    {
        if( !isspace(ch) )
        {
            n_chars++; 
            if(!line_flag)
            {
                n_lines++;
                line_flag = true;
            }
        }

        if(ch == '\n')
        { line_flag = false; }

        if( isspace(ch))
        { word_flag = false; }
        else if(!word_flag)
        {
            n_words++;
            word_flag = true;
        }
    }
    printf("n_chars=%d,n_words=%d,  n_lines=%d", n_chars, n_words, n_lines);
    return 0;
}

 

7.9 조건연산자

bool 데이터타입 변수를 선언과 함께 변하지 않는 상수값으로 설정하고 싶다면 ?(trenary) 연산자를 사용하자. 

int number;
scanf("%d", &number);

// const + trenary Operator
const bool isEven = (number % 2 == 0 ) ? true : false;

Trenary(?) Operator와 함수도 함께 쓸 수 있다. 하지만 flag (bool 데이터 타입) 변수를 만들어서 if 조건문 이하에서 구현하는 것이 일반적이다.

// Trenary Opeartor with Function
(number % 2 == 0) ? printf("Even") : printf("Odd");

// Trenary Operator in flag, using it in If statement
bool isEven = (number % 2 == 0) ? true : false;
if( isEven )
    printf("Even");
else
    printf("Odd");

 

7.10 Loop 도우미 Continue 와 Break

while 반복문에서 { } body가 없을 때 이를 continue로 대신 표기해줄 수 있다

/* continue as a place holder */
while( getchar() != '\n' )
    continue;

 

break는 가장 가까운 for 반복문을 중지시킨다.

for(int i=0; i<10; ++i)
{
    for(int j=0; j<10; ++j)
    {
        if(j==5)
            break;
        printf("(%d,%d) ", i,j);
    }
}

/*  출력값
    (0,0) (0,1) (0,2) (0,3) (0,4) (1,0) (1,1) (1,2) (1,3) (1,4) 
    (2,0) (2,1) (2,2) (2,3) (2,4) (3,0) (3,1) (3,2) (3,3) (3,4) 
    (4,0) (4,1) (4,2) (4,3) (4,4) (5,0) (5,1) (5,2) (5,3) (5,4) 
    (6,0) (6,1) (6,2) (6,3) (6,4) (7,0) (7,1) (7,2) (7,3) (7,4) 
    (8,0) (8,1) (8,2) (8,3) (8,4) (9,0) (9,1) (9,2) (9,3) (9,4)  
*/

 

7.12 다중 선택 switch와 break

switch(expression)에서 expression은 정수 형태만 가능하다.

    char ch;
    while ((ch = getchar()) != '.')
    {
        switch (ch)
        {
        case 'a': case 'A':
            printf("type is start with A\n");
            break;
        case 'b':
        case 'B':
            printf("type is start with B\n");
            break;
        default:
            printf("Nothing\n");
        }
        //while( getchar() != '\n')
        //    continue;
    }

while( getchar() != '\n') continue를 사용하면 첫 번째 문자값만 switch( ) 이하 코드가 실행된다.

while( getchar() != '\n') continue를 주석처리하면 입력한 모든 문자를 대상으로 switch( )이하 코드가 실행된다.

 

 

7.13 Goto

잘 사용하지 않는다. CPU가 일하는 방법과 가깝다

read: c = getchar();
    putchar(c);
    if(c == '.' ) goto quit;
    goto read;
quit:
    return 0;

 

Comments