#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void perimeter(double, double, double, double *, double *);
double square(double, double, double, double);
void heights(double, double, double, double *, double *, double *, double);
void medians(double, double, double, double *, double *, double *);
void bisectors(double, double, double, double *, double *, double *, double);
int main()
{
char buffer[32];
double first_side = 0;
double second_side = 0;
double third_side = 0;
double per1;
double per2;
double height_to_firstside;
double height_to_secondside;
double height_to_thirdside;
double median_to_firstside;
double median_to_secondside;
double median_to_thirdside;
double bisector_to_firstside;
double bisector_to_secondside;
double bisector_to_thirdside;
for (int i = 0; i < 3; i++)
{
printf("Enter a number for side %d: ", i + 1);
fgets(buffer, sizeof(buffer), stdin); // Зчитуємо рядок
//Validation
if (strspn(buffer, "0123456789.") != strlen(buffer) - 1)
{
printf("Invalid input. Please enter other nums.\n");
return 0;
}
int dot_count = 0;
for (int j = 0; j < strlen(buffer); j++)
{
if (buffer[0] == '0' && buffer[1] != '.')
{
printf("Invalid input. Please enter other nums.\n");
return 0;
}
if (buffer[j] == '.')
{
dot_count++;
}
if (dot_count >= 2)
{
printf("Invalid input. Please enter other nums.\n");
return 0;
}
}
double input;
sscanf(buffer, "%lf", &input);
if (i == 0) // Зберігаємо значення в відповідній змінній
{
first_side = input;
}
else if (i == 1)
{
second_side = input;
}
else if (i == 2)
{
third_side = input;
}
/*int c;
while ((c = getchar()) != '\n' && c != EOF) {}
memset(buffer, 0, sizeof(buffer));*/
}
if ((first_side + second_side) < third_side || (second_side + third_side) < first_side || (first_side + third_side) < second_side)
{
printf("Unreal triangle, enter other nums\n");
return 0;
}
perimeter(first_side, second_side, third_side, &per1, &per2);
double area = square(first_side, second_side, third_side, per2);
heights(first_side, second_side, third_side, &height_to_firstside, &height_to_secondside, &height_to_thirdside, per2);
medians(first_side, second_side, third_side, &median_to_firstside, &median_to_secondside, &median_to_thirdside);
bisectors(first_side, second_side, third_side, &bisector_to_firstside, &bisector_to_secondside, &bisector_to_thirdside, per2);
//results
printf("Perimeter: %lf\n", per1);
printf("Semi-perimeter: %lf\n", per2);
printf("Square: %lf\n", area);
printf("Height for the first side: %lf\n", height_to_firstside);
printf("Height for the second side: %lf\n", height_to_secondside);
printf("Height for the third side: %lf\n", height_to_thirdside);
printf("Median for the first side: %lf\n", median_to_firstside);
printf("Median for the second side: %lf\n", median_to_secondside);
printf("Median for the third side: %lf\n", median_to_thirdside);
printf("Bisector for the first side: %lf\n", bisector_to_firstside);
printf("Bisector for the second side: %lf\n", bisector_to_secondside);
printf("Bisector for the third side: %lf\n", bisector_to_thirdside);
return 0;
}
void perimeter(double first, double second, double third, double *pPer1, double *pPer2)
{
*pPer1 = first + second + third;
*pPer2 = *pPer1 / 2;
}
double square(double first, double second, double third, double semi_perimeter)
{
double square_size;
square_size = sqrt(semi_perimeter * (semi_perimeter - first) * (semi_perimeter - second) * (semi_perimeter - third));
return square_size;
}
void heights(double first, double second, double third, double *pHeight_firstside, double *pHeight_secondside, double *pHeight_thirdside, double semi_perimeter)
{
*pHeight_firstside = 2 * (sqrt(semi_perimeter * (semi_perimeter - first) * (semi_perimeter - second) * (semi_perimeter - third))) / first;
*pHeight_secondside = 2 * (sqrt(semi_perimeter * (semi_perimeter - first) * (semi_perimeter - second) * (semi_perimeter - third))) / second;
*pHeight_thirdside = 2 * (sqrt(semi_perimeter * (semi_perimeter - first) * (semi_perimeter - second) * (semi_perimeter - third))) / third;
}
void medians(double first, double second, double third, double *pMedian_firstside, double *pMedian_secondside, double *pMedian_thirdside)
{
*pMedian_firstside = 0.5 * (sqrt((2 * second * second) + (2 * third * third) - (first * first)));
*pMedian_secondside = 0.5 * (sqrt((2 * first * first) + (2 * third * third) - (second * second)));
*pMedian_thirdside = 0.5 * (sqrt((2 * first * first) + (2 * second * second) - (third * third)));
}
void bisectors(double first, double second, double third, double *pBisector_firstside, double *pBisector_secondside, double *pBisector_thirdside, double semi_perimeter)
{
*pBisector_firstside = (2 / (second + third)) * (sqrt((second * third * semi_perimeter) * (semi_perimeter - first)));
*pBisector_secondside = (2 / (first + third)) * (sqrt((first * third * semi_perimeter) * (semi_perimeter - second)));
*pBisector_thirdside = (2 / (first + second)) * (sqrt((first * second * semi_perimeter) * (semi_perimeter - third)));
}
这是我的代码,正如你所看到的,我使用字符数组从用户那里获取值,然后验证它并最终将其转换为双精度,但这都是在循环中完成的,所以我遇到了我无法清除缓冲区的问题,但是当用户输入第一个值时,忽略接下来的两个值,然后第一个值也分配给第二个和第三个值。
我尝试使用
fflush(stdin)
,但它不起作用,我也尝试过这个:
int c;
while ((c = getchar()) != '\n' && c != EOF)
但它也不起作用,所以我什至不知道现在应该尝试什么。
您确实可以清除输入缓冲区。或者只是按照预期消耗数据。
fflush
未定义用于输入。它仅为输出而定义,并不意味着 discard
任何东西。示例:您可以让 stdout
的驱动程序等待 \n
打印 tty
上的行,但随后程序结束。无论如何,缓冲区中的字节都会被打印:OS
最后会刷新输出缓冲区。如果代码中需要立即真正打印数据,那么就有fflush
。
一些
C
编译器在输入流上接受 fflush
作为扩展,据我所知,仅供学生使用。
在控制台输入的
Windows
下,您可以调用
BOOL WINAPI FlushConsoleInputBuffer(
_In_ HANDLE hConsoleInput
);
如文档中所述。在 Linux 上,我认为您可以搜索
ioctl
调用或 termios
来执行相同的操作。
如果您消耗了所有数据,则输入缓冲区不是您的代码所关心的。
我将向您展示一个示例,重新排列您的代码。
围绕数据编写代码。只要有机会就使用封装。这不仅仅是一个OOP的花哨词。这是一个强大的东西。
从你的代码:
只有当您有输入三角形时,程序中计算的值才有意义。如果一方的措施发生变化,所有值都将失效。
所以...
考虑这件事:
typedef struct
{
double s1;
double s2;
double s3;
Measures msrs;
} Triangle;
这是您的数据。至于
msrs
,来自你的代码
typedef struct
{
double perimeter;
double semi_perimeter;
double area;
double height_to_firstside;
double height_to_secondside;
double height_to_thirdside;
double median_to_firstside;
double median_to_secondside;
double median_to_thirdside;
double bisector_to_firstside;
double bisector_to_secondside;
double bisector_to_thirdside;
} Measures;
使用 Triangle
的值
INSIDE可以轻松强制执行依赖关系。并且还可以在代码中处理任意数字或三角形...
Triangle
Triangle* so_create()
{
Triangle* tri = malloc(sizeof(Triangle));
if (tri == NULL) return NULL;
printf(
" Triangle:\n\tPlease enter values for the 3 "
"sides: ");
int res =
scanf("%lf %lf %lf", &tri->s1, &tri->s2, &tri->s3);
if (res != 3)
{
free(tri);
return NULL;
}
if (not so_is_triangle(tri))
{
free(tri);
return NULL;
}
tri->msrs = so_get_measures(tri);
return tri;
}
这是程序中
main
中的起始代码。但这里
scanf
即可读取 3 个测量值C
风格中,如果三角形的尺寸合适,则 so_is_triangle()
返回 1
so_get_measures()
计算所有三角形的参数考虑这些功能:
Triangle* so_create();
Triangle* so_destroy(Triangle*);
int so_is_triangle(Triangle*);
Measures so_get_measures(Triangle*);
int so_show_triangle(Triangle*, const char*);
含义明显。
main
进行简单测试int main(void)
{
Triangle* one = so_create();
if (one == NULL)
{
fprintf(
stderr,
" Invalid data entered. Please try again\n");
return -1;
};
so_show_triangle(one, "\n\n[First triangle]");
so_destroy(one);
return 0;
}
这样更容易阅读。
Triangle:
Please enter values for the 3 sides: 3 4 5
[First triangle] Sides: [ 3.0000, 4.0000, 5.0000]
Perimeter: 12.0000
Semi-perimeter: 6.0000
Square: 6.0000
Height for the first side: 4.0000
Height for the second side: 3.0000
Height for the third side: 2.4244
Median for the first side: 4.2720
Median for the second side: 3.6056
Median for the third side: 2.5000
Bisector for the first side: 4.2164
Bisector for the second side: 3.3541
Bisector for the third side: 2.4244
so_show_triangle
请注意,一个变量的 12 个 printf 比 12 个变量的单个 printf 慢数百倍。并且更难纠正或对齐...
比较:
// results
printf("Perimeter: %lf\n", per1);
printf("Semi-perimeter: %lf\n", per2);
printf("Square: %lf\n", area);
printf(
"Height for the first side: %lf\n",
height_to_firstside);
printf(
"Height for the second side: %lf\n",
height_to_secondside);
printf(
"Height for the third side: %lf\n",
height_to_thirdside);
printf(
"Median for the first side: %lf\n",
median_to_firstside);
printf(
"Median for the second side: %lf\n",
median_to_secondside);
printf(
"Median for the third side: %lf\n",
median_to_thirdside);
printf(
"Bisector for the first side: %lf\n",
bisector_to_firstside);
printf(
"Bisector for the second side: %lf\n",
bisector_to_secondside);
printf(
"Bisector for the third side: %lf\n",
bisector_to_thirdside);
与
printf(
"\
Sides: [%10.4f, %10.4f, %10.4f]\n\
\n\
Perimeter: %10.4f\n\
Semi-perimeter: %10.4f\n\
Square: %10.4f\n\
\n\
Height for the first side: %10.4f\n\
Height for the second side: %10.4f\n\
Height for the third side: %10.4f\n\
\n\
Median for the first side: %10.4f\n\
Median for the second side: %10.4f\n\
Median for the third side: %10.4f\n\
\n\
Bisector for the first side: %10.4f\n\
Bisector for the second side: %10.4f\n\
Bisector for the third side: %10.4f\n",
tri->s1, tri->s2, tri->s3,
tri->msrs.perimeter, tri->msrs.semi_perimeter,
tri->msrs.area, tri->msrs.height_to_firstside,
tri->msrs.height_to_secondside,
tri->msrs.bisector_to_thirdside,
tri->msrs.median_to_firstside,
tri->msrs.median_to_secondside,
tri->msrs.median_to_thirdside,
tri->msrs.bisector_to_firstside,
tri->msrs.bisector_to_secondside,
tri->msrs.bisector_to_thirdside);
在示例中使用。
C
代码#include <iso646.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
double perimeter;
double semi_perimeter;
double area;
double height_to_firstside;
double height_to_secondside;
double height_to_thirdside;
double median_to_firstside;
double median_to_secondside;
double median_to_thirdside;
double bisector_to_firstside;
double bisector_to_secondside;
double bisector_to_thirdside;
} Measures;
typedef struct
{
double s1;
double s2;
double s3;
Measures msrs;
} Triangle;
Triangle* so_create();
Triangle* so_destroy(Triangle*);
int so_is_triangle(Triangle*);
Measures so_get_measures(Triangle*);
int so_show_triangle(Triangle*, const char*);
int main(void)
{
Triangle* one = so_create();
if (one == NULL)
{
fprintf(
stderr,
" Invalid data entered. Please try again\n");
return -1;
};
so_show_triangle(one, "\n\n[First triangle]");
so_destroy(one);
return 0;
}
Triangle* so_create()
{
Triangle* tri = malloc(sizeof(Triangle));
if (tri == NULL) return NULL;
printf(
" Triangle:\n\tPlease enter values for the 3 "
"sides: ");
int res =
scanf("%lf %lf %lf", &tri->s1, &tri->s2, &tri->s3);
if (res != 3)
{
free(tri);
return NULL;
}
if (not so_is_triangle(tri))
{
free(tri);
return NULL;
}
tri->msrs = so_get_measures(tri);
return tri;
}
Triangle* so_destroy(Triangle* tri)
{
if (tri == NULL) return NULL;
free(tri);
return NULL;
}
int so_is_triangle(Triangle* tri)
{
if (tri == NULL) return 0;
if ((tri->s1 + tri->s2) < tri->s3 ||
(tri->s2 + tri->s3) < tri->s1 ||
(tri->s1 + tri->s3) < tri->s2)
return 0;
return 1; // ok it is a triangle
}
Measures so_get_measures(Triangle* tri)
{
Measures m = {0};
if (tri == NULL) return m;
// perimeter
m.perimeter = tri->s1 + tri->s2 + tri->s3;
m.semi_perimeter = m.perimeter / 2;
// area
m.area = sqrt(
m.semi_perimeter * (m.semi_perimeter - tri->s1) *
(m.semi_perimeter - tri->s2) *
(m.semi_perimeter - tri->s3));
// heights
m.height_to_firstside =
2 *
(sqrt(
m.semi_perimeter *
(m.semi_perimeter - tri->s1) *
(m.semi_perimeter - tri->s2) *
(m.semi_perimeter - tri->s3))) /
tri->s1;
m.height_to_secondside =
2 *
(sqrt(
m.semi_perimeter *
(m.semi_perimeter - tri->s1) *
(m.semi_perimeter - tri->s2) *
(m.semi_perimeter - tri->s3))) /
tri->s2;
m.height_to_thirdside =
2 *
(sqrt(
m.semi_perimeter *
(m.semi_perimeter - tri->s1) *
(m.semi_perimeter - tri->s2) *
(m.semi_perimeter - tri->s3))) /
tri->s3;
// medians
m.median_to_firstside =
0.5 *
(sqrt(
(2 * tri->s2 * tri->s2) +
(2 * tri->s3 * tri->s3) - (tri->s1 * tri->s1)));
m.median_to_secondside =
0.5 *
(sqrt(
(2 * tri->s1 * tri->s1) +
(2 * tri->s3 * tri->s3) - (tri->s2 * tri->s2)));
m.median_to_thirdside =
0.5 *
(sqrt(
(2 * tri->s1 * tri->s1) +
(2 * tri->s2 * tri->s2) - (tri->s3 * tri->s3)));
// bisectors
m.bisector_to_firstside =
(2 / (tri->s2 + tri->s3)) *
(sqrt(
(tri->s2 * tri->s3 * m.semi_perimeter) *
(m.semi_perimeter - tri->s1)));
m.bisector_to_secondside =
(2 / (tri->s1 + tri->s3)) *
(sqrt(
(tri->s1 * tri->s3 * m.semi_perimeter) *
(m.semi_perimeter - tri->s2)));
m.bisector_to_thirdside =
(2 / (tri->s1 + tri->s2)) *
(sqrt(
(tri->s1 * tri->s2 * m.semi_perimeter) *
(m.semi_perimeter - tri->s3)));
return m;
}
int so_show_triangle(Triangle* tri, const char* msg)
{
if (tri == NULL) return -1;
if (msg != NULL) printf("%s", msg);
//
printf(
"\
Sides: [%10.4f, %10.4f, %10.4f]\n\
\n\
Perimeter: %10.4f\n\
Semi-perimeter: %10.4f\n\
Square: %10.4f\n\
\n\
Height for the first side: %10.4f\n\
Height for the second side: %10.4f\n\
Height for the third side: %10.4f\n\
\n\
Median for the first side: %10.4f\n\
Median for the second side: %10.4f\n\
Median for the third side: %10.4f\n\
\n\
Bisector for the first side: %10.4f\n\
Bisector for the second side: %10.4f\n\
Bisector for the third side: %10.4f\n",
tri->s1, tri->s2, tri->s3,
tri->msrs.perimeter, tri->msrs.semi_perimeter,
tri->msrs.area, tri->msrs.height_to_firstside,
tri->msrs.height_to_secondside,
tri->msrs.bisector_to_thirdside,
tri->msrs.median_to_firstside,
tri->msrs.median_to_secondside,
tri->msrs.median_to_thirdside,
tri->msrs.bisector_to_firstside,
tri->msrs.bisector_to_secondside,
tri->msrs.bisector_to_thirdside);
return 0;
}
// https://stackoverflow.com/questions/77216624/impossibility-to-clear-the-buffer