12주차 과제 - jaeyong-choi1234/progamming-team-1 GitHub Wiki

두 직선의 교점 찾기

코드

#include <stdio.h>

typedef struct
{
    double x[2];
    double y[2];
} TwoPoint;

void FixNegativeZero(double* value);
void InputLine(TwoPoint* line, char* text);
int ValidateNumberString(char* str);
void StringToDouble(char* str, double* number);
int SamePoint(TwoPoint* line);
double CalculateSlope(TwoPoint* line);
double CalculateIntersectionX(TwoPoint* line1, TwoPoint* line2, double slope1, double slope2);
double CalculateIntersectionY(TwoPoint* line, double slope, double intersectionX);

int main(void)
{
    TwoPoint line1, line2;
    double slope1 = 0, slope2 = 0;
    double intersectionX = 0, intersectionY = 0;

    printf("이 프로그램은 두 직선의 교점 좌표를 구하는 프로그램입니다.\n");
    printf("점의 좌표를 입력할 때에는 (2.12, -1.2)를 -> 2.12 -1.2 와 같이 입력해주세요.\n");
    printf("---------------------------------------------------------------------------------\n");

    while (1)
    {
        InputLine(&line1, "첫 번째 직선의 두 점을 입력해주세요: ");
        InputLine(&line2, "두 번째 직선의 두 점을 입력해주세요: ");

        int vertical1 = (line1.x[0] == line1.x[1]);
        int vertical2 = (line2.x[0] == line2.x[1]);

        if (!vertical1 && !vertical2)
        {
            slope1 = CalculateSlope(&line1);
            slope2 = CalculateSlope(&line2);

            if (slope1 == slope2)
                printf("두 직선이 평행하거나 일치합니다. 다시 입력해주세요.\n");
            else
            {
                intersectionX = CalculateIntersectionX(&line1, &line2, slope1, slope2);
                intersectionY = CalculateIntersectionY(&line1, slope1, intersectionX);
                break;
            }
        }
        else if (vertical1 && !vertical2)
        {
            intersectionX = line1.x[0];
            slope2 = CalculateSlope(&line2);
            intersectionY = CalculateIntersectionY(&line2, slope2, intersectionX);
            break;
        }
        else if (!vertical1 && vertical2)
        {
            intersectionX = line2.x[0];
            slope1 = CalculateSlope(&line1);
            intersectionY = CalculateIntersectionY(&line1, slope1, intersectionX);
            break;
        }
        else
            printf("두 직선이 평행하거나 일치합니다. 다시 입력해주세요.\n");
    }

    FixNegativeZero(&intersectionX);
    FixNegativeZero(&intersectionY);

    printf("교점의 좌표: (%g, %g)\n", intersectionX, intersectionY);
    return 0;
}
/**
* 함수명: FixNegativeZero
* 기능: -0을 0으로 바꾼다.
* 매개변수:
*   - value: 교점의 좌표(x or y)
*/
void FixNegativeZero(double* value)
{
    if (*value == 0)
        *value = 0;
}
/**
* 함수명: InputLine
* 기능: 좌표를 입력받는다.
* 매개변수:
*   - line: 두 점의 좌표(x[0], y[0], x[1], y[1])를 담을 구조체 포인터
*   - text: 입력받을 때 작성할 문장을 담은 char형 포인터
*/
void InputLine(TwoPoint* line, char* text)
{
    while (1)
    {
        char input[4][20] = { 0 };

        printf("%s", text);
        scanf_s("%s %s %s %s", input[0], 20, input[1], 20, input[2], 20, input[3], 20);

        int valid = 1;
        for (int i = 0; i < 4; i++)
        {
            if (!ValidateNumberString(input[i]))
            {
                valid = 0;
                break;
            }
        }

        if (!valid)
            printf("잘못된 입력입니다. 다시 입력해주세요.\n");
        else
        {
            StringToDouble(input[0], &line->x[0]);
            StringToDouble(input[1], &line->y[0]);
            StringToDouble(input[2], &line->x[1]);
            StringToDouble(input[3], &line->y[1]);

            if (SamePoint(line))
                printf("서로 다른 두 점을 입력해주세요.\n");
            else
                break;
        }
    }
}
/**
* 함수명: ValidateNumberString
* 기능: 문자열이 숫자 형식인지 검사한다.
* 매개변수:
*   - str: 문자열로 입력받은 좌표
* 빈환값:
*   - 문자열이 숫자 형식이면 1, 아니면 0반환 (int 형식)
*/
int ValidateNumberString(char* str)
{
    int dotCount = 0, i = 0;

    if (str[0] == '+' || str[0] == '-')
        i++;
    if (str[i] == '\0')
        return 0;
    if (str[i] == '.' || str[i] < '0' || str[i] > '9')
        return 0;

    for (; str[i] != '\0'; i++)
    {
        if (str[i] == '.')
        {
            if (++dotCount > 1)
                return 0;
        }
        else if (str[i] < '0' || str[i] > '9')
            return 0;
    }

    return 1;
}

/**
* 함수명: StringToDouble
* 기능: 문자열을 double형으로 변환하여 number에 저장한다.
* 매개변수:
*   - str: 문자열로 입력받은 좌표
*   - number: 직선의 두 점중 하나의 좌표(x or y) double형 포인터
*/
void StringToDouble(char* str, double* number)
{
    double integer = 0, fraction = 0;
    int sign = 1, i = 0;

    if (str[0] == '-')
    {
        sign = -1;
        i++;
    }
    else if (str[0] == '+')
        i++;

    while (str[i] && str[i] != '.')
        integer = integer * 10 + (str[i++] - '0');

    if (str[i] == '.')
    {
        i++;
        double div = 10;
        while (str[i])
        {
            fraction += (str[i++] - '0') / div;
            div *= 10;
        }
    }

    *number = sign * (integer + fraction);
}
/**
* 함수명: SamePoint
* 기능: 두 점의 좌표가 동일한지 확인한다.
* 매개변수:
*   - line: 두 점의 좌표(x[0], y[0], x[1], y[1])를 담은 구조체 포인터
* 반환값:
*   - 두 점이 같으면 1, 다르면 0반환 (int 형식)
*/
int SamePoint(TwoPoint* line)
{
    return (line->x[0] == line->x[1] && line->y[0] == line->y[1]);
}
/**
* 함수명: CalculateIntersectionY
* 기능: 직선의 기울기와 구하고자 하는 점의 x좌표를 이용하여 y좌표를 계산한다.
* 매개변수:
*   - line: 두 점의 좌표(x[0], y[0], x[1], y[1])를 담은 구조체 포인터
*   - slope: 직선의 기울기
*   - intersectionX: 구하고자 하는 점의 x좌표
* 반환값:
*   - 구하고자 하는 점의 y좌표 (double 형식)
*/
double CalculateIntersectionY(TwoPoint* line, double slope, double intersectionX)
{
    return slope * (intersectionX - line->x[0]) + line->y[0];
}
/**
* 함수명: CalculateIntersectionX
* 기능: 두 직선의 기울기와 점의 좌표를 이용하여 교점의 x좌표를 계산한다.
* 매개변수:
*   - line1: 첫 번째 직선을 이루는 두 점의 좌표(x[0], y[0], x[1], y[1])를 담은 구조체 포인터
*   - line2: 두 번째 직선을 이루는 두 점의 좌표(x[0], y[0], x[1], y[1])를 담은 구조체 포인터
*   - slope1: 첫 번째 직선의 기울기
*   - slope2: 두 번째 직선의 기울기
* 반환값:
*   - 두 직선이 만나는 지점의 x좌표 (double 형식)
* 주의사항:
*   - slope1과 slope2가 같은 경우(평행한 직선)는 0으로 나누는 오류가 발생하므로
*     호출하는 쪽에서 사전 확인이 필요하다.
*/
double CalculateIntersectionX(TwoPoint* line1, TwoPoint* line2, double slope1, double slope2)
{
    return ((slope1 * line1->x[0]) - (slope2 * line2->x[0]) - line1->y[0] + line2->y[0]) / (slope1 - slope2);
}
/**
* 함수명: CalculateSlope
* 기능: 두 점의 좌표를 이용하여 직선의 기울기를 계산한다.
* 매개변수:
*   - line: 두 점의 좌표(x[0], y[0], x[1], y[1])를 담은 구조체 포인터
* 반환값:
*   - 두 점을 잇는 직선의 기울기 (double 형식)
* 주의사항:
*   - x[0]과 x[1]가 같은 경우는 0으로 나누는 오류가 발생하므로
*     호출하는 쪽에서 사전 확인이 필요하다.
*/
double CalculateSlope(TwoPoint* line)
{
    return (line->y[1] - line->y[0]) / (line->x[1] - line->x[0]);
}

예제입력

0 2.5 5 -2.5
0 -2.5 5 2.5

에제출력

교점의 좌표: (2.5, 0)
⚠️ **GitHub.com Fallback** ⚠️