#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