IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Triangle validity test in C

V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Neaktivní uživatel:1.11.2017 10:12

Ahoj vsem,

nebyl by tu nekdo tak hodny a pomohl mi s ukolem? V programovani jsem relativni zacatecnik a obavam se, ze tohle zadani je nad moje sily a chapani. Domnivam se, ze to ma byt sestrojene jako array[pocet_tro­juhelniku][3].

#include <stdio.h>
#include <limits.h>
#include <float.h>

int main(){
...
return 0;
}

1. Uzivatel ma byt vyzvan k zadani cisla (mnozstvi kontrolovanych trojuhelniku, >= 1, < UCHAR_MAX, musi to byt integer). To, myslim, mam v poradku.

int pocet_trojuhelniku;
int check = 0;
char letter_check;
float trojuhelnik[pocet_trojuhelniku][3];


do
{
  printf("Please enter the number of triangles to check: \n");
  scanf("%d", &pocet_trojuhelniku);
  scanf("%c", &letter_check);


  if(letter_check != '\n')
  {
    while(getchar() != '\n')
    {
    }
    check = 0;
  }


  if(pocet_trojuhelniku >= 1 && pocet_trojuhelniku < UCHAR_MAX)
  {
    check = 1;
  }
  if(pocet_trojuhelniku < 1 || pocet_trojuhelniku > UCHAR_MAX)
  {
    printf("[ERR] Invalid number of triangles.\n");
    check = 0;
  }
}
while(check == 0);

2. Uzivatel ma byt pocet_trojuhelniku-krat vyzvan k zadani velikosti stran ( > 0.0, < FLT_MAX, musi to byt float). A tady uz mam problemy s kontrolou, zda je vse zadano v poradku.

int counter;


for(counter = 0; counter < pocet_trojuhelniku; counter++)
{
  printf("Please enter the first number of the triplet: \n");
  scanf("%f", &trojuhelnik[counter][0]);


  printf("Please enter the second number of the triplet: \n");
  scanf("%f", &trojuhelnik[counter][1]);


  printf("Please enter the third number of the triplet: \n");
  scanf("%f", &trojuhelnik[counter][2]);
}

Kdyz jsem se snazila uplatnit vyse uvedene do, if, while, tak mi chodila hlaska "Segmenation fault".

A dal uz jsem uplne ztracena....

3. Razeni kazde trojice cisel (velikosti stran) od nejmensiho po nejvetsi. (bubble sort?)

4. Na zaklade a+b>c, a+c>b, b+c>a ma byt urceno, zda se jedna o trojuhelnik. Vystup ma vypadat takto: Triplet [number] (a=[a], b=[b], c=[c]) is a triangle. (prip. is NO triangle).

5. Pro kazdou trojici ma byt urceno, zda se jedna o rovnostranny trojuhelnik (a==b && b==c), rovnoramenny trojuhelnik (a==b || b==c || a==c), pripadne pravouhly trojuhelnik (a*a + b*b == c*c || b*b + c*c == a*a || a*a + c*c == b*b).

Body cislo 4 a 5 se mi podarilo vyresit pouze pro pripad propoctu jednohoh trojuhelniku, nevim, jak to nasadit na pole.

if((a + b) > c)
{
  if((a + c) > b)
  {
    if((b + c) > a)
    {
      printf("Triplet (a=%f, b=%f, c=%f) is a triangle.\n", a, b, c);
    }
  }
}


else
{
  printf("Triplet (a=%f, b=%f, c=%f) is no triangle.\n", a, b, c);
}


if(a==b && b==c)
{
  printf("It is an equilateral triangle.\n");
}


if(a==b || b==c || a==c)
{
  printf("It is an isosceles triangle.\n");
}


if(a*a + b*b == c*c || b*b + c*c == a*a || a*a + c*c == b*b)
{
  printf("It is a right triangle.\n");
}

6. Pokud by melo po jakemkoli inputu nasledovat EOF, ma byt program bez dalsiho ukoncen.

Ukazka, jak to ma vypadat:

Please enter the number of triangles to check: 0

[ERR] Invalid number of triangles.

Please enter the number of triangles to check: 4

Please enter the first number of the triplet: 1

Please enter the second number of the triplet: 2

Please enter the third number of the triplet: foo

[ERR] Invalid number for the triplet.

Please enter the third number of the triplet: 1

Please enter the first number of the triplet: 4.5

Please enter the second number of the triplet: 7.24

Please enter the third number of the triplet: 4.5

Please enter the first number of the triplet: 11.7

Please enter the second number of the triplet: 11.7

Please enter the third number of the triplet: 11.7

Please enter the first number of the triplet: 3

Please enter the second number of the triplet: 4

Please enter the third number of the triplet: 5

Triplet 1 (a=1.000000, b=1.000000, c=2.000000) is NO triangle.

Triplet 2 (a=4.500000, b=4.500000, c=7.240000) is a triangle.

It is an isosceles triangle.

Triplet 3 (a=11.700000, b=11.700000, c=11.700000) is a triangle.

It is an equilateral triangle.

It is an isosceles triangle.

Triplet 4 (a=3.000000, b=4.000000, c=5.000000) is a triangle.

It is a right triangle.

Budu vdecna za jakoukoli pomoc....

Odpovědět
1.11.2017 10:12
Neaktivní uživatelský účet
Avatar
Matúš Olejník:1.11.2017 12:33

Segmenation fault ti nastáva pretože sa snažíš zapisovať do pola pre ktoré nemáš alokovanú pamäť, preto ju treba alokovať dynamicky.

Pridaj knižnicu

#include <stdlib.h>

Namiesto

float trojuhelnik[pocet_trojuhelniku][3];

daj

float **trojuhelnik;

Následne pred for-om v ktorom ideš načítavať jednotlivé strany trojuholníka (ak "check" je 1) si alokuj potrebnú pamäť

trojuhelnik = (float**)malloc(pocet_trojuhelniku * sizeof(float*));
for (i = 0; i < pocet_trojuhelniku; i++) {
        trojuhelnik[i] = (float*)malloc(POCET_STRAN_TROJUHOLNIKA * sizeof(float));
}

Po tomto už môžeš klasicky pracovať s "trojuhelnik" ako s dvojrozmerným polom.

Nakoniec keď už nebudeš "trojuhelnik" používať alebo pred ukončením programu uvolni alokovanú pamäť presne opačným spôsobom ako pri alokovaní

for (i = 0; i < pocet_trojuhelniku; i++) {
        free(trojuhelnik[i]);
}
free(trojuhelnik);
Nahoru Odpovědět
1.11.2017 12:33
/* I am not sure why this works but it fixes the problem */
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Neaktivní uživatel
DarkCoder:1.11.2017 16:26
  1. I když to v tomto příkladu není až tak důležité, je dobré, pokud už znám výsledek testu vstupu na negativní validitu, nečekat z důvodu efektivity až na konec testování. Třeba tak že využiji příkaz continue. Navíc se tak mohu vyhnout chybě negativní validity, která nastala. I přesto, že vstup nebyl korektní, může v určitých případech přiřadit funkce scanf() hodnotu do proměnné. Chybí kooperace testu vstupu spolu vyprázdněním vstupního bufferu a testu na platný rozsah. Správně vyhodnocená neplatná validace vstupu je chybně považována za platnou, protože scanf() přiřadil hodnotu do proměnné a tato hodnota je v platném rozsahu.
int pocet_trojuhelniku;
char letter_check;

do {
        printf("Please enter the number of triangles to check: ");
        scanf("%d", &pocet_trojuhelniku);
        letter_check = getchar();

        if (letter_check != '\n'){
                printf("Invalid number of triangles.\n");
                while (getchar() != '\n');
                continue;
        }

        if ((pocet_trojuhelniku < 1) || (pocet_trojuhelniku > UCHAR_MAX)) {
                printf("Invalid number of triangles.\n");
        }
} while ((pocet_trojuhelniku < 1) || (pocet_trojuhelniku > UCHAR_MAX) || (letter_check != '\n'));

Ještě pár tipů:

  • pro načítání znaků používat getchar(), getche(), getch() nikoli scanf()
  • používat vazbu if-else namísto if-if
  • používat závorky u výrazů v podmínce
Editováno 1.11.2017 16:28
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
1.11.2017 16:26
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Neaktivní uživatel
DarkCoder:2.11.2017 21:46
  1. Spíše než-li vytvářet 2D pole je elegantnější řešit úlohu za pomoci ukazatele na dynamicky alokované jednorozměrné pole struktur, kde struktura je tvořena třemi prvky typu float.
// Ladeni
#define DEBUG 1

// Strukturova sablona
struct sTriangle {
        float a;
        float b;
        float c;
};

// Promenne
int i;
int pocet_trojuhelniku;
struct sTriangle *triangle = NULL;

// Alokace pameti pro pole struktur
triangle = (struct sTriangle *)malloc(pocet_trojuhelniku * sizeof(struct sTriangle));
if (!triangle) {
        printf("Chyba alokace pameti.\n");
        exit(1);
}

// kontrolni vypis mnozstvi alokovane pameti
#if(DEBUG)
        printf("Mnozstvi alokovane pameti: %d bytu\n\n", pocet_trojuhelniku * sizeof(struct sTriangle));
#endif

// Nacteni stran trojuhleniku
for (i = 0; i < pocet_trojuhelniku; i++) {
        printf("Zadej 1. stranu %d. trojuhelnika: ", i + 1);
        scanf("%f", &((triangle + i)->a));
        printf("Zadej 2. stranu %d. trojuhelnika: ", i + 1);
        scanf("%f", &((triangle + i)->b));
        printf("Zadej 3. stranu %d. trojuhelnika: ", i + 1);
        scanf("%f", &((triangle + i)->c));
        printf("\n");
}

// kontrolni vypis trojuhelniku
#if(DEBUG)
        for (i = 0; i < pocet_trojuhelniku; i++) {
                printf("%d. trojuhelnik: %f %f %f\n", i + 1, (triangle+i)->a, (triangle + i)->b, (triangle + i)->c);
        }
        printf("\n");
#endif

// uvolneni pameti
free(triangle);
triangle = NULL;

Kód neobsahuje ošetření vstupů

Nahoru Odpovědět
2.11.2017 21:46
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 4 zpráv z 4.