Computer >> 컴퓨터 >  >> 프로그래밍 >> C 프로그래밍

C/C++ 개발자라면 꼭 풀어볼 까다로운 프로그래밍 문제 10선

프로그래밍의 기본기를 제대로 시험해 볼 수 있는 까다로운 C/C++ 문제 10가지를 소개합니다. 이스케이프 시퀀스부터 재귀 함수, 비트 연산자 활용까지, 평소에는 쉽게 지나칠 수 있는 언어의 세부 동작 원리를 다루고 있으니 면접 준비나 코딩 실력 점검에 활용해 보세요.

1. C++에서 큰따옴표("") 출력하기

C++에서는 큰따옴표(")가 문자열의 시작과 끝을 나타내는 특수 문자로 사용됩니다. 따라서 화면에 따옴표 자체를 출력하려면 이스케이프 시퀀스인 \"를 사용해야 합니다.

예제 코드

#include<iostream>
using namespace std;
int main() {
    cout<<"\"Tutorials Point \"";
    return 0;
}

실행 결과

"Tutorials Point "

2. 반복문과 goto 없이 1부터 10까지 출력하기

프로그래밍에서 같은 코드 블록을 여러 번 실행하는 방법은 크게 세 가지입니다.

  • 반복문(for, while 등) 사용
  • goto문 사용
  • 재귀 함수 사용

반복문과 goto문을 사용할 수 없다면 남은 방법은 재귀 함수뿐입니다. 재귀 호출을 이용해 1부터 10까지의 숫자를 출력하는 방법을 살펴보겠습니다.

예제 코드

#include <stdio.h>
void printNumber(int count){
    printf("%d\n", count );
    count+=1;
    if(count<=10)
       printNumber(count);
}
int main(){
    printNumber(1);
    return 0;
}

실행 결과

1
2
3
4
5
6
7
8
9
10

3. 산술·비교 연산자 없이 두 수의 같음 판별하기

두 수가 같은지 확인할 때는 비트 XOR 연산자(^)를 활용할 수 있습니다. XOR 연산의 특성상 두 값이 완전히 같으면 결과는 0이 됩니다. 이 원리를 코드로 구현해 보겠습니다.

예제 코드

#include<iostream>
using namespace std;
int main(){
    int a = 132;
    int b = 132;
    if ( (a ^ b) )
        cout<<"a is not equal to b";
    else
        cout<<"a is equal to b";
        return 0;
}

실행 결과

a is equal to b

4. 세미콜론 없이 "Hello" 출력하기

C/C++에서는 세미콜론(;)을 사용하지 않고도 문자를 출력할 수 있습니다. 핵심은 printf 함수의 반환값을 활용하는 것입니다. printf는 출력된 문자 수를 반환하므로, 이 값을 조건문의 조건으로 사용하면 세미콜론 없이도 실행할 수 있습니다.

예제 코드

#include <stdio.h>
int main(){
    if(printf("Hello "))
    return 0;
}

실행 결과

Hello

5. 비교 연산자 없이 두 수의 최댓값·최솟값 구하기

비교 연산자 없이 두 수 중 큰 값과 작은 값을 찾으려면 abs 함수를 이용하면 됩니다. 두 수의 차이를 abs에 전달하면 절댓값(양수 차이)이 반환되는데, 이를 합에서 더하거나 빼면 최댓값과 최솟값을 각각 구할 수 있습니다.

예제 코드

#include<iostream>
using namespace std;
int main (){
    int x = 15, y = 20;
    cout<<"The numbers are x = "<<x<<"and y = "<<y<<endl;
    cout<<"The max of the numbers is "<<((x + y) + abs(x - y)) / 2<<endl;
    cout<<"The min of the numbers is "<<((x + y) - abs(x - y)) / 2<<endl;
    return 0;
}

실행 결과

The numbers are x = 15and y = 20
The max of the numbers is 20
The min of the numbers is 15

공식을 정리하면 다음과 같습니다.

  • 최댓값: (x + y + |x − y|) / 2
  • 최솟값: (x + y − |x − y|) / 2

6. 프로그램이 자기 자신의 소스 코드 출력하기

프로그램의 출력 결과로 그 프로그램 자체의 소스 코드를 보여주는 것은 상당히 까다로운 문제로, 언어에 대한 깊은 이해가 필요합니다. 이른바 '퀴인(Quine)'이라고 불리는 유형입니다.

여기서는 파일 처리(file handling) 개념을 활용합니다. 매크로 __FILE__을 사용하면 현재 컴파일 중인 파일의 경로를 얻을 수 있으므로, 이 파일을 읽기 모드로 열어 내용을 그대로 출력하면 됩니다.

예제 코드

#include <stdio.h>
int main(void){
    FILE *program;
    char ch;
    program = fopen(__FILE__, "r");
    do{
        ch=fgetc(program);
        printf("%c", ch);
    }
    while(ch!=EOF);
        fclose(program);
    return 0;
}

7. + 연산자 없이 두 수의 합 구하기

+ 연산자 대신 - 연산자를 활용하면 두 수의 합을 구할 수 있습니다. 뺄셈에서 피연산자의 부호를 반전시키면(-(-y)) 결국 덧셈과 같은 효과를 얻게 됩니다.

예제 코드

#include<iostream>
using namespace std;
int main(){
    int x = 5;
    int y = 5;
    int sum = x - (-y);
    cout<<"The numbers are x = "<<x<<" y = "<<y<<endl;
    cout<<"Their sum = "<<sum;
    return 0;
}

실행 결과

The numbers are x = 5 y = 5
Their sum = 10

8. 산술·관계 연산자 없이 짝수 판별하기

주어진 수가 짝수인지 확인할 때도 비트 연산자를 사용할 수 있습니다. 비트 AND 연산자(&)와 0x01을 함께 사용하면 숫자의 0번째 비트(LSB)를 검사할 수 있습니다. 0번째 비트가 1이면 홀수, 0이면 짝수입니다.

예제 코드

#include<iostream>
using namespace std;
int main(){
    int a = 154;
    if(a & 0x01) {
        cout<<a<<" is an odd number";
    } else{
        cout<<a<<" is an even number";
    }
    printf("\n");
    return 0;
}

실행 결과

154 is an even number

9. / 연산자 없이 4로 나누기

나눗셈 연산자(/) 없이 숫자를 4로 나누려면 오른쪽 시프트 연산자(>>)를 사용하면 됩니다. 오른쪽으로 1비트 이동하면 2로 나눈 것과 같고, 2비트 이동하면 4로 나눈 결과와 동일합니다.

예제 코드

#include<iostream>
using namespace std;
int main(){
    int n = 128;
    cout<<n<<"divided by 4 = ";
    n = n >> 2;
    cout<< n;
    return 0;
}

실행 결과

128 divided by 4 = 32

10. 한 자리 숫자가 될 때까지 자릿수 합을 재귀적으로 계산하기

숫자의 모든 자릿수를 더한 뒤, 그 결과가 한 자리 숫자가 아니면 다시 자릿수를 더하는 과정을 반복하여 최종적으로 한 자리 숫자를 구하는 문제입니다.

참고로 이 문제에는 수학적 지름길이 있습니다. 어떤 수를 9로 나눈 나머지를 반복해서 구하면 결국 '디지털 루트(digital root)'에 도달하게 되며, 나누어떨어질 경우 답은 9가 됩니다. 아래 코드는 이 성질을 활용한 것입니다.

예제 코드

#include <iostream>
using namespace std;
int main() {
    int a = 534;
    int sum;
    if(a)
        sum = a % 9 == 0 ? 9 : a % 9 ;
    else
        sum = 0;
    cout<<"The final sum is "<<sum;
    return 0;
}

실행 결과

The final sum is 3

534의 경우 5 + 3 + 4 = 12, 다시 1 + 2 = 3이 되므로 최종 결과는 3입니다. 위 코드에서 a % 9를 이용하면 반복 과정을 거치지 않고도 바로 답을 얻을 수 있습니다.

마무리

이번 글에서 소개한 10가지 문제는 단순히 정답을 맞히는 것보다 C/C++ 언어의 내부 동작 원리(이스케이프 시퀀스, 재귀 호출, 비트 연산, 함수 반환값 등)를 이해하는 데 초점이 맞춰져 있습니다. 각 문제의 코드를 직접 작성하고 실행해 보면서 변형 문제에도 스스로 도전해 보시길 추천합니다.