본문 바로가기

Programming/C

[ProjectH4C] 코드업(CodeUp) 기초 100제 1021~1040 Write-up

#1021   단어 1개 입력받아 그대로 출력하기

문자와 문자열이라는 것이 있다. 문자는 한 글자, 예를 들어 a, b Q, V, M 등을 문자라고 한다. 이들이 두 개이상 모여있을시

이를 문자열이라 한다. 문자를 표현할 땐 작은 따옴표를 이용해서 'a'와 같이 표현하고, 문자열은 "이런식으로" 표현한다.

기본적으로 문자형 변수는 여러 문자를 담지 못한다. 그러니까 한 글자만 저장할 수 있고 한 단어는 저장하지 못한다.

이러한 문제를 배열로 해결 할 수 있다.

배열이란 같은 자료형의 변수 여러개를 하나의 이름으로 묶어 놓은 것이라고 보면 된다. 만약 apple이란 단어를 저장하고자 한다면

'a', 'p', 'p', 'l', 'e' 각각을 저장할 공간과 마지막에 '\0'을 저장할 공간까지 총 6개 짜리 배열을 이용하면 된다.

 

배열 사용 시 주의할 점

- 배열의 이름은 첫 번째 인덱스의 주소 값을 가짐. scanf를 사용할 시에 변수의 주소 값을 넘기기 위해 &를

앞에 붙였지만, 배열은 이름 자체가 주소 값을 나타내기에 & 없이 이름만 쓰면 된다.

- 크기가 10인 배열 arr[10]을 선언했다면, 각각의 변수는 arr[1] ~ arr[10]이 아닌 arr[0] ~ arr[9]가 된다.

이때의 배열의 주소값은 arr.

 

이렇게 각각의 글자를 담을 공간을 만듦으로써 문자열을 구현할 수 있게 된다. 이 때, 형식 지정자는 %c가 아닌 String(문자열)의 앞

글자를 따서 %s를 사용한다.

#include <stdio.h>

int main(){
    char buf[51]="";
    scanf("%s", buf);
    printf("%s", buf);
    
    return 0;
}

 

#1022   문장 1개 입력받아 그대로 출력하기

하나의 단어를 입력받고자 할 땐 scanf를 이용하면 된다. scanf는 개행문자('\n') 또는 공백(' ')을  만날 때 까지 입력을 받는다. 만약 띄어쓰기로 구분 된 두 개의 단어를 입력한다면 띄어쓰기 이후의 문자열은 증발하고 앞의 한 단어만 변수에 저장된다. 이런 경우엔 scanf 대신 fgets 함수를 이용하면 된다. fgets는 공백까지도 문자로 처리하고 오직 개행문자('\n')를 만나야만 입력을 그만 둔다. fgets의 형태는

fgets(변수명, 입력할 글자 수, 입력 스트림); 

이 된다. 여기서 스트림에 대해 짚고 넘어가고자 한다.

 

스트림(Stream)

'한 방향으로 흐르는 데이터의 흐름'이란 뜻을 가지고 있다. 즉, 스트림이란 용어 자체에는 단 방향으로만 데이터 전송이 이루어진다는 의미가 내포된다. 실제로 입력하는 방향의 스트림을 입력 스트림, 출력하는 방향의 스트림을 출력 스트림이라고 칭한다. 스트림의 의미는 이와 같고, 실제로 스트림이 하는 역할은 프로그램과 모니터, 키보드와 같은 장치 사이를 연결해주는 매개체 역할을 한다. 예를 들어 printf, scanf함수를 사용할 때, 키보드를 통해 입력 받고, 모니터를 통해 출력하는 과정에서 그 사이의 다리 역할을 해주는 것이 스트림이다. 하지만 우리가 printf, scanf 함수를 사용할 때 스트림을 따로 지정해주지 않아도 프로그램은 알아서 키보드로 입력받고 모니터로 출력해준다. 이처럼 기본적으로 제공해주는 스트림을 "표준 스트림(Standard Stream)"이라고 한다. C언어 상에서 제공하는 표준 스트림은 다음과 같다.

 

  • stdin = 표준 입력 스트림, 키보드 대상으로 입력
  • stdout = 표준 출력 스트림, 모니터 대상으로 출력
  • stderr = 표준 에러 스트림, 모니터 대상으로 출력
#include <stdio.h>

int main(){
    char buf[2001];
    fgets(buf, 2000, stdin);
    printf("%s", buf);
    
    return 0;
}

 

#1023 실수 1개 입력받아 부분별로 출력하기

실수를 입력받는다면 XX.XXX 형태로 입력받게 될 것이다. 그렇다면 정수부와 소수부를 나누는 가장 간편한 방법은

입력 형태를 XX.XXX 로 받고 . 앞의 수를 a(정수부), . 뒤의 수를 b(소수부)에 저장하면 끝이다.

입력 예시를 제대로 보지 않아 1.000009 같은 값이 들어오면 소수부를 출력할 때 000009가 아닌 9가 출력 될 것

같아서 처음엔 b의 값을 %06d로 입력 받았지만, 문제를 다시 보고서는 아차 싶었다.

0이 아닌 숫자로 시작한다면 %d로만 받아도 소수점 아래 6자리가 모두 출력 될 것이다. 

#include <stdio.h>

int main(){
    int a, b;
    
    scanf("%d.%d", &a, &b);
    printf("%d \n", a);
    printf("%d", b);
    
    return 0;
}

 

#1024   단어 1개 입력받아 나누어 출력하기

C언어에서의 문자열이란, 단어 그 자체를 변수에 저장하는 개념이 아니라 문자형 배열을 이용해 문자 하나 하나 따로 저장한 후에 

출력 할 때 이들을 이어서 출력함으로써 문자열처럼 보이게끔 처리해야 한다.

이때 배열의 맨 마지막에는 문자열이 끝났다는 의미로 NULL문자('\0')를 넣어줘야 하고, 컴파일러는 널 문자를 만나면 출력을 멈추게 된다.

그러니 실질적으로 배열의 크기는 입력할 단어 + NULL문자를 위한 공간이여야 해서 입력할 단어 + 1개의 크기로 선언해야 한다.

for문은 반복문이라고 하며 조건이 참일 경우 for문 안의 내용을 실행하고 조건이 거짓이 될 때까지 반복하게 된다.

이 들을 이용하면 문자열을 입력한 배열의 첫 번째 인덱스부터  NULL문자를 만나기 전까지 각각의 인덱스, 그러니까 각각의 단어들에 대해

접근 할 수 있다.

#include <stdio.h>

int main(){
    char d[30];
    int i;
    scanf("%s", d);
    for(i=0; d[i]!='\0'; i++){
        printf("\'%c\' \n", d[i]);
    }
    return 0;
}

#1025 정수 1개 입력받아 나누어 출력하기

보통은 두 개의 정수를 입력받을 때 띄어쓰기, 점 등으로 구분해서 한 번에 입력받을 수 있지만

띄어쓰기 없이도 가능하다. 이 땐, 얼만큼의 길이의 숫자를 변수에 저장할 건지 지정해주어야 한다.

예를 들어,

scanf("%d%d", &x, &y);

에서 1234를 입력한다면 1234에서 x에 저장될 값이 얼마인지, y에 저장될 값이 얼마인지 모호해지게 되는데

이럴 땐 

scanf("%2d%2d", &x, &y);

위의 코드처럼 작성하면 1234를 입력하면 x, y에 각각 12, 34가 저장된다는 걸 알 수 있다.

#include <stdio.h>

int main(){
    int a, b, c, d, e;
    scanf("%1d%1d%1d%1d%1d", &a, &b, &c, &d, &e);
    printf("[%d] \n", a*10000);
    printf("[%d] \n", b*1000);
    printf("[%d] \n", c*100);
    printf("[%d] \n", d*10);
    printf("[%d] \n", e*1);
    
    return 0;
}

 

#1026 시분초 입력받아 분만 출력하기

계속 같은 맥락이다. 시분초를 :으로 구분지어서 입력받는다.

hh:mm:ss로 입력 받으면 mm에 해당하는 변수만 출력해주면 된다.

#include <stdio.h>

int main(){
    int h, m, s;
    scanf("%d:%d:%d", &h, &m, &s);
    printf("%d \n", m);
    
    return 0;
}

#1027 년월일 입력 받아 형식 바꿔 출력하기

yyyy.mm.dd의 형태로 입력받아 dd-mm-yyyy의 형태로 출력한다.

yyyy, mm, dd를 각각의 변수에 저장한 후 출력하는 순서만 바꿔준 다음, 그 사이사이에 -를 출력해주면 된다.

 

주의할 점 -> 7월이 7로 출력이 되는게 아니라 07로 출력이 된다. mm, dd를 출력할 땐 %02d, yyyy는 %04d로 출력해야 한다.

#include <stdio.h>

int main(){
    int y, m, d;
    scanf("%d.%d.%d", &y, &m, &d);
    printf("%02d-%02d-%04d", d, m, y);
    
    return 0;
}

#1028 정수 1개 입력받아 그대로 출력하기2

C언어에서는 자료형 마다 할당되는 크기가 다르다.

문자형 변수인 char은 1byte, int는 4byte, float은 4byte, double은 8byte 된다.

int형의 4byte를 bit로 변환하면 1byte=8bit 이므로 32bit인데 1비트 = 이진수 한자리 라고 생각하면 된다.

32개의 비트 중 맨 앞의 비트는 부호비트라고 하여서 양수이면 0, 음수이면 1이다. 나머지 31개의 비트가 값을 결정하는데,

앞자리가 0일 경우 2^31 = 2,147,483,648 보다 1 작은 2,147,483,647까지 가능하고, 앞자리가 1일 경우 2,147,483,648까지 가능하다.

다시 말해 int형 변수의 공간에 들어갈 수 있는 수의 범위는 -2,147,483,648 ~ 2,147,483,647이 된다.

하지만 음수가 존재할 수 없는 키, 몸무게 따위를 저장하고자 한다면?

그 땐 int 대신 unsigned int로 선언해주면 된다. unsigned int는 양수의 값만 존재하는데, 그렇다면 맨 앞자리를 부호비트로 쓸 이유가 없기때문에 32개의 비트를 모두 숫자를 표현하는데 사용할 수 있고, 조금 더 큰 숫자를 표현할 수 있다.

2^32 = 4,294,967,296 => 0 ~ 4,294,967,295 표현 가능.

 

주의할 점 -> unsigned int의 입출력 형식은 %d가 아닌 %u.

#include <stdio.h>

int main(){
    unsigned int n;
    scanf("%u", &n);
    printf("%u \n", n);
    
    return 0;
}

#1029 실수 1개 입력받아 그대로 출력하기2

float -> -3.4*10^38 ~ +3.4*10^38

double -> -1.79*10^308 ~ +1.79*10^308

double이 조금 더 큰 범위의 실수를 표현할 수 있다. 문제에서 주어진 입력되는 실수의 범위가 double형으로 표현할 수 있는 범위이기

때문에 double형 변수를 사용한다. 이때의 형식 지정자는 %lf가 된다.

 

주의할 점 -> 실수형은 기본으로 소수점 아래 6번째 자리까지만 표기 됨. 11자리까지 표시해야 하기 때문에 %.11lf로 출력해야 한다.

#include <stdio.h>

int main(){
    double d;
    scanf("%lf", &d);
    printf("%.11lf \n", d);
    
    return 0;
}

 

#1030 정수 1개 입력받아 그대로 출력하기3

int, unsigned int는 둘다 4바이트의 크기이지만, 그보다 더 큰 수를 출력하는 방법이 있다.

long long int -> 8바이트의 범위를 표현할 수 있다.

형식 지정자 : %lld (long long decimal의 약자).

#include <stdio.h>

int main(){
    long long int n;
    scanf("%lld", &n);
    printf("%lld", n);
    
    return 0;
}

 

#1031 10진 정수 1개 입력받아 8진수로 출력하기

정수를 입출력할때 썼던 %d에서 d는 Decimal(10진수)의 약자로, 만약 10진수가 아닌 8진수로 출력하고 싶다면 %o를 사용하면 된다.

%o -> 8진수(octal)

#include <stdio.h>

int main(){
    int n;
    scanf("%d", &n);
    printf("%o", n);
    
    return 0;
}

#1032 10진 정수 입력받아 16진수로 출력하기1

16진수로 출력하려면 %x를 사용하면 된다.

%x -> 16진수(hexadecimal)

#include <stdio.h>

int main(){
    int n;
    scanf("%d", &n);
    printf("%x", n);
    
    return 0;
}

#1032 10진 정수 입력받아 16진수로 출력하기2

16진수의 출력 형태는 두 가지가 있다. 10~15의 수를 A~F를 사용해서 표현하는데, 이들을 소문자로 출력하려면 소문자 x, 대문자로 출력하려면 대문자 X로 작성하면 된다.

 

%x -> a ~ f

%X -> A ~ F

#include <stdio.h>

int main(){
    int n;
    scanf("%d", &n);
    printf("%X", n);
    
    return 0;
}

#1034 8진 정수 1개 입력받아 10진수로 출력하기

입력이 8진수이기 때문에 scanf("%o", &n)로 입력을 받고, 출력은 10진수이기 때문에 printf("%d", n)와 같이 해주면 된다.

#include <stdio.h>

int main(){
    int n;
    scanf("%o", &n);
    printf("%d", n);
    
    return 0;
}

#1035 16진 정수 1개 입력받아 8진수로 출력하기

%x 또는 %X로 입력받은 후 %o로 출력해주면 된다.

#include <stdio.h>

int main(){
    int n;
    scanf("%x", &n);
    printf("%o", n);
    
    return 0;
}

#1036 영문자 1개 입력받아 10진수로 출력하기

C언어에선 문자를 입력하면 문자가 그대로 저장되는게 아니라 아스키 코드로 변환되어 변수에 저장된다.아스키코드는 

정수로 구성되어 있기 때문에 문자형 변수를 정수로 출력하면 상응하는 아스키 코드 값을 출력할 수 있다.

 

아스키코드(ASCII, American Standard Code for Information Interchange)

  -> 미국 표준 협회가 주도해서 표준화한 부호체계.

#include <stdio.h>

int main(){
    char ch;
    scanf("%c", &ch);
    printf("%d", ch);
    
    return 0;
}

#1037 정수 입력받아 아스키 문자로 출력하기

입력은 %d, 출력은 %c로 해주면 되고 정수를 입력받기 때문에 당연히 변수는 정수형으로 선언해주어야 한다.

#include <stdio.h>

int main(){
    int n;
    scanf("%d", &n);
    printf("%c", n);
    
    return 0;
}

#1038 정수 2개 입력받아 합 출력하기1

지금까지는 printf("%d", a)와 같이 변수 그 자체를 출력하는 문제만 풀었는데,

그 자체의 값이 아닌 하나의 식을 입력하여도 그 결과가 계산되어 출력된다.

예를 들어, a와 b를 입력받고 이들의 합을 구하기 위해선 

int a, b, c;

scanf("%d %d", &a, &b);

c = a + b;

printf("%d", c);

와 같이 작성하여도 되지만 c를 선언하지 않고

 

int a, b;

scanf("%d %d", &a, &b);

printf("%d", a+b);

와 같이 바로 결과를 출력할 수 있다. 이 때, c를 할당하지 않은 만큼의 메모리를 확보할 수 있다는 장점이 있다.

 

문제에서 주어진 범위 내에서 나올 수 있는 결과 중 가장 큰 값은 2,147,483,648 이고, int의 범위를 벗어나게 되기 때문에 

long int로 선언해주는 것이 좋을 것 같다.

#include <stdio.h>

int main(){
    long int a, b;
    scanf("%ld %ld", &a, &b);
    printf("%ld", a+b);

    return 0;
}

#1039 정수 2개 입력받아 합 출력하기2

입력되는 정수의 범위에서 가장 큰 두 값을 더하면 long int의 범위를 넘어가기 때문에 long long int로 선언해주는 것이 좋을 것 같다.

#include <stdio.h>

int main(){
    long long int a, b;
    scanf("%lld %lld", &a, &b);
    printf("%lld", a+b);
    
    return 0;
}

 

#1040 정수 1개 입력받아 부호 바꿔 출력하기

만약 int a=10; 으로 선언했다면 a의 부호를 바꿔주는 방법은 a 앞에 -를 붙여주면 된다.

ex)

int a=10;

printf("%d", a);     //10 출력

printf("%d", -a);   //-10 출력

#include <stdio.h>

int main(){
    int n;
    scanf("%d", &n);
    printf("%d", -n);
    
    return 0;
}