728x90

21-1

 

프로그램 사용자로부터 알파벳 문자를 하나 입력받아서, 입력받은 문자가 대문자면 이를 소문자로변환해서 출력해주고, 입력받은 문자가 소문자면 이를 대문자로 변환해서 출력해주는 프로그램을 작성해보자. 단, 문자의 입출력에는 getchar함수와 putchar함수를 사용하기로하자. 그리고 프로그램 사용자가 알파벳 이외의 문자를 입력하는 경우에는 오류메시지를 간단히 출력하기로 하자.

#include <stdio.h>
int ConvCase(int ch){
    int diff='a'-'A';
    if(ch>='A'&&ch<='Z'){
        return ch+diff;
    }
    else if(ch>='a'&&ch<='z'){
        return ch-diff;
    }
    else{
        return -1;
    }
}
int main(void){
    int ch;
    printf("문자입력:");
    ch=getchar();
    ch=ConvCase(ch);
    if(ch==-1){
        puts("범위벗어남");
        return -1;
    }
    putchar(ch);
    return 0;
}

21-2

 

문제1) 적당한 길이의 문자열을 입력받아서 그 안에 존재하는 숫자의 총 합을 계산해서 출력하는 프로그램을 작성해보자. 예를 들어서 프로그램 사용자로부터 입력 받은 문자열이 "A15#43"이라 하면, 이 문자열중 아라비아 숫자는 1,5,4,3이니 1+5+4+3의 연산결과가 출력되어야 한다.

#include <stdio.h>
int sum=0;
int number(char c){
    static int diff=1-'1';
    printf("%d A15#43", diff);
    return c+diff;
}
int main(void){
    char str[10];
    printf("문자열 입력: ");
    fgets(str,sizeof(str), stdin);
    int len=strlen(str);
    for(int i=0;i<len;i++){
        if('1'<=str[i]&&str[i]<='9'){
            sum+=number(str[i]);
        }
    }
    printf("%d", sum);
    return 0;
}

사실 이 내용을 이해하는데에 꽤 오랜 시간이 걸렸다. 그래도 이해를 했으니 말로 설명을 해보도록 하겠다.

일단 문자열을 입력 받는데에는 어려움이 없다. 여기 단원에서 배운 fget을 이용하면 훨씬 좋고 strlen을 배웠으므로 문자열 길이도 계산 간으하다. for문까지 만드는데에는 쉬운데 여기서 조금 걸렸다. 숫자만 걸러내는 과정이 필요하다.

숫자를 걸러내기 위해서는 먼저 문자 '1' 과 '9' 사이에 있도록 해야 한다. 그리고 여기서 왜 함수를 써야하는지 의문이 들었는데 그 이유는 문자이기 때문이다. 합을 위해서는 숫자로 바꾸어 주어야 한다. 문자 1은 49이다. 그리고 숫자 1은 1이다. 즉 48만큼의 차이가 있다는 것이다. 다른 숫자도 같은 간격이다. 그러므로 '문자+문자와 숫자 간격'을 더해주면 문자가 숫자로 바뀌는 처리가 된다. 이를 통해 합을 구해주어야 숫자가 정상적으로 더해질 수 있다. 이 처리를 해주지 않는다면 쓰레기 값이 나오게 된다.

마지막으로 합을 출력해주면 끝이다. 


 

문제2) 다음과 같이 총 3개의 배열을 선언한다.

char str1[20];

char str2[20];

char str3[20];

그리고는 str1과 str2를 통해서 프로그램 사용자로부터 문자열을 입력 받되, fgets함수 호출을 통해서 입력받는다. 이어서 str1에 저장된 문자열을 str3에 복사하고,str2에 저장된 문자열을 str3에 저장된 문자열의 뒤에 덧붙이자. 그리고 마지막으로 str3에 저장된 문자열을 출력하자. 다소 설명이 복잡했는데, 예를 들어서 str1과 저장된 문자열이 각각 다음과 같다면,

str1   "Simple"

str2   "String"

str3에는 문자열"SimpleString이 저장되어야한다. 그런데 여기서 한가지 주의해야 할 사항이 있다. fgets 함수를 통해서 문자열을 읽어들이면 \n문자도 함께 읽혀지는데 이는 문자열의 일부가 되지 않도록 해야 한다는 점이다. 쉽게 말해서 str1과 str2에 저장된 문자열에서 \n은 소멸시켜야 한다.

#include <stdio.h>
#include <string.h>

int main(void){
    char str1[20];
    char str2[20];
    char str3[20];

    fgets(str1, sizeof(str1),stdin);
    fgets(str2, sizeof(str2),stdin);

    str1[strlen(str1)-1]=0;
    strcpy(str3,str1);
    strcat(str3,str2);

    puts(str3);
}

여기서는 문자열을 선언하고 입력받는데까지는 큰 어려움이 없었다. 그렇지만 조금 머뭇거리던 부분은 바로 \n을 없애는 부분이었다. 이것을 없애주기 위해서는 별도의 줄에서 처리를 해 주어야 한다. strlen이 1개보다 작은 것이 끝자리다. 0부터 시작하기 때문이다. 그래서 여기 부분을 0으로 처리해준다. 그러면 \n이 사라질 수 있다. 이후에는 copy 하는 형태인 strcpy를 이용하고 뒤에 붙여주는 형태인 strcat을 하면된다. 이 두가지를 생각하고 \n형태는 더더욱 기억하는 것이 앞으로 문제풀 때 중요할 것 같다는 생각이 들었다.

 


문제3) 프로그램 사용자로부터 이름과 나이를 다음의 형식에 맞춰서 하나의 무자열로 입력 받는다.

"이정선 29"

"한수정 7"

"오선주 17"

이름은 세글자가 아닐 수도 있고 영문으로 입력될 수도 있다. 단 이름과 나이 사이에만 공백이 삽입되어야 한다. 이러한 형식으로 두 사람의 정보를 입력 받아서 이름과 나이가 각각 닽은지 다른지를 판단하여 출력하는 프로그램을 작성해보자. 참고로 이 문제는 수준이 어느정도 있는 문제이니 천천히 생각하며 해결하기 바란다.

#include <stdio.h>
#include <string.h>

int main(void){
    char str1[20];
    char str2[20];
    int age1;
    int age2;

    printf("이름과 나이 입력1: ");
    scanf("%s %d", &str1, &age1);
    printf("이름과 나이 입력2: ");
    scanf("%s %d", &str2, &age2);
    if(!strcmp(str1,str2)){
        puts("두 사람의 이름은 같습니다.");
        if(age1==age2){
            puts("두 사람의 나이는 같습니다.");
        }
        else{
            puts("두 사람의 나이는 다릅니다.");
        }
    }
    else{
        puts("두 사람의 이름은 다릅니다.");

        if(age1==age2){
            puts("두 사람의 나이는 같습니다.");
        }
        else {
            puts("두 사람의 나이는 다릅니다.");
        }
    }
}

음 나는 어렵게 풀지 않았다. 풀이를 보니 굉장히 복잡하게 함수로 엮여져 있는데 나는 그냥 한 곳 안에서 끝내버렸다. 이번 단원에서 배운 것중에 사용한 것은 strcmp이다 문자 비교인데 이것을 이용하여 이름을 판단해 주었다. 숫자는 문자 비교 보다는 아무래도 같은지 다른지 한번에 판단이 가능하기 때문에 if문 안에서 ==을 이용해 해 주었다. 이를 if  else로 나누어서 풀었다. 출력은 puts로 해 주었다.

728x90
728x90

도전1) 길이 10인 배열을 선언하고 총10개의 정수를 입력받아서, 홀수와 짝수를 구분지어 출력하는 프로그램을 작성해보자. 일단 홀수부터 출력하고 나서 짝수를 출력하도록 하자. 단, 10개의 정수는 main함수 내에서 입력받도록 하고 배열 내에 존재하는 홀수만 출력하는 함수와 배열 내에 존재하는 짝수만 출력하는 함수를 각각 정의해서 이 두 함수를 호출하는 방식으로 프로그램을 완성하자

(수정: 21.10.12/한정된 코드로 되어 있어 새롭게 수정)

#include <stdio.h>
int main(void){
    int arr[10];

    for(int i=0;i<10;i++){
        printf("입력: ");
        scanf("%d" ,&arr[i]);
    }
    printf("홀수 출력: ");
    for(int i=0;i<10;i++){
        if(i%2==0){
            printf("%d, ", arr[i]);
        }
    }
    printf("\n");
    printf("짝수 출력: ");
    for(int i=0;i<10;i++){
        if(i%2!=0){
            printf("%d, ", arr[i]);
        }
    }
    
}

처음에 함수로 안풀고 그냥 if, for써서 만들었다가 급하게 분리했다. 경고문은 뜨기는 하지만 그래도 실행은 정상적

 

도전2) 프로그램 사용자로부터 10진수 형태로 정수를 하나 입력 받은 다음, 이를 2진수로 변환해서 출력하는 프로그램을 작성해보자

#include <stdio.h>
int main(void){
    int N,i=0;
    char num[30];

    scanf("%d", &N);

    while(N>0){
        num[i++]=N%2;
        N/=2;
    }
    while(i>0){
       i--;
       printf("%d ", num[i]);
    }
   return 0;
}

일단 공간과 정수를 선언해주고 저장한다음에 진수 변환방식을 써주어야 한다. 나저미가 있으면 더해주고 숫자 역시 나누어 주는 것이 필요하다. 이것을 나만의 방식으로 i++을 내보내려 했는데 잘 안되긴 해서 저자의 말을 따르기로 했다. 안익숙한 것은 사실이다. 그리고 탈출한 다음에는 이를 거꾸로 출력해야 하므로 i를 올린 상태에서 다시 -를 통해 출력을 시켜중야 한다.

 

도전3) 길이가 10인 배열을 선언하고 총 10개의 정수를 입력 받는다. 단, 입력받은 숫자가 홀수이면 배열의 앞에서부터 채워나가고 짝수이면 뒤에서부터 채워나가는 형식을 취하기로 하자. 따라서 사용자가 [1,2,3,4,5,6,7,8,9,10]을 입력했다면 배열에는[1,3,5,7,9,10,8,6,4,2]순으로 저장되어야 한다.

#include <stdio.h>
int main(void){
    int num;
    int new[10];
    int f=0,e=9;
    for(int i=0; i<10;i++){
        printf("입력: ");
        scanf("%d", &num);
        if(num%2==1){
            new[f++]=num;
        }
        else if(num%2==0){
            new[e--]=num;
        }
    }
    printf("배열요소의 출력: ");
    for(int i=0;i<10;i++){
        printf("%d ", new[i]);
    }
    
}

이 것도 처음에 나만의 방식을 만들려고 했다. 처음에 앞에것은 i++로 올려주고 뒤에서부터 오는 것은 10-i-1를 활용하려고 했다. 다시 생각해보니 불가인 것이었다. 숫자가 겹칠 수 있기 때문이다. 그래서 사실 초기화를 시키면서 숫자를 지정해서 거기서부터 빼는게 확실히 맞는 말 같았다. 충돌없이 마무리가 가능하다. 출력과정은 for문 돌리는 것이므로 어렵지는 않다.

 

도전4) 회문은 앞으로 읽으나 뒤로 읽으나 차이가 없는 단어들을 뜻한다. 예를 들어서 level,bob과 같은 단어들은 회문에 속한다. 이에 우리는 인자로 전달되는 영단어가 회문인지 아닌지를 판단해서 그 결과를 출력한는 기능의 함수를 정의하고 이에 적절한 main함수를 정의해보고자 한다. 단 구현의 편의를 위해서 대문자까지 일치해야 회문으로 인정하기로 하겠다.

#include <stdio.h>
void Pal1(char* word){
    int len=0;
    int num=0;
    while(word[len]!=0){
        len++;
    }
    for(int i=0; i<len/2;i++){
        if(word[i]!=word[len-i-1]){
            num +=1;
        }
    }
    if(num ==0){
        printf("회문입니다.");
    }
    else{
        printf("회문이 아닙니다.");
    }
    
}
int main(void){
    char Pal[30];
    scanf("%s", &Pal);
    Pal1(Pal);
    return 0;
}

이것도 굉장히 고민을 많이 했다. 함수선언도 익숙치 않았고 guide 부분에서 strlen이 있다는 것을 알려줘서 그것을 쓰라하는 줄 알았는데 아니어서 당황했다. 그냥 여기서는 while문으로 len을 구해준다. 그리고 반으로 나누어서 앞과 뒤를 검사하고 만약 다를 경우에는 +1를 해주는 형태로 구현해보았다. 회문이라면 num가 올라가지 않을 것이므로 회문이라고 출력하도록 하였고 나머지 경우에는 회문이 아니라고 하였다. 이를 함수 안에서 구현하였다.

 

도전5) 배열에 저장되어 있는 요소들을 내림차순으로 정렬한는 함수를 정의하자.(함수의 이름은  DesSort로 정의하자) 그리고 이 함수를 호출하는 예제를 작성해보자. 프로그램의 흐름은 다음과 같이 구성을 하자. 일단 길이가 7인 int형 배열을 선언해서 프로그램 사용자로 부터 7개의 정수를 입력받도록 하자. 그리고 입력받은 정수를 내림차수능로 정렬하기 위해서 배열을 인자로 전달하면서 DesSort함수를 호출하자. 그리고 마지막으로 제대로 정렬이 되었는지 확인하기 위해서 배열의 요소들을 순서대로 출력해보자

#include <stdio.h>
void DesSort(int ary[], int len);

int main(void){
    int arr[7];
    int i;
    for(i=0;i<7;i++){
        printf("입력 %d:", i);
        scanf("%d", &arr[i]);
    }
    DesSort(arr,sizeof(arr)/sizeof(int));
    for(i=0;i<7;i++){
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}
void DesSort(int ary[], int len){
    int i,j;
    int temp;
    for(i=0;i<len-1;i++){
        for(j=0;j<(len-i)-1;j++){
            if(ary[j]<ary[j+1]){
                temp=ary[j];
                ary[j]=ary[j+1];
                ary[j+1]=temp;
            }
        }
    }
}

이것은 문제 앞에서 형태를 주어졌기 때문에 큰 어려움은 없었다. 함수 이름 변화와 배열의 크기 변화주기, 그리고 scanf를 통해 저장해주는 것, 그리고 바꿔주는 형태에서 부등호의 방향만 바꿔주었다. 배열의 전달방식을 알고있는게 필요할 것 같다. 그리고 for문 2개를 통해 차례대로 그리고 거꾸로 검사할 수 있다는 것을 확인해야 겠다. 바꿔주는 것은 temp로 하는 것은 익숙하니까.....

 

 

도전프로그래밍 2 끝!!!!!

728x90
728x90

도전1) 10진수 정수를 입력받아서 16진수로 출력하는 프로그램을 작성해보자. 이는 서식문자의 활용에 대한 문제이므로 쉽게 해결할 수 있을 것이다.

#include <stdio.h>
int main(void){
    int a;
    scanf("%d",&a);
    printf("%X", a);
}

서식문자를 알아야 한다. %x가 16진수의 표현법이라는 것을 알고 풀면 금방 나오는 문제이다.

 

도전2) 프로그램 사용자로부터 두개의 정수를 입력 받아서 구구단을 출력하는 프로그램을 작성해보자. 예를 들어서 프로그램 사용자가 3과 5를 입력하면 3단,4단, 5단을 출력되어야 하고, 2와 4를 입력하면 2단, 3단,4단이 출력되어야 한다. 

단 한가지 조건이 있다. 사용자는 두개의 숫자를 입력할 때에 입력 순서에 자유로워야 한다. 즉 3과 5를 입력하건 5와 3을 입력하건 프로그램은 같은 결과를 출력해야 한다.

#include <stdio.h>
int main(void){
    int a,b,temp;
    scanf("%d %d", &a, &b);
    if(a>b){
        temp=a;
        a=b;
        b=temp;
    }
    for(int i=a;i<=b;i++){
        for(int j=1;j<=9;j++){
            printf("%d * %d = %d \n",i, j, i*j );
        }
    }
    return 0;
}

구구단 문제이다.

일반적 구구단과 다른점은 순서 상관없이 보이는것은 작은것부터 출력을 해야한다는 점이다. 이를 위해 if 문을만들어서 temp 공간을 활용해 숫자를 바꿔주는 작업을 해 주었다. 이외에는 구구단 구하는 것과 같다.

 

 

도전3) 두개의 정수를 입력받아서 최대 공약수를 구하는 프로그램을 작성 해 보자

#include <stdio.h>
int main(void){
    int a,b,temp,max;
    scanf("%d %d", &a, &b);
    if(a>b){
        temp=a;
        a=b;
        b=temp;
    }
    for(int i=1;i<=a;i++){
        if(a%i==0&&b%i==0){
            max=i;
        }
    }
    printf("%d", max);
    return 0;
}

머릿속으로 그냥 푼거라 틀릴 수도 잇을 것 같다. 처음에 짜놓고 살짝의 수정을 거쳤다. 일단 입력을 받아서 for문을 돌린다. 단 공약수이기 때문에 작은 수를 판단해줘서 a 위치가 작은 수가 들어갈 수 있도록 해준다. 그리고 그만큼 반복을 시킨다. if문에서는 나누어 주는데 둘다 나머지가 0이 될 수 있는 부분이 있는데 그 부분마다 계속 max값을 설정해준다. 만약 최대인 경우에는 변하지 않을 것이므로 배열을 쓰지 않았다. 그리고 이것을 출력을 시킨다.

 

도전4) 필자가 좋아하는 것 중 하나가 금요일 저녁 퇴근길에 DVD나 만화채을 잔뜩 빌리고, 동네 슈퍼에 들려서 굿것질거리를 사가지고 집에 들어가는 것이다 오늘은 금요일이다. 현재 필자의 주머니에는 5천원이 있다. DVD 한편을 빌리면 3500원이 남는다. 슈퍼에 들려서 크림빵(500)원, 새우깡(700원), 콜라(400원)을 사려한다. 잔돈을 하나도 남기지 않고 이 세가지 물건을 하나 이상 구매하려면 어떻게 구매를 진행해야 하겠는가?

#include <stdio.h>
int main(void){
    int c=500;
    int s=700;
    int d=400;
    int i,j,k,money;
    printf("현재  당신이 소유하고 있는 금액: ");
    scanf("%d", &money);
    for(i=1;i<money/c;i++){
        for(j=1;j<money/s;j++){
            for(k=1;k<money/d;k++){
                if(money==c*i+s*j+d*k){
                    printf("크림빵 %d개 새우깡 %d개 콜라 %d개\n", i,j,k);
                }
            }
        }
    }
}

문제에 대해서 잘 이해를 못하기도 했고 이 원리가 왜 성립되는지 고민을 했었다. 일단 먼저 소유하는 것은 입력을 받는 것이 맞다. 그리고 각 경우에서 돈/각 물건의 가격을 나누어주었는데 반복 횟수를 세어주는 것이다. 이렇게 하면 횟수가 넘어 갈 수도 있는데 for문 3번째 if문에서 같을 경우에만 출력을 하게 하므로 큰 문제가 되지 않는다. for문만 똑같이 만들어주면 큰문제가 없는 문제였다.

 

도전5)10개의 소수를 출력하는 프로그램을 작성해보자. 참고로 정수num이 1과 num으로 밖에 나눠지지 않는다면 이는 소수에 해당한다. 따라서 3은 소수이다. 그러나 4는 소수가 아니다. 1,2,4로 나눠지기 때문이다.

#include <stdio.h>
int num[31];
int main(void){
    for(int i=1;i<=31;i++){
        for(int j=1;j<=i;j++){
            if( i % j == 0){
                num[i]++;
            }
        }
    }
        
    
    for(int i=1;i<=31;i++){
            if(num[i]==2){
                printf("%d ", i);
            }
    }  
}

 

도전6) 프로그램 사용자로부터 초를 입력받은 후에 이를 [시,분,초]의 형태로 출력하는 프로그램을 작성해보자

#include <stdio.h>
int main(void){
    int second;
    scanf("%d", &second);
    int h=second/3600;
    int m=(second-h*3600)/60;
    int s=(second-h*60)%60;
    printf("%d시 %d분 %d초", h,m,s);
}

이문제는 분, 초 원리를 알면 쉬워진다. 일단 초를 입력받고 h,m,s를 통해 시,분,초 변수를 만들어 준다. 

그리고 시 부분에서는 초에서 3600을 곱해야 하므로 이를 나누어준다. 분 부분에서는 이 부분을 second에서 빼준뒤 초와의 관계는 60이므로 이를 나누어준다. 마지막으로 초는 m부분 식에서 나머지를 구해주는 식으로 해주면 큰 문제가 생기지 않는다.

 

도전7) 프로그램 사용자로부터 숫자n을 입력받는다. 그리고 나서 다음 공식이 성립하는 k의 최댓값을 계산해서 출력하는 프로그램을 작성해보자

  k

2    <=n

#include <stdio.h>
int main(void){
    int n;
    int i=0;
    scanf("%d", &n);
    while(n/2){
        if(n/2==0){
            break;
        }
        else{
            n=n/2;
            i++;
        }
    }
    printf("%d", i);
}

약간 생각만 하면 쉽게 풀수 있는 문제였다. 횟수 제한은 숫자에 따라 달라지기 때문에 while을 이용해고 나눠준다. 끝까지 갔을경우에는 몫이 0이 될것이므로 이때 break가 되도록 하였고 그외인 경우에는 n의 값을 나누어주도록 하였다. 그리고 횟수를 1회 더해주도록 하였다. 그래서 break가 되면 얼마나 반복되었는지를 볼 수 있다. 

횟수 i를 print해주면 된다.

 

도전8) 2의 n승을 구하는 함수를 재귀적으로 구현해보자. 그리고 그에 따른 적절한 main함수도 구현해보자. 참고로 재귀함수의 구현이 처음에느 어려운 편이기 때문에 여기서는 쉬운 문제를 제시하였다.

#include <stdio.h>
int main(void){
    int i;
    int n;
    int total=1;
    scanf("%d",&n);
    for(i=0;i<n;i++){
        total*=2;
    }
    printf("2의 %d는 %d", i,total);
}

여기서 중요한 것은 total을 꼭 1로 설정해야 하는 것이다. 그리고 for문을 이용해 확인하면서 2를 곱해준다. 출력을 해줄때에는 i와 total을 2를 곱한 것이므로 이를 출력시켜주면 된다.

 

도전프로그래밍 도장깨기!

도전프로그래밍 1 끝!!

728x90

+ Recent posts