Я получил следующий вопрос в рамках скринингового интервью:
Напишите функцию, которая получает три целых входа для длин сторон треугольника и возвращает одно из четырех значений для определения типа треугольника (1 = scalene, 2 = равнобедренные, 3 = равносторонние, 4 = ошибка). Генерируйте тестовые примеры для функции, предполагающей, что другой разработчик закодировал эту функцию.
Мой ответ:
#define ERROR 4
#define EQUILATERAL 3
#define ISOSCELES 2
#define SCALENE 1
int detemineTriangle(int x, int y, int z)
{
if((x<=0) || (y<=0) || (z<=0))
return ERROR;
if((x==y) || (x==z) || (y==z))
{
if((x==y) && (y==z))
return EQUILATERAL;
else
return ISOSCELES;
}
return SCALENE;
}
ИСПЫТАНИЯ:
detemineTriangle (0,0,0); //error
detemineTriangle (2,2,2); //equilateral
detemineTriangle (3,3,1); //isosceles
detemineTriangle (1,3,3); //isosceles
detemineTriangle (3,1,3); //isosceles
detemineTriangle (1,2,3); //scalene
detemineTriangle (-1,2,3); //error scalene
detemineTriangle (1,-2,3); //error scalene
detemineTriangle (1,2,-3); //error scalene
detemineTriangle (-2,-2,-2); //error equilateral
detemineTriangle (-2,5,-2); //error isosceles
detemineTriangle (-2,-2,5); //error isosceles
detemineTriangle (5,-2,-2); //error isosceles
//looking for overflows/underflows
detemineTriangle (INT_MAX,INT_MAX,INT_MAX);
detemineTriangle (INT_MAX,1,1);
detemineTriangle (1,INT_MAX,1);
detemineTriangle (1,1,INT_MAX);
detemineTriangle (-INT_MAX,-INT_MAX,-INT_MAX);
detemineTriangle (-INT_MAX,1,1);
detemineTriangle (1,-INT_MAX,1);
detemineTriangle (1,1,-INT_MAX);
//boundary tests
detemineTriangle(1,1,1)
detemineTriangle(0,0,0)
detemineTriangle(-1,-1,-1)
detemineTriangle (0,10,10);
detemineTriangle (1,10,10);
detemineTriangle (-1,10,10);
detemineTriangle (10,0,10);
detemineTriangle (10,1,10);
detemineTriangle (10,-1,10);
detemineTriangle (10,10,0);
detemineTriangle (10,10,1);
detemineTriangle (10,10,-1);
//checking thread safety
a =detemineTriangle (10,10,10);
b =detemineTriangle (10,10,10);
//a==b function does not appear to depend on global or static variables
Вы видите что-то не так с этим ответом? Заранее спасибо.
Вы также должны проверить длину стороны. Как вы знаете, сумма длины двух сторон ДОЛЖНА быть больше длины последней стороны. поэтому вы должны также проверить что-то вроде этого:
if(x+y<=z || x+z<=y || z+y<=x)
return ERROR;
UPD: вот полное решение (включая проверку переполнения):
inline bool isSidesOverflow(int a, int b)
{
return b > INT_MAX - a;
}
int detemineTriangle(int x, int y, int z)
{
if((x<=0) || (y<=0) || (z<=0)) return ERROR;
// If all sides are equal and greater than 0 - no need to check overflow and validness.
if(x == y && y == z) return EQUILATERAL;
//Check overflow now
if(isSidesOverflow(x,y) || isSidesOverflow(x,z) || isSidesOverflow(y,z)) return ERROR;
//Check if it valid triangle
if(x+y<=z || x+z<=y || z+y<=x) return ERROR;
if((x==y) || (x==z) || (y==z)) return ISOSCELES;
return SCALENE;
}
(не компилировать, не стесняйтесь сообщать об ошибках через комментарии)
x + y
...
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
// define the data type "triangletype" with {values}
enum triangleType { scalene, isosceles, equilateral, noTriangle };
// Prototype function which returns the position of triangleType{value}
// Example: Scalene = 0, isosceles = 1, etc. These are zero indexed.
triangleType triangleShape(double a, double b, double c);
// Prototype function which takes the integer value of the
// triangle type and outputs the name of triangle
string shapeAnswer(int value);
int main() {
double inputA;
double inputB;
double inputC;
cout << "To determine whether a triangle is either:" << endl;
cout << setw(50) << " - Scalene" << endl; // Unequal in length
cout << setw(52) << " - Isosceles" << endl; // Two sides equal length
cout << setw(54) << " - Equilateral" << endl; // All sides equal
cout << setw(57) << " - Not a triangle" << endl;
cout << "Enter side A: ";
cin >> inputA;
cout << "Enter side B: ";
cin >> inputB;
cout << "Enter side C: ";
cin >> inputC;
cout << "The triangle is " << shapeAnswer(triangleShape(inputA, inputB, inputC)) << endl;
}
triangleType triangleShape(double a, double b, double c) {
triangleType answer;
if ( c >= (a + b) || b >= (a + c) || a >= (b + c) ) {
answer = noTriangle;
}
else if (a == b && b == c) {
answer = equilateral;
}
// Test the 3 options for Isosceles equality
else if ( (a == b) && (a != c) || (b == c) && (b != a) || (a == c) && (a != b) ) {
answer = isosceles;
}
else {
answer = scalene;
}
return answer;
}
string shapeAnswer(int value) {
string answer;
switch (value) {
case 0:
answer = "Scalene";
break;
case 1:
answer = "Isosceles";
break;
case 2:
answer = "Equilateral";
break;
case 3:
answer = "Not a triangle";
break;
default:
break;
}
return answer;
}
Недавно я боролся с этой проблемой.
Вот как я это решил.
int detemineTriangle(int x, int y, int z)
{
if (x <= 0 || y <= 0 || z <= 0 )
return ERROR;
else
if (z >= (x + y) || y >= (x + z) || x >= (y + z) )
return ERROR;
else if (x == y && y == c)
return EQUILATERAL;
else if ( ( (x == y) && (x != z) ) || ( (y == z) && (y != x) ) )
return ISOSCELES;
else
return SCALENE;
}
Первый оператор if квалифицирует вход, чтобы убедиться, что значения больше единицы. Второй оператор if квалифицирует, является ли вход действительным треугольником (две стороны, вместе взятые, должны быть больше, чем третья сторона). Третий оператор if ищет x = y и y = z, откуда следует x = z. Четвертый оператор if ищет две стороны равны, а третья сторона - нет. Заключительный оператор else просто возвращает scalene, но вы можете проверить его, если хотите.
Я верну свой комментарий к ответу.
Вы также должны проверить, что длины трех сторон действительны. Общее правило: longest_size < shortest_side + median_side
.
Тест для этого может быть:
detemineTriangle(1, 1, 100);
Помимо этого, вы можете сделать тестирование в целом более прочным, выполнив то, что предложили другие, например, тестирование всех перестановок аргументов (@Ivaylo).
Я бы разделил тесты на несколько тестов для различных ошибок. Таким образом, вы теперь не только, что функция determineTriangle
неверна, но будет иметь некоторое преимущество в том, что с ней не так.
Я бы сказал, что использование сторонней библиотеки для тестирования (например, CXXTest или Google Test Framework) было бы преимуществом. Большинство таких фреймворков предоставляют различные функции assert, которые вы можете использовать для проверки.
Еще одно улучшение, которое я могу придумать, - проверить каждый триплет во всех его возможных перестановках - результат функции должен быть одним и тем же (поэтому, возможно, написать вспомогательную функцию testTiplet(int sidea, int sideb, itn sidec, int expectedType))
.
EDIT: мой ответ показывает только, как вы можете улучшить свою часть тестирования. Важный поток вашей реализации упоминается Сатом в его/ее ответе.
1
,1
и1000
. Общее правило должно быть таким:longest_size < shortest_side + median_side
.