Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Pejtl6 18. 11. 2022, 15:53:12

Název: Načtení 2D pole v C
Přispěvatel: Pejtl6 18. 11. 2022, 15:53:12
Dobry den. Chtel bych ze souboru nacist ctvercovou matici o neznamem poctu radku/sloupcu a nasledne ji opet printnout. Nemuzu prijit na to proc to nenacita zadny cisla. Kod i input je v priloze. Predem dekuji za jakykoli feedback <3
Název: Re:Načtení 2D pole v C
Přispěvatel: alex6bbc 18. 11. 2022, 16:23:58
mate tam jen scanf, ten cte ze standartniho vstupu (prikazovy radek) ne ze souboru.

open, read, close nebo fopen, fread, fclose 
Název: Re:Načtení 2D pole v C
Přispěvatel: a6b 18. 11. 2022, 16:32:43
jinak nejake komentare:

lepsi by bylo kod vlozit jako text, mohli bychom ho tu predelat a hned by sis to zkopiroval.

chapu, ze se ucis s polem, ale mit natvrdo maximalni pocty radku a sloupcu nastavene na 100 neni moc pekne.

array by bylo lepsi alokovat dynamicky a pri potrebe zvetseni realokovat.

mas tam for smycky pro i a j a jeste menis hodnoty i a j uvnitr smycky.
Název: Re:Načtení 2D pole v C
Přispěvatel: Pejtl6 18. 11. 2022, 16:36:49
mate tam jen scanf, ten cte ze standartniho vstupu (prikazovy radek) ne ze souboru.

open, read, close nebo fopen, fread, fclose

Pardon, spatne jsem se vyjadril, cisla posilam ze souboru na stdin :)
Název: Re:Načtení 2D pole v C
Přispěvatel: Pejtl6 18. 11. 2022, 16:49:11
jinak nejake komentare:

lepsi by bylo kod vlozit jako text, mohli bychom ho tu predelat a hned by sis to zkopiroval.

chapu, ze se ucis s polem, ale mit natvrdo maximalni pocty radku a sloupcu nastavene na 100 neni moc pekne.

array by bylo lepsi alokovat dynamicky a pri potrebe zvetseni realokovat.

mas tam for smycky pro i a j a jeste menis hodnoty i a j uvnitr smycky.
1) kod posilam v .c souboru v priloze (pouceni pro priste, diky :) )
2+3) zatim jsem si chtel udelat program pro max. matici 100x100, az to bude fungovat tak bych se chtel presunout na dyn. alokaci pro jakoukoli velikost
4) tema for loopama jsem chtel vytvorit ze pro array[0][0] ([radek=i][sloupec=j]) se zapise 1, array[0][1] -> 2 ... "\n"
array[1][0] -> 4 atd..
Název: Re:Načtení 2D pole v C
Přispěvatel: z_sk 18. 11. 2022, 17:06:30
Logická chyba na riadku 19.
Hrubá logická chyba na riadku 24.

Prečo sa Tvoj kód snaží načítať maticu, keď nie je funkčné načítanie jedného problému? T. j. narážka na to, že aký je postup riešenia problémov, t. j. či postupne z hora nadol alebo zdola nahor.
Název: Re:Načtení 2D pole v C
Přispěvatel: snugar_i 18. 11. 2022, 17:21:20
Myslím, že pomocí scanf nejsi schopný poznat, kde je konec řádku, protože přeskakuje všechen whitespace.
Doporučoval bych ti si to ze začátku trochu ulehčit a dát na začátek ještě jeden řádek, kde bude napsaný rozměr matice. Až ti tohle bude fungovat, tak to potom můžeš zkusit vymyslet bez něj (ale předem upozorňuju, že to bude o dost složitější).
Název: Re:Načtení 2D pole v C
Přispěvatel: Pejtl6 18. 11. 2022, 17:28:32
Logická chyba na riadku 19.
Hrubá logická chyba na riadku 24.

Prečo sa Tvoj kód snaží načítať maticu, keď nie je funkčné načítanie jedného problému? T. j. narážka na to, že aký je postup riešenia problémov, t. j. či postupne z hora nadol alebo zdola nahor.
Chtel jsem si osetrit vstupy, ale ted uz chapu, ze to je asi posledni vec, kterou resit. Chapu chybu na 19.r, ale nemohl bys prosim trosku rozvinout to, v cem je chyba na 24.? Diky
Název: Re:Načtení 2D pole v C
Přispěvatel: z_sk 18. 11. 2022, 18:36:01
Moja oprava: Prečo sa Tvoj kód snaží načítať maticu, keď nie je funkčné načítanie jedného riadku?

Riadok 24., ak bolo cieľom zistiť koniec riadku, tak to nie je dobre. Dokonca, číselný vstup 32 by sa tomu rovnal.

Vstup do programu je vždy ako prúd bajtov/znakov. Funkcia scanf číta hodnoty (t.j. reťazec znakov 0 až 9, a ten konvertuje na typ int). Na načítanie riadkov služí fgets, getline a potom použiť sscanf.

Ak chceš scanf, tak tam ako oddeľovať v tomto prípade sa buď dá, že záporné číslo sa rovná zmena na nový riadok, alebo vopred sa vie počet hodnôt (počet urči pri spustení použivateľ).

Zoznám sa a používaj man stránky pre fukcie C, napr. pre  (https://man7.org/linux/man-pages/man3/scanf.3.html). Určite si pozri sekciu Return value a pripadne príklad.

!!!! Nova extremná hrubá chyba je v riadku 16 !!! Dokonca pretečenie pamäte.
Název: Re:Načtení 2D pole v C
Přispěvatel: snugar_i 18. 11. 2022, 19:16:54
Dokonca, číselný vstup 32 by sa tomu rovnal.
Drobnost: newline je ASCII 10. 32 je mezera.
Název: Re:Načtení 2D pole v C
Přispěvatel: mr.rubik 19. 11. 2022, 13:49:51
1. Začni tím, že se vůbec naučíš načítat hodnoty ze souboru/stdin (je to vlastně to samé, ale nebudu ti plést hlavu), tj. zadefinuj si na začátku souboru rozměry matice, ty načti a potom podle toho načítej řádky a sloupce. Až to budeš mít, vypiš si všechno zase zpátky na stdout, přesměruj do souboru a diff. Ten vstup bude vypadat cca takhle:
Kód: [Vybrat]
2 3
1 2 3
3 4 5
Až tohle budeš mít správně, jdi k bodu 2.

2. Smaž rozměry matice ze vstupu (tj. první řádek vstupu výše) a naprogramuj úplně zvlášť funkci, kterou určíš počet sloupců matice. Bude to něco ve smyslu že načteš první řádek vstupu (tj. vše až po první '\n') a z toho načteš počet platných integerů. Další postup bude, že vezmeš to, co máš z bodu 1. a budeš načítat o řádek méně (ten jsi už načetl, když jsi počítal sloupce). Navíc ještě nebudeš počítat řádky, ale budeš načítat "dokud není EOF", ptž dopředu nevíš, kolik těch řádků je. Měla by to být menší úprava kódu z bodu 1.

Až budeš mít i bod dva, udělej opět to samé co v bodu 1.: Vypiš výsledek do stdout a porovnej se vstupem (pak si můžeš udělat vstupů víc a napsat si na to bash script).

3. Až ti tohle všechno bude fungovat, můžeš vůbec začít přemýšlet o dynamické alokaci.

Na závěr se zamysli nad tím, jaké "mezní hodnoty" a nesprávné vstupy můžeš dostat. Můžeš dostat prázdný vstup, vstup větší než tvoje staticky alokované pole, matice může být tzv. "zubatá" (trochu těžší na ošetření), může obsahovat neplatné znaky atd. A zkus tyhle věci ošetřit (tj. aby například program zdechnul kontrolovaným způsobem se správnou zprávou na výstupu) nebo se aspoň zamyslet, jak to udělat.

Hinty
1. Zjisti si, jaký je rozdíl mezi scanf("%d", ...); a scanf(" %d", ...); - tj. bez mezery před formátovacím řetězcem a s mezerou ;)
2. Používej vývojové prostředí a debugger - názorně uvidíš, co se děje.
3. Automatizuj si testování.
Název: Re:Načtení 2D pole v C
Přispěvatel: Ink 20. 11. 2022, 07:53:26
Otázka zní, zda vůbec používat funkci scanf() a zda by nebylo lepší udělat si vlastní konečný automat a načítat si ta čísla po znacích. Je to dost triviální.
Název: Re:Načtení 2D pole v C
Přispěvatel: mr.rubik 20. 11. 2022, 16:44:08
Otázka zní, zda vůbec používat funkci scanf() a zda by nebylo lepší udělat si vlastní konečný automat a načítat si ta čísla po znacích. Je to dost triviální.

To by teda nebylo lepší :) Je to dost citlivá funkce, protože načítá vstup, udělat to správně a bez chyb není vůbec triviální. A to se bavíme jen o integerech, floaty jsou úplně jiná liga. A navíc je to úplně mimo mísu pro začátečníka...
Název: Re:Načtení 2D pole v C
Přispěvatel: Ink 20. 11. 2022, 17:10:58
Otázka zní, zda vůbec používat funkci scanf() a zda by nebylo lepší udělat si vlastní konečný automat a načítat si ta čísla po znacích. Je to dost triviální.

To by teda nebylo lepší :) Je to dost citlivá funkce, protože načítá vstup, udělat to správně a bez chyb není vůbec triviální. A to se bavíme jen o integerech, floaty jsou úplně jiná liga. A navíc je to úplně mimo mísu pro začátečníka...

Ano, bavíme se o integerech. Jaké hrozné problémy tam jsou? V čem je lepší používat obskurní funkce typu scanf()?.
Název: Re:Načtení 2D pole v C
Přispěvatel: mikrom 20. 11. 2022, 17:34:38
@Pejtl6:
Mozes pouzit takyto postup: Textovy subor s datami otvoris s fopen() a zavries s fclose()
Subor budes citat v cykle po riadkoch za pouzitia funkcie fgets(). Pritom cisla z kazdeho riadku rozparsujes funkciou strtok() a ulozis ich do 2D pola.
Ak si s tym nebudes vediet poradit postni svoj dotaz sem https://www.tek-tips.com/threadminder.cfm?pid=205 a ja tam postnem funkcny kod



   
Název: Re:Načtení 2D pole v C
Přispěvatel: mr.rubik 20. 11. 2022, 17:40:42
Otázka zní, zda vůbec používat funkci scanf() a zda by nebylo lepší udělat si vlastní konečný automat a načítat si ta čísla po znacích. Je to dost triviální.

To by teda nebylo lepší :) Je to dost citlivá funkce, protože načítá vstup, udělat to správně a bez chyb není vůbec triviální. A to se bavíme jen o integerech, floaty jsou úplně jiná liga. A navíc je to úplně mimo mísu pro začátečníka...

Ano, bavíme se o integerech. Jaké hrozné problémy tam jsou? V čem je lepší používat obskurní funkce typu scanf()?.

Tak napriklad

A vubec, vse vyse zminene je naprosto nepodstatne, protoze zvolit "napsat si to sam" i kdyz je k dispozici standardni funkce je vzdy spatna volba (pokud nepotrebujete vyzdimat kazdou mikrosekundu) - a to z mnoha duvodu: kazdy, kdo to vezme po vas, si tu funkci bude muset precist, protoze nevi, co dela, pokud najde chybu, vy budete kopat okolo, ze "jste to tak myslel" - namisto "aha, scanf, ok, ten znam...".

To, co jsem napsal plati pro produkcni kod, ale dost hrubym zpusobem to miji pointu tohoto vlakna. Tazatel je zacatecnik, chce nacist matici, dostal zadani udelat to v C a scanf je v tom jazyce standardni funkce...
Název: Re:Načtení 2D pole v C
Přispěvatel: Ink 20. 11. 2022, 19:34:08
A vubec, vse vyse zminene je naprosto nepodstatne, protoze zvolit "napsat si to sam" i kdyz je k dispozici standardni funkce je vzdy spatna volba (pokud nepotrebujete vyzdimat kazdou mikrosekundu) - a to z mnoha duvodu: kazdy, kdo to vezme po vas, si tu funkci bude muset precist, protoze nevi, co dela, pokud najde chybu, vy budete kopat okolo, ze "jste to tak myslel" - namisto "aha, scanf, ok, ten znam...".

Kdybych to měl řešit "po svém", pravděpodobně bych nepoužil C, kdybych musel použít C, je otázka, zda bych měl k dispozici jenom tyhle "standardní" funkce apod.

To, co jsem napsal plati pro produkcni kod, ale dost hrubym zpusobem to miji pointu tohoto vlakna. Tazatel je zacatecnik, chce nacist matici, dostal zadani udelat to v C a scanf je v tom jazyce standardni funkce...

OK, v pohodě. Zadání jsem neviděl - buďto tu není nebo jsem ho přehlédl. Přesto mi nepřijde to řešení s konečným automatem v takovémto případě špatné - vyřeší celkem jednoduše řádkování atd. Znaménko, whitespace apod. jsou úplně v pohodě, ošetřit "správně" invalidní znak je triviální, poskládání integeru z dekadického zápisu je triviální. Řešit hexa číslo je zvláštní, že se int nevejde do mezí typu je sice možné, ale co na tom vyřeší scanf()? Co když někdo napíše do vstupu stočíslicovou hodnotu?
Název: Re:Načtení 2D pole v C
Přispěvatel: mr.rubik 20. 11. 2022, 21:22:12
Tahle debata nema vyznam :) Ano, to, co pisete je jeden ze zpusobu, jak parsovat cela cisla ze stringu.

Nicmene:

1. Tazatel neumi nacist pole ze vstupu, kde berete jistotu, ze zvladne spravne naprogramovat stavovy automat?
2. I pokud se bavime o produkcnim kodu, znovu,  scanf je standardni funkce. Pointa "standardnich" funkcionalit nespociva primarne v tom, ze jsou krasne (i kdyz zrovna scanf je vcelku ok - clovek si holt musi precist dokumentaci), ale v tom, ze to pouziva ranec existujicich aplikaci, vsichni to znaji, vsichni vedi, ze to funguje spravne a nikdo nepotrebuje studovat kod.
3. Tohle je C-specific vlakno, neni to C++, neni to Ruby, neni to Java. A holt v C je scanf (amd friends) standard. Nema cenu zde psat, co si myslite o C, ja si o Jave, Ruby... taky myslim sve.

Predpokladam, ze kdyz stavite dum, take netezite holyma rukama jil a nepalite vlastni cihly.
Název: Re:Načtení 2D pole v C
Přispěvatel: alex6bbc 20. 11. 2022, 21:28:48
Predpokladam, ze kdyz stavite dum, take netezite holyma rukama jil a nepalite vlastni cihly.

kdyz chce nekdo proniknout do veci, tak si i ty cihly muze sam udelat a vyzkouset si to.
pak kdyz zjisti jak to funguje, nasledne muze prejit na cihly co uz jsou k dispozici.
Název: Re:Načtení 2D pole v C
Přispěvatel: pensioner 20. 11. 2022, 22:14:04
Používám tuto konstrukci, čte celý řádek a pak řádek parsuje daným separátorem.

char *separator = " \t";
FILE *file = fopen( "jmeno_souboru.txt", "rt" );

fscanf( file, "%[^\n]s", line ); fgetc( file );

int index = atoi( strtok( line, separator ) );
double koef = atof( strtok( NULL, separator ) );
Název: Re:Načtení 2D pole v C
Přispěvatel: kanoe22 20. 11. 2022, 23:11:15
Predpokladam, ze kdyz stavite dum, take netezite holyma rukama jil a nepalite vlastni cihly.

kdyz chce nekdo proniknout do veci, tak si i ty cihly muze sam udelat a vyzkouset si to.
pak kdyz zjisti jak to funguje, nasledne muze prejit na cihly co uz jsou k dispozici.

Lenze totalny zaciatocnik ktory ma problem nacitat 2d maticu nepotrebuje vediet ako funguje scanf interne, a uz toboz sa nepotrebuje pokusat napodobnit jeho functionalitu vlastnou implementaciou.

Ked si niekto robi vodicak, tiez ho instruktor nevezme do oceliarni aby videl ako sa odlieva ocel, z ktorych sa nasledne robia diely, a neprejdu si spolu celu vyrobnu linku v automobilke. Co ale urobi je to, ze ho uci ako pouzivat to co uz je k dispozicii (hotove auto). Ked clovek naberie dost skusenosti zo soferovanim moze sa zacat hrabat v motore. Nie je to dokonaly priklad, ale na pochopenie hadam staci.
Název: Re:Načtení 2D pole v C
Přispěvatel: BoneFlute 20. 11. 2022, 23:24:16
kdyz chce nekdo proniknout do veci, tak si i ty cihly muze sam udelat a vyzkouset si to.
pak kdyz zjisti jak to funguje, nasledne muze prejit na cihly co uz jsou k dispozici.

Na youtubu jsem viděl pár videí několika lidí, kteří to skutečně tak udělali. V reálném životě neznám nikoho. Tedy vulgo: ano, máte pravdu, ale ta vaše pravda je k ničemu.
Název: Re:Načtení 2D pole v C
Přispěvatel: Ink 21. 11. 2022, 06:58:40
Používám tuto konstrukci, čte celý řádek a pak řádek parsuje daným separátorem.

char *separator = " \t";
FILE *file = fopen( "jmeno_souboru.txt", "rt" );

fscanf( file, "%[^\n]s", line ); fgetc( file );

int index = atoi( strtok( line, separator ) );
double koef = atof( strtok( NULL, separator ) );

Tokenizace + zpracování po řádcích? To vypadá jako plán.
Název: Re:Načtení 2D pole v C
Přispěvatel: Ink 21. 11. 2022, 07:01:11
kdyz chce nekdo proniknout do veci, tak si i ty cihly muze sam udelat a vyzkouset si to.
pak kdyz zjisti jak to funguje, nasledne muze prejit na cihly co uz jsou k dispozici.

Na youtubu jsem viděl pár videí několika lidí, kteří to skutečně tak udělali. V reálném životě neznám nikoho. Tedy vulgo: ano, máte pravdu, ale ta vaše pravda je k ničemu.

A co jiného je výuka C, než základní pochopení, jak program funguje na mikroúrovni?
Název: Re:Načtení 2D pole v C
Přispěvatel: alex6bbc 21. 11. 2022, 09:01:35
jeste by slo pouzit mmap.
Název: Re:Načtení 2D pole v C
Přispěvatel: mikrom 21. 11. 2022, 16:45:28
Zatial je tu mnoho filozofickej diskusie, ale malo kodu, tak postnem ja - ako som uz vyssie spomenul, da sa to vyriesit so standardnymi C funkciami fgets() a strtok() napr. takto:

matrix.c
Kód: [Vybrat]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_ROWS 100
#define MAX_COLS 100
#define MAX_LINE_LENGTH 256

int main()
{
    FILE *fp;
    char matrix_line[MAX_LINE_LENGTH];
    char *matrix_element;
    int i, j, max_i, max_j;
    int num_element;
    int matrix[MAX_ROWS][MAX_COLS];

    fp = fopen("matrix.dat","r");

    printf("Reading data from the file into the matrix:\n");
    i = 0;
    while (fgets(matrix_line, MAX_LINE_LENGTH, fp) != NULL) {
        // split line into matrix elements
        matrix_element = strtok(matrix_line, ",;\t ");
        j = 0;
        while(matrix_element != NULL) {
            // populate matrix
            matrix[i][j] = atoi(matrix_element);
            j++;
            matrix_element = strtok(NULL, ",;\t ");
        }
        i++;
    }
    max_i = i;
    max_j = j;
    fclose(fp);
    printf("..DONE.\n\n");

    // now print the matrix
    printf("The matrix is:\n");
    for (i = 0; i < max_i; i++) {
        for (j = 0; j < max_j; j++) {
            printf("%d\t", matrix[i][j]);
        }
        printf("\n");
    }

    return 0;
}

Nacita zo suboru matica.dat takuto
Kód: [Vybrat]
1 2 3 4
5 6 7 8
alebo aj takuto maticu kde su prvky oddelene roznymi separatormi.
Kód: [Vybrat]
1; 2, 3 4
5 6; 7 8

Output:
Kód: [Vybrat]
$ gcc matrix.c -o matrix

$ matrix
Reading data from the file into the matrix:
..DONE.

The matrix is:
1       2       3       4
5       6       7       8
Název: Re:Načtení 2D pole v C
Přispěvatel: linuxak 21. 11. 2022, 17:56:04
Zatial je tu mnoho filozofickej diskusie, ale malo kodu, tak postnem ja - ako som uz vyssie spomenul, da sa to vyriesit so standardnymi C funkciami fgets() a strtok() napr. takto:

matrix.c
Kód: [Vybrat]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_ROWS 100
#define MAX_COLS 100
#define MAX_LINE_LENGTH 256

int main()
{
    FILE *fp;
    char matrix_line[MAX_LINE_LENGTH];
    char *matrix_element;
    int i, j, max_i, max_j;
    int num_element;
    int matrix[MAX_ROWS][MAX_COLS];

    fp = fopen("matrix.dat","r");

    printf("Reading data from the file into the matrix:\n");
    i = 0;
    while (fgets(matrix_line, MAX_LINE_LENGTH, fp) != NULL) {
        // split line into matrix elements
        matrix_element = strtok(matrix_line, ",;\t ");
        j = 0;
        while(matrix_element != NULL) {
            // populate matrix
            matrix[i][j] = atoi(matrix_element);
            j++;
            matrix_element = strtok(NULL, ",;\t ");
        }
        i++;
    }
    max_i = i;
    max_j = j;
    fclose(fp);
    printf("..DONE.\n\n");

    // now print the matrix
    printf("The matrix is:\n");
    for (i = 0; i < max_i; i++) {
        for (j = 0; j < max_j; j++) {
            printf("%d\t", matrix[i][j]);
        }
        printf("\n");
    }

    return 0;
}

No... stačí tam poslat více jak MAX_ROWS řádků a máme ukázkový buffer overflow na stacku s (remote) code execution.  CVSS score 10/10 ;).
Název: Re:Načtení 2D pole v C
Přispěvatel: mikrom 21. 11. 2022, 19:00:19
No... stačí tam poslat více jak MAX_ROWS řádků a máme ukázkový buffer overflow na stacku s (remote) code execution.  CVSS score 10/10 ;).
To neni produkcny kod ale iba ukazka JAK NA TO.
Vyhnut sa problemu o ktorom hovoris sa da roznymi sposobmi - napriklad:
- Osetrit podmienkou aby sa do matice nacitalo len tolko riadkov kolko riadkov ma subor.
- Najprv nacitat subor 1. krat, pritom zistit pocet riadkov (pripadne aj stlpcov), nasledne alokovat maticu danej velkosti, potom urobit rewind a nacitat subor 2. krat  do matice.
Název: Re:Načtení 2D pole v C
Přispěvatel: linuxak 21. 11. 2022, 19:12:00
To neni produkcny kod ale iba ukazka JAK NA TO.

To je spíš ukázka, JAK TO NEDĚLAT. Problémů je tam víc.

Nestačí ošetřit počet řádků, další buffer overflow nastane, když bude v řádku víc jak MAX_COLS (100) prvků. To jde snadno docílit, protože MAX_LINE_LENGTH je 256, jde tam nacpat až 128 prvků. Výsledek je úplně stejný, přepis stacku s (remote) code execution.

Pak je tam uninitialized memory access v případě, když budou mít řádky různý počet sloupců, matrix není inicializované. Neinicializovaná data se potom vypisují a může tam být cokoliv, třeba šifrovací klíče, které program používá.

Tohle bych začátečníkovi fakt neukazoval.
Název: Re:Načtení 2D pole v C
Přispěvatel: mikrom 21. 11. 2022, 19:30:42
To neni produkcny kod ale iba ukazka JAK NA TO.

To je spíš ukázka, JAK TO NEDĚLAT.
...
Toto su malicherne nedostatky, ktore sa daju lahko osetrit. Rozne ucebnice a navody su plne takychto prikladov. Cielom je aby bol priklad kratky a lahko zrozumitelny a to aj je.
Keby si mal nejaku sebareflexiu, tak by si namiesto kritiky radsej postol vlastny funkcny kod, co sa ale nestalo.
Název: Re:Načtení 2D pole v C
Přispěvatel: linuxak 21. 11. 2022, 20:07:32
Toto su malicherne nedostatky, ktore sa daju lahko osetrit.
Asi máme jiný názor na to, co jsou malicherné nedostatky. Já vidím tři kritické bezpečnostní chyby.

Keby si mal nejaku sebareflexiu, tak by si namiesto kritiky radsej postol vlastny funkcny kod, co sa ale nestalo.
Kdybys měl nějakou sebereflexi, poděkoval bys za kostruktivní code review.
Název: Re:Načtení 2D pole v C
Přispěvatel: alex6bbc 21. 11. 2022, 20:48:56
tu to je jak v zidovske skole.

je to zacatecnik, takze ukazat jak funguje pole na stacku je v poradku.
a ze to je v realu chyba nevadi, protoze se zaroven muze ukazat co se stane kdyz se prejede nektery index.
jakmile se nauci pointery, pak se muze naucit jak alokovat pole na heapu.
a taky se to muze nejprve naucit pro 100x100 a pozdeji treba pomoci realloc kdyz bude matice rust.
takze povidani o bezpecnostnich chybach je pro takoveho zacatecnika predcasna optimalizace.
Název: Re:Načtení 2D pole v C
Přispěvatel: linuxak 21. 11. 2022, 21:06:45
a ze to je v realu chyba nevadi, protoze se zaroven muze ukazat co se stane kdyz se prejede nektery index.
V reálu je to undefined behavior, takže se může stát cokoliv. Začátečník na to bude koukat a nebude chápat, co se děje. Proto není C vhodný jazyk pro začátečníka. Když už s tím ale někdo začíná, je mu od začátku potřeba vysvětlovat, co je to undefined behavior, protože když to nebude vědět, nebude rozumnět tomu, proč to nefunguje (a může to dělat cokoliv).
jakmile se nauci pointery, pak se muze naucit jak alokovat pole na heapu.
Jde to napsat bezpečně i se staticky alokovaným polem. S tím je vhodné začít.
Název: Re:Načtení 2D pole v C
Přispěvatel: Ink 21. 11. 2022, 21:08:04
Toto su malicherne nedostatky, ktore sa daju lahko osetrit.
Asi máme jiný názor na to, co jsou malicherné nedostatky. Já vidím tři kritické bezpečnostní chyby.

Keby si mal nejaku sebareflexiu, tak by si namiesto kritiky radsej postol vlastny funkcny kod, co sa ale nestalo.
Kdybys měl nějakou sebereflexi, poděkoval bys za kostruktivní code review.

Je to super, jak z toho školního příkladu chcete udělat skoro produkční kód. Docela by mě zajímalo, co na to původní tazatel. Začal dost bezradně a tohle je jiný level. Mimochodem, co jsou ty tři chyby? Já tam vidím přetečení řádku nebo sloupce a pokud dobře rozumím, co se děje s inicializací toho pole, tak pokud není deklarováno jako static (nebo není vynulováno něčím jako int matrix[MAX_ROWS][MAX_COLS] = {0};), je v případě, že tam ta čísla v některých řádcích chybí (řídká matice?), v některých pozicích nedefinovaná hodnota. Jinak ale přidat dynamickou alokaci podle potřeby, umět načíst dlouhé řádky a je to?
Název: Re:Načtení 2D pole v C
Přispěvatel: linuxak 21. 11. 2022, 21:22:33
Je to super, jak z toho školního příkladu chcete udělat skoro produkční kód.
Je v pořádku, že je ve školním projektu undefined behavior na třech místech? S tím, že jsou to kritické bezpečnostní chyby?

Mimochodem, co jsou ty tři chyby?
Název: Re:Načtení 2D pole v C
Přispěvatel: Ink 21. 11. 2022, 22:22:58
Je to super, jak z toho školního příkladu chcete udělat skoro produkční kód.
Je v pořádku, že je ve školním projektu undefined behavior na třech místech? S tím, že jsou to kritické bezpečnostní chyby?

Souhlasím s tím, co jsi psal výše, tedy že C je jazyk nevhodný pro začátečníky (plný pastí, dodávám).

Mimochodem, co jsou ty tři chyby?
  • Buffer overflow na počet řádků.
  • Buffer overflow na počet sloupců.
  • Neinicializovaná matrix. Prakticky celou neinicializovanou matrix je možné vypsat, to je hodně dat. Tím to ale nekončí. V kombinaci s buffer overflow je možné vypsat úplně všechno, co je na zásobníku. Celý zásobník procesu, ke kterému se útočník snadno dostane. To může být fakt hodně potenciálně citlivých dat. Jako chápu, že to většina lidí neřeší, ale kritická bezpečnostní chyba to prostě je.

Jasně, dík.
Název: Re:Načtení 2D pole v C
Přispěvatel: alex6bbc 21. 11. 2022, 23:01:17
Je to super, jak z toho školního příkladu chcete udělat skoro produkční kód.
Je v pořádku, že je ve školním projektu undefined behavior na třech místech? S tím, že jsou to kritické bezpečnostní chyby?

Souhlasím s tím, co jsi psal výše, tedy že C je jazyk nevhodný pro začátečníky (plný pastí, dodávám).

Mimochodem, co jsou ty tři chyby?
  • Buffer overflow na počet řádků.
  • Buffer overflow na počet sloupců.
  • Neinicializovaná matrix. Prakticky celou neinicializovanou matrix je možné vypsat, to je hodně dat. Tím to ale nekončí. V kombinaci s buffer overflow je možné vypsat úplně všechno, co je na zásobníku. Celý zásobník procesu, ke kterému se útočník snadno dostane. To může být fakt hodně potenciálně citlivých dat. Jako chápu, že to většina lidí neřeší, ale kritická bezpečnostní chyba to prostě je.

Jasně, dík.

na to stejne prijde postupem casu jak bude sam experimentovat.
Název: Re:Načtení 2D pole v C
Přispěvatel: mikrom 22. 11. 2022, 00:05:05
...
na to stejne prijde postupem casu jak bude sam experimentovat.
presne tak, ak bude s tym experimentovat i tie "kritické bezpečnostní chyby" si najde a odstrani sam   
Název: Re:Načtení 2D pole v C
Přispěvatel: mikrom 22. 11. 2022, 00:14:02
Otázka zní, zda vůbec používat funkci scanf() a zda by nebylo lepší udělat si vlastní konečný automat a načítat si ta čísla po znacích. Je to dost triviální.

...
Přesto mi nepřijde to řešení s konečným automatem v takovémto případě špatné - vyřeší celkem jednoduše řádkování atd. Znaménko, whitespace apod. jsou úplně v pohodě, ošetřit "správně" invalidní znak je triviální, poskládání integeru z dekadického zápisu je triviální. Řešit hexa číslo je zvláštní, že se int nevejde do mezí typu je sice možné, ale co na tom vyřeší scanf()? Co když někdo napíše do vstupu stočíslicovou hodnotu?

Ked to je pre teba take trivialne tak sem ukaz funkcny kod s tym konecnym automatom  8)
Název: Re:Načtení 2D pole v C
Přispěvatel: linuxak 22. 11. 2022, 07:56:46
presne tak, ak bude s tym experimentovat i tie "kritické bezpečnostní chyby" si najde a odstrani sam
To co jsi vyrobil, je klasický buffer overflow s přepsáním zásobníku a návratové adresy na něm, což je ta úplně nejkritičtější a velmi snadno zneužitelná chyba. Začátečník si nic sám neodstaní a učit ho tohle opravdu není dobrý nápad. Fakt bych nepsal "kritické bezpečnostní chyby" v uvozovkách, tím jenom dokazuješ, že bezpečnosti moc nerozumíš. Doporučil bych ti používat paměťove bezpečný jazyk a držet se od C dál. To bych ostatně doporučil úplně všem, protože praxe ukázala, že psát bezpečný software v C neumí nikdo. Takový člověk prostě neexistuje, nedá se to uhlídat.
Název: Re:Načtení 2D pole v C
Přispěvatel: Karmelos 22. 11. 2022, 09:29:09

Mimochodem, co jsou ty tři chyby?
  • Buffer overflow na počet řádků.
  • Buffer overflow na počet sloupců.
  • Neinicializovaná matrix. Prakticky celou neinicializovanou matrix je možné vypsat, to je hodně dat. Tím to ale nekončí. V kombinaci s buffer overflow je možné vypsat úplně všechno, co je na zásobníku. Celý zásobník procesu, ke kterému se útočník snadno dostane. To může být fakt hodně potenciálně citlivých dat. Jako chápu, že to většina lidí neřeší, ale kritická bezpečnostní chyba to prostě je.

hele a když už vidíš ty chyby, tak bude jiste triviální pro tebe je opravit - postnul bys prosím správný příklad jak to ošetřit? Poukázáním - máš tam chybu - se někdo, kdo o tom nemá ani páru, nic nenaučí... Já třeba v C vůbec nedělám, tak trošku znám základy, ale mikromův příklad mi přišel OK....
Název: Re:Načtení 2D pole v C
Přispěvatel: premekv 22. 11. 2022, 09:55:01
tu to je jak v zidovske skole.

je to zacatecnik, takze ukazat jak funguje pole na stacku je v poradku.
...
takze povidani o bezpecnostnich chybach je pro takoveho zacatecnika predcasna optimalizace.

Dovolím si mírně nesouhlasit. Jsem javista, v Cčku nedělám (evidentně štěstí pro mne i pro Cčko), ale jak jsem pochopil, tak C je to jazyk efektivní a rychlý, ale psát v něm je jako manipulovat s granátem, s prstem permanentně na pojistce. Souhlasil bych s těmi, co říkají, že např. správné ošetření vstupů tady není jen nadstavba, ale základ vzhledem k povaze "zbraně" se kterou si tady někdo chce začít dobrovolně hrát.

Tak jako tak to je zajímavá a poučná diskuze (nejen pro začátečníka). Přiznávám na rovinu, mne v hlavě hned svítily kontrolky, že přetečení indexů není v cyklech ošetřeno, ale to o té "zubaté" matici a neinicializované paměti mne napadlo až po přečtení komentáře... Mina, na kterou bych třeba sám šlápnul.
Název: Re:Načtení 2D pole v C
Přispěvatel: sad2 22. 11. 2022, 12:47:22
Čau, zde jsem napsal blog o pointerech a na konci je i příklad na dynamickou alokaci matice:

https://www.abclinuxu.cz/blog/apra/2021/2/ukazatele-jazyk-c

Myslím, že by ti to mohlo hodně pomoct.

Pokud bys měl zájem o konzultace, můj email je rubyac@seznam.cz

Název: Re:Načtení 2D pole v C
Přispěvatel: honzako 22. 11. 2022, 13:08:48
Diskuse se zajímavě rozjela.
Nicméně všichni mají pravdu!
Avšak je důležité co na to říká ten "student", protože on by to měl psát dle jemu známých a získatelných informacích z přednášek, a ty matice jsou někde ke konci semestru. Tzn. on nemusí ani tušit o nějakých standardních postupech.

Myslel jsem, že na těchto VŠ cvičeních jde spíše o správný postup a jeho objevení, než o ošetření všech možných stavů.

Proto se obávám, že tazatel možná ani nechápe proč se tu diskutuje o pointerech, alokacích atd.
Název: Re:Načtení 2D pole v C
Přispěvatel: mikrom 22. 11. 2022, 17:26:46
Tu je fix predosleho programu:

ocakam dalsie code review  ;)

matrix.c
Kód: [Vybrat]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_ROWS 100
#define MAX_COLS 100
#define MAX_LINE_LENGTH 256

int main()
{
    FILE *fp;
    char data_line[MAX_LINE_LENGTH];
    char *matrix_element;
    int i, j, max_i, max_j;
    int matrix[MAX_ROWS][MAX_COLS] = { 0 };

    fp = fopen("matrix.dat","r");

    printf("Reading data from the file:\n\n");
    max_j = 0;
    i = 0;
    while (fgets(data_line, MAX_LINE_LENGTH, fp) != NULL) {
        // Remove trailing \n
        data_line[strcspn(data_line, "\n")] = 0;

        // split line into matrix elements
        matrix_element = strtok(data_line, ",;\t ");
        j = 0;
        while(matrix_element != NULL) {
            printf("%s ", matrix_element);
            // populate matrix
            if ((i < MAX_ROWS) && (j < MAX_COLS)) {
               matrix[i][j] = atoi(matrix_element);
            }
            j++;
            if (max_j < j) max_j = j;

            matrix_element = strtok(NULL, ",;\t ");
        }
        printf("\n");
        i++;
    }
    max_i = i;
    fclose(fp);
    printf("..Done.\n\n");
    printf("Datafile contains %d rows and %d columns\n\n", max_i, max_j);

    // eventually, adapt maximum indexes to the size of the matrix
    if (max_i > MAX_ROWS) {
        printf("WARNING: matrix contains only %d rows of %d data rows from the file\n",
               MAX_ROWS, max_i);
        max_i = MAX_ROWS;
    }
    if (max_j > MAX_COLS) {
        printf("WARNING: matrix contains only %d columns of %d data columns from the file\n",
               MAX_COLS, max_j);
        max_j = MAX_COLS;
    }

    // now print the matrix
    printf("\nThe matrix is:\n\n");
    for (i = 0; i < max_i; i++) {
        for (j = 0; j < max_j; j++) {
            printf("%d\t", matrix[i][j]);
        }
        printf("\n");
    }

    return 0;
}

Malo by to spracovat aj zubatu maticu, ze chybajuce prvky budu nuly
Kód: [Vybrat]
1  2
5  6  7  8
Název: Re:Načtení 2D pole v C
Přispěvatel: D.A. Tiger 22. 11. 2022, 21:23:31
Ahoj, pár postřehů z rychlíku

1) Když deklaruješ proměnnou, tak ji co nejdříve také inicializuj a nečekej na chvíli, kdy ji budeš chtít použít. Velmi lehce se na to zapomíná a následky mohou být neblahé. Obzvláště to platí pro pointery!
2) Pokud nejsi schopný zaručit, že ti funkce neselže, pak vždy kontroluj alespoň její návratovou hodnotu, pokud něco vrací. V tomto případě se to týká funkce fopen( ), protože v případě, že se něco provede se souborem, který má otevřít (bude smazán, přejmenován, atd...) koleduješ si - v lepším případě - o segfault o pár řádku níže.

já chápu, že toto je studijní kód začátečníka. Přesto z vlastní zkušenosti považuji za důležité na to upozornit. Důsledky podobných opomenutí se v rozsáhlejším a komplexnějším kódu velmi špatně hledají. A nestačí o tom jen vědět, je potřeba si to vštípit do krve hned od začátku. Věř mi, že ti to hodně časem ulehčí život.

3) Proměnná i je zbytečná. Jenom ji inkrementuješ a a pak přiřadíš do max_i. Popřemýšlej, zda není lepší pracovat rovnou s max_i a i zrušit.
4) Navrhuji ti, abys přesunul podmínku max_j < j až za vnitřní cyklus. To proto, že V současné chvíli testuješ max_j proti všem pozicím elementů v řádku a to v každém cyklu opakovaně. Ale já bych řekl, tebe určitě zajímá, zda max_j neni náhodou menší než celkový počet elementů v řádku. A to budeš vědět až cyklus skončí.   

Tyhle nedostatky přímo funkčnost neovlivní, ale jednak znamenají plýtváním zdrojů mašiny (časem procesoru a pamětí) a jednak hrubě znesnadní čtení kódu v případě rozsáhlejšího souboru. No jen si představ jak by se to četlo, když by jsi měl těch vnořených cyklů několik a byly o něco delší.

5) Pokud vyloženě není tvým záměrem zjišťovat, kolik řádků a kolik elementů v nich je ve vstupu navíc (alespoň v původním zadání o tom nic nebylo), tak já osobně bych z cyklu vyskočil, jakmile bych dosáhl MAX_COLS  nebo MAX_ROWS. Tím si kód zpřehledníš a zjednodušíš, a odpadnou ti ty korekce před výpisem pole.
Název: Re:Načtení 2D pole v C
Přispěvatel: mikrom 23. 11. 2022, 03:45:08
Ahoj, pár postřehů z rychlíku

1) Když deklaruješ proměnnou, tak ji co nejdříve také inicializuj a nečekej na chvíli, kdy ji budeš chtít použít. Velmi lehce se na to zapomíná a následky mohou být neblahé. Obzvláště to platí pro pointery!
2) Pokud nejsi schopný zaručit, že ti funkce neselže, pak vždy kontroluj alespoň její návratovou hodnotu, pokud něco vrací. V tomto případě se to týká funkce fopen( ), protože v případě, že se něco provede se souborem, který má otevřít (bude smazán, přejmenován, atd...) koleduješ si - v lepším případě - o segfault o pár řádku níže.

já chápu, že toto je studijní kód začátečníka. Přesto z vlastní zkušenosti považuji za důležité na to upozornit. Důsledky podobných opomenutí se v rozsáhlejším a komplexnějším kódu velmi špatně hledají. A nestačí o tom jen vědět, je potřeba si to vštípit do krve hned od začátku. Věř mi, že ti to hodně časem ulehčí život.

3) Proměnná i je zbytečná. Jenom ji inkrementuješ a a pak přiřadíš do max_i. Popřemýšlej, zda není lepší pracovat rovnou s max_i a i zrušit.
4) Navrhuji ti, abys přesunul podmínku max_j < j až za vnitřní cyklus. To proto, že V současné chvíli testuješ max_j proti všem pozicím elementů v řádku a to v každém cyklu opakovaně. Ale já bych řekl, tebe určitě zajímá, zda max_j neni náhodou menší než celkový počet elementů v řádku. A to budeš vědět až cyklus skončí.   

Tyhle nedostatky přímo funkčnost neovlivní, ale jednak znamenají plýtváním zdrojů mašiny (časem procesoru a pamětí) a jednak hrubě znesnadní čtení kódu v případě rozsáhlejšího souboru. No jen si představ jak by se to četlo, když by jsi měl těch vnořených cyklů několik a byly o něco delší.

5) Pokud vyloženě není tvým záměrem zjišťovat, kolik řádků a kolik elementů v nich je ve vstupu navíc (alespoň v původním zadání o tom nic nebylo), tak já osobně bych z cyklu vyskočil, jakmile bych dosáhl MAX_COLS  nebo MAX_ROWS. Tím si kód zpřehledníš a zjednodušíš, a odpadnou ti ty korekce před výpisem pole.

AHOJ A DIKY ZA VYBORNE POSTREHY

2) navratovu hodnotu fpopen() som osetril
4) max_j < j som tiez dal az za vnutorny cyklus
5) kvoli kontrole bolo mojim zamerom vypisat aj kolko riadkov a stlpcov ma vstupny subor.

Normalne by som nedeklaroval vsetky premenne na zaciatku main(), ale pomocne premenne deklaroval az na mieste kde ich idem pouzit, napr.:  for (int i = 0; ...)
Dalej by som na jednotlive casti urobil samostatne funkcie, t.j.:
- funkciu ktora nacita nazov suboru z command line argumentu programu,
- funkciu ktora nacita data zo suboru do pola
- funkciu ktora vypise obsah pola

Dalo by sa na tom este dost popracovat, ale tazatel tu nedava k tomu ziadny feedback  :( takze to nema vyznam.

Pripajam zmeneny zdrojak

matica.c
Kód: [Vybrat]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_ROWS 100
#define MAX_COLS 100
#define MAX_LINE_LENGTH 256

int main()
{
    FILE *fp;
    char file_name[MAX_LINE_LENGTH] = "matrix.dat";
    char data_line[MAX_LINE_LENGTH];
    char *matrix_element;
    int i, j, max_i, max_j;
    int matrix[MAX_ROWS][MAX_COLS] = { 0 };

    if (!(fp = fopen(file_name,"r"))) {
        printf("ERROR: file \"%s\" not found !\n", file_name);
        return 1;
    }

    printf("Reading data from the file \"%s\":\n\n", file_name);
    max_j = 0;
    i = 0;
    while (fgets(data_line, MAX_LINE_LENGTH, fp) != NULL) {
        // Remove trailing \n
        data_line[strcspn(data_line, "\n")] = 0;

        // split line into matrix elements
        matrix_element = strtok(data_line, ",;\t ");
        j = 0;
        while(matrix_element != NULL) {
            printf("%s ", matrix_element);
            // populate matrix
            if ((i < MAX_ROWS) && (j < MAX_COLS)) {
                matrix[i][j] = atoi(matrix_element);
            }
            j++;
            matrix_element = strtok(NULL, ",;\t ");
        }
        if (max_j < j) max_j = j;
        printf("\n");
        i++;
    }
    max_i = i;
    fclose(fp);

    printf("\n..Done.\n\n");

    printf("Data file contains %d rows and %d columns\n\n", max_i, max_j);

    // eventually, adapt maximum indexes to the size of the matrix
    if (max_i > MAX_ROWS) {
        printf("WARNING: due to the declared size, matrix can only store\n"
               "         %d rows of a total of %d rows from the file.\n\n",
               MAX_ROWS, max_i);
        max_i = MAX_ROWS;
    }
    if (max_j > MAX_COLS) {
        printf("WARNING: due to the declared size, matrix can only store\n"
               "         %d columns of a total of %d columns from the file.\n\n",
               MAX_COLS, max_j);
        max_j = MAX_COLS;
    }

    // now print the matrix
    printf("The matrix is:\n\n");
    for (i = 0; i < max_i; i++) {
        for (j = 0; j < max_j; j++) {
            printf("%d\t", matrix[i][j]);
        }
        printf("\n");
    }

    return 0;
}
Název: Re:Načtení 2D pole v C
Přispěvatel: mr.rubik 23. 11. 2022, 11:46:16
Kod posledniho reseni jsem nestudoval do detailu, nicmene, reseni je vcelku nestastne a to z nasledujicich duvodu:

vse je tzv. nam*dane v mainu, neexistuje cleneni do funkci, ktere ten dany kus kodu "pojmenovavaji", minimalne ten print matice by mela byt funkce, i pro debugovaci ucely

jak jsem psal vyse, manualni parsovani vstupu pomoci fgets, strcspn apod. je naprosto nevhodne a to z nasledujicich duvodu:

muj nazor na komentare je, ze v kodu by jich melo byt co nejmene, protoze to vypovida o tom, ze autor neumi svuj kod sestavit tak, aby komentare nepotreboval (tj. mel by pouzivat standardni funkce), krasne to vystihuje komentar "// Remove trailing \n" - tohle presne resi getline a je to popsane v jeho dokumentaci

tohle je spis o definici problemu, ale i tak si nemyslim, ze je vhodne nechat program projit bez chyby pokud se prekroci limit na rozmery matice - k cemu pak je vypocet nad necelou matici? dale pak se program tvari, ze neco dela, nacita radky, parsuje, ale nic neuklada? to je dle meho nazoru podivne

tohle taky zalezi na definici a neexistuje univerzalni pravda, nicmene tyhle "skolni" priklady (stejne tak drtiva vetsina leetcode apod. problemu) parsuje vstupy ze stdin, je to i univerzalnejsi v tom, ze pokud ma clovek vstupy v souboru, muze ten soubor samozrejme presmerovat na vstup programu, ale zaroven muze zadavat male testovaci veci na stdin, odpada tim take osetrovani otevirani souboru, jmeno souboru (ktere je tady stejne hardcoded) atd.

Priznavam, ze jsem nejaky ten cas v pure Ccku nekodil, ale tohle je takova mala pekna ulozka pro oziveni, takze bych si dovolil take prispet svoji troskou do mlyna. Kdo najde nejakou zasadni chybu, ma u me pivo :) Automatizaci testovani ponechavam jako cviceni pro zvidaveho ctenare.
Název: Re:Načtení 2D pole v C
Přispěvatel: mikrom 23. 11. 2022, 12:44:37
..
Dik za vsetky postrehy a hinty.
To ze v tom mojom zdrojaku je vsetko spolu nam*dane v mainu som pisal v predoslom komente, ze by to bolo treba rozbit do funkcii, ale nakolko tazatel nedava feedback nedavalo mi to zmysel.
Ze ma C standardnu funkciu getline() som doteraz vobec nevedel, asi to bude nejaka novinka o ktorej neviem, lebo C nepouzivam. Urcite tu funkciu vyskusam.

VELKE DIK za prilozeny kod. Videt ze si si s tim dal hodne namahy. Este som ho neskusal, ale na prvy pohlad vyzera ze to je skor advanced level ako pre zaciatocnika. Vyskusam si ho a prestudujem.
Název: Re:Načtení 2D pole v C
Přispěvatel: snugar_i 23. 11. 2022, 15:17:11
@mr.rubik: Moje znalosti C jsou dost neaktuální, takže k tvýmu kódu mám hloupej dotaz - proč funkce freeMatrix a freeMatrixRow žerou const pointery? Myslel jsem, že const značí, že se s parametrem pracuje v podstatě "read-only", což dealokace jeho části úplně není? Díky za osvětlení
Název: Re:Načtení 2D pole v C
Přispěvatel: mr.rubik 23. 11. 2022, 17:42:05
@mr.rubik: Moje znalosti C jsou dost neaktuální, takže k tvýmu kódu mám hloupej dotaz - proč funkce freeMatrix a freeMatrixRow žerou const pointery? Myslel jsem, že const značí, že se s parametrem pracuje v podstatě "read-only", což dealokace jeho části úplně není? Díky za osvětlení

Dobra otazka!

Vec se ma tak, ze to, co je const je pointer na strukturu typu Matrix, tj. nemuzete zmenit rowCount, colCount, ale hlavne, nemuzete priradit jiny pointer do ukazatele data. A to je vlastne to, co jsem tim "v tu chvili" chtel rict: az tahle funkce skonci, vsechny membery budou v puvodnim stavu, i ten pointer bude porad ukazovat tam, kam puvodne, ale ta pamet uz bude uvolnena.

Nicmene, tohle je trochu obskurita Ccka: content toho pointeru data uvnitr pointeru, ktery ukazuje na strukturu, ve ktere je obsazen uz const sam o sobe neni. Jinak by se to ani nezkompilovalo, free vyzaduje non-const pointer.

Uznavam, ze tohle je trochu divne a kdybych si delal self-review, asi bych se nad tim pozastavil. Ale spis bych to tak nechal a z pohledu konzistence zmenil ostatni mista, kde inicializuju pointery na NULL. Spis se asi priklanim k neinicializaci promennych, pokud vylozene nepotrebuju a spis nastavit "kontrakt", kdy muzu data pouzivat - jako napriklad tady: kdyz row.colCount je 0, nema cenu lezt do row.data.

Nebo jako v tomto pripade: nastavil jsem "kontrakt", ze kdyz se zavola freeMatrix, matice uz neni pouzitelna a musi si to ohlidat programator. Prijde mi to lepsi nez neustale kontrolovat jestli pointery nejsou NULL i kdyz vim, ze proste v te dane casti kodu NULL nejsou.
Název: Re:Načtení 2D pole v C
Přispěvatel: vrit 24. 11. 2022, 12:22:50
Dobry den. Chtel bych ze souboru nacist ctvercovou matici o neznamem poctu radku/sloupcu a nasledne ji opet printnout. Nemuzu prijit na to proc to nenacita zadny cisla. Kod i input je v priloze. Predem dekuji za jakykoli feedback <3

1. Radek 16: pouzivas i < COL_MAX, ale mas pouzit j
2. Radek 24: Tato podminka je nesmysl, scanf pri formatu %d neco ulozi pouze pokud se jedna o cislo v textove forme
3. Radek 36: pouzivas i<countRow ale mas pouzit j a taky mas pouzit countCols (pokud matice neni garantovane ctvercova)

Misto i,j doporucuju pouzit row,col, mozna te to rychleji trkne kdyz udelas chybu.

Jinak jsem tvuj kod vzal, opravil a udelal minimalni upravy, aby to bylo ve tvem stylu. Pridal jsem zpracovani po radcich, ale zachoval jsem formatovany vstup pomoci sscanf (obdoba scanf, ktera ale jako vstup pouziva retezec, namisto standardniho vstupu). Muzes si je porovnat.

Kód: [Vybrat]
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define ROW_MAX 100
#define COL_MAX 100
#define LINE_MAX 256

int main()
{
char line[LINE_MAX];
char *p;

int array[ROW_MAX][COL_MAX] = { 0 };
int countRows = 0;
int countCols = 0;
int matrixScan = 0;

printf("Matice:\n");

for (int i = 0; i < ROW_MAX; i++) // loads matrix numbers into array
{
if (fgets(line, LINE_MAX, stdin) == NULL)
break;

if ((p = strtok(line, " ")) == NULL)
break;

for (int j = 0; j < COL_MAX; j++)
{

matrixScan = sscanf(p, "%d", &array[i][j]);

if (matrixScan != 1)
return 1;

countCols = i > countCols ? i : countCols;

if ((p = strtok(NULL, " ")) == NULL)
break;
}

countRows++;

if (matrixScan == EOF)
break;
}

printf("Pocet radku: %d\n", countRows);

for (int i = 0; i < countRows; i++) //prints matrix
{
printf("\n");

for (int j = 0; j < countCols; j++)
{
printf("%d ", array[i][j]);
}
}

return 0;
}
Název: Re:Načtení 2D pole v C
Přispěvatel: vrit 25. 11. 2022, 07:50:50
@mr.rubik: Moje znalosti C jsou dost neaktuální, takže k tvýmu kódu mám hloupej dotaz - proč funkce freeMatrix a freeMatrixRow žerou const pointery? Myslel jsem, že const značí, že se s parametrem pracuje v podstatě "read-only", což dealokace jeho části úplně není? Díky za osvětlení
Vec se ma tak, ze to, co je const je pointer na strukturu typu Matrix, tj. nemuzete zmenit rowCount, colCount, ale hlavne, nemuzete priradit jiny pointer do ukazatele data. A to je vlastne to, co jsem tim "v tu chvili" chtel rict: az tahle funkce skonci, vsechny membery budou v puvodnim stavu, i ten pointer bude porad ukazovat tam, kam puvodne, ale ta pamet uz bude uvolnena.
@mr.rubik: Nesouhlasim, konkretne s tvrzenim "to, co je const je pointer na strukturu typu Matrix". Neni to pravda. Pointer neni const ale ukazuje na const data, cili pres nej nelze zapisovat.

Kód: [Vybrat]
MatrixRow *const row; // konstantni ukazatel na typ MatrixRow (nelze primo zmenit kam ukazuje)
const MatrixRow *row; // ukazatel na typ const MatrixRow (nelze pres nej zapisovat)
const MatrixRow *const row; // konstantni ukazatel na typ const MatrixRow (nelze pres nej zapisovat, ani primo zmenit kam ukazuje)

Název: Re:Načtení 2D pole v C
Přispěvatel: vrit 25. 11. 2022, 07:59:55
@mr.rubik: Moje znalosti C jsou dost neaktuální, takže k tvýmu kódu mám hloupej dotaz - proč funkce freeMatrix a freeMatrixRow žerou const pointery? Myslel jsem, že const značí, že se s parametrem pracuje v podstatě "read-only", což dealokace jeho části úplně není? Díky za osvětlení

Bezna implementace free() nic s daty na ktera pointer ukazuje nedela, obycejne existuje nekde v pameti seznam vsech alokovanych chunku pameti, a v tomto seznamu se odstrani zaznam o alokovane pameti na niz posilame pointer jako parametr funkce free(). Timpadem si alokator tento chunk pameti "oznaci jako znovu pouzitelny" a to je cele. Z tohoto pohledu spada dealokace do kategorie read-only.

Muze existovat nejaka bezpecnostni verze, ktera napriklad pri dealokaci vsechno prepise nulami, ale neni to bezne. Data tam zustanou dokud je nekdo jiny neprepise. Dealokaci se vsak programator zavazuje, ze s nimi jiz nebude nakladat.
Název: Re:Načtení 2D pole v C
Přispěvatel: Ink 25. 11. 2022, 08:31:52
@mr.rubik: Moje znalosti C jsou dost neaktuální, takže k tvýmu kódu mám hloupej dotaz - proč funkce freeMatrix a freeMatrixRow žerou const pointery? Myslel jsem, že const značí, že se s parametrem pracuje v podstatě "read-only", což dealokace jeho části úplně není? Díky za osvětlení

Bezna implementace free() nic s daty na ktera pointer ukazuje nedela, obycejne existuje nekde v pameti seznam vsech alokovanych chunku pameti, a v tomto seznamu se odstrani zaznam o alokovane pameti na niz posilame pointer jako parametr funkce free(). Timpadem si alokator tento chunk pameti "oznaci jako znovu pouzitelny" a to je cele. Z tohoto pohledu spada dealokace do kategorie read-only.

Muze existovat nejaka bezpecnostni verze, ktera napriklad pri dealokaci vsechno prepise nulami, ale neni to bezne. Data tam zustanou dokud je nekdo jiny neprepise. Dealokaci se vsak programator zavazuje, ze s nimi jiz nebude nakladat.

Nikdo rozumný ale už nemůže předpokládat, že tam ten uvolněný objekt pořád je a o to jde. Z pohledu programové logiky a ne nějaké technické nahodilosti.
Název: Re:Načtení 2D pole v C
Přispěvatel: vrit 25. 11. 2022, 09:03:23
@mr.rubik: Moje znalosti C jsou dost neaktuální, takže k tvýmu kódu mám hloupej dotaz - proč funkce freeMatrix a freeMatrixRow žerou const pointery? Myslel jsem, že const značí, že se s parametrem pracuje v podstatě "read-only", což dealokace jeho části úplně není? Díky za osvětlení

Bezna implementace free() nic s daty na ktera pointer ukazuje nedela, obycejne existuje nekde v pameti seznam vsech alokovanych chunku pameti, a v tomto seznamu se odstrani zaznam o alokovane pameti na niz posilame pointer jako parametr funkce free(). Timpadem si alokator tento chunk pameti "oznaci jako znovu pouzitelny" a to je cele. Z tohoto pohledu spada dealokace do kategorie read-only.

Muze existovat nejaka bezpecnostni verze, ktera napriklad pri dealokaci vsechno prepise nulami, ale neni to bezne. Data tam zustanou dokud je nekdo jiny neprepise. Dealokaci se vsak programator zavazuje, ze s nimi jiz nebude nakladat.

Nikdo rozumný ale už nemůže předpokládat, že tam ten uvolněný objekt pořád je a o to jde. Z pohledu programové logiky a ne nějaké technické nahodilosti.

Souhlas... Jak jsem jiz zminil
Citace
Dealokaci se vsak programator zavazuje, ze s nimi jiz nebude nakladat.
Název: Re:Načtení 2D pole v C
Přispěvatel: mr.rubik 25. 11. 2022, 10:53:51
@mr.rubik: Moje znalosti C jsou dost neaktuální, takže k tvýmu kódu mám hloupej dotaz - proč funkce freeMatrix a freeMatrixRow žerou const pointery? Myslel jsem, že const značí, že se s parametrem pracuje v podstatě "read-only", což dealokace jeho části úplně není? Díky za osvětlení
Vec se ma tak, ze to, co je const je pointer na strukturu typu Matrix, tj. nemuzete zmenit rowCount, colCount, ale hlavne, nemuzete priradit jiny pointer do ukazatele data. A to je vlastne to, co jsem tim "v tu chvili" chtel rict: az tahle funkce skonci, vsechny membery budou v puvodnim stavu, i ten pointer bude porad ukazovat tam, kam puvodne, ale ta pamet uz bude uvolnena.
@mr.rubik: Nesouhlasim, konkretne s tvrzenim "to, co je const je pointer na strukturu typu Matrix". Neni to pravda. Pointer neni const ale ukazuje na const data, cili pres nej nelze zapisovat.

Kód: [Vybrat]
MatrixRow *const row; // konstantni ukazatel na typ MatrixRow (nelze primo zmenit kam ukazuje)
const MatrixRow *row; // ukazatel na typ const MatrixRow (nelze pres nej zapisovat)
const MatrixRow *const row; // konstantni ukazatel na typ const MatrixRow (nelze pres nej zapisovat, ani primo zmenit kam ukazuje)

Ano, mate pravdu, spatne jsem se vyjadril. Kazdopadne si myslim, ze jsem to popsal v nasledujicim textu spravne. Nabouchal jsem to vecer a mockrat jsem to po sobe necetl. Uznavam, ze tohle je vec k diskuzi, nicmene nevidim to jako nejaky vyznamny prohresek (typu buffer ovf apod.).

V C++ jeste existuje bitwise and logical constness - jsou to dve ruzne veci. Proto napriklad existuje keyword mutable.