Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
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í.
Avatar
Jirka Kadlec
Člen
Avatar
Jirka Kadlec:28.11.2019 19:24

Ahoj, mám projekt do programování, jehož cílem je udělat konzolovou aplikaci na databázi pro sázkovou kancelář, parametry jsou, že musím vést záznamy o jednotlivých sportech, ligách, týmech, zápasech a kurzech na zápasy data musím ukládat do texťáku a z hotové aplikace musím umět jednotlivé záznamy umět přidávat, editovat a mazat... zatím mám +- tohle:

Zkusil jsem:

# include <stdio.h>
# include <conio.h>
# include <stdlib.h>
# include <string.h>

struct sazky {
        char sport[30];
        char liga[40];
        char tym[20];
        char zapas[20];
        char kurz[10];
};

void zadej();
void edit();


int main()
{
        system("clr");
        int vyber;
        printf("1. vytvotit\n");
        printf("2. Editovat\n");
        printf("3. Smazat\n");
        printf("4. Odejit\n");

        scanf("%d", &vyber);

        switch (vyber)
        {
        case 1:
                zadej();
                break;
        case 2:
                edit();
                break;
        case 4:
                exit(0);

        default:
                printf("Spatny vyber. Zadejte novou hodnotu.");
                main();
        }
        getchar();
        return 0;
}

void zadej()
{
        FILE* fp;
        fp = fopen("sazkova kancelar.txt", "w");

        char sport[30];
        char liga[40];
        char tym[20];
        char zapas[20];
        char kurz[10];

        printf("zadejte sport:\n ");
        scanf("%s", &sport);
        printf("zadejte ligu:\n ");
        scanf("%s", &liga);
        printf("zadejte tym:\n ");
        scanf("%s", &tym);
        printf("zadejte zapas:\n ");
        scanf("%s", &zapas);
        printf("zadejte kurz:\n ");
        scanf("%s", &kurz);

        fprintf(fp,"Sport: %s Liga: %s Tym: %s Zapas: %s Kurz: %s",sport,liga,tym,zapas,kurz);
        fclose(fp);

        return 0;
}
void edit()
{
        FILE* fp1;
        FILE* fp2;
        char puvod_s[200];
        char edit_s[200];
        char retezec[200];
        fp1 = fopen("sazkova kancelar.txt", "a+");
        fp2 = fopen("sazka_edit.txt", "a+");
        fgets(retezec, 200, fp1);
        printf("%s\n", retezec);
        printf("Zadejte sazku kterou chcete editovat:");
        scanf("%s", &puvod_s);
        fscanf(fp1, "%s", puvod_s);
                printf("Zadejte novou sazku: ");
                scanf("%s", edit_s);
                fprintf(fp2, "%s", edit_s);
        fclose(fp1);
        fclose(fp2);

        fp1 = fopen("sazkova kancelar.txt", "a+");
        fp2 = fopen("sazka_edit.txt", "a+");
        while (!feof(fp2))
        {
                fscanf(fp2, "%s", edit_s);
                fprintf(fp1, "%s", edit_s);
        }
        fclose(fp1);
        fclose(fp2);

        return 0;
}

Chci docílit: momentálně nemám tušení jak napsat kód, který mi vybere ze záznamu dejme tomu třeba nějaký tým a změní ho nebo ho odstraní… Možná je to debilní způsob, kdyby vás prosím napadl lepší, byl bych moc vděčný... Kdyby se našel někdo kdo by mi dokázal pomoct ve formě naprogramování aspoň části toho, jsem ochotný finančně odměnit... Díky moc...

 
Odpovědět
28.11.2019 19:24
Avatar
Erik Hawlasek:28.11.2019 20:43

Ahoj, tak v prvé řadě, pokud otevřeš soubor v módu "w" jako write, soubor se vždy přepíše, to znamená, že by jsi nebyl schopný uchovávat týmu více, a vždy by jsi je přepsal tím jedním týmem, otevírej tedy soubor v módu "a" jako append, dále tam máš strukturu, kterou nevyužíváš, buď si deklaruj nějaké pole

struct sazky data[100]; //Uznej dle uvážení

, kde budeš hodnoty ze souboru například načítat, to je ten jednodušší způsob, já bych ale doporučoval naučit se dynamické alokování paměti, nebo tento problém řešit spojovým seznamem, ty sám si alokuješ velikost takovou, kolik potřebuješ a nemusíš řešit pak problémy, že v souboru máš 101 údajů a ty máš pole o 100 položkách. K té editaci a mazání, nepředpokládám, že by jsi tam měl údajů miliony, tak pro tebe nejjednodušší způsob bude načíst si všechny data ze souboru krásně do pole, dejme tomu, a poté jednoduše zjistíš, například podle čísla řádku, nebo jména klubu, který řádek potřebuješ editovat, vyzveš uživatele k zadání nových údajů a tento řádek přepíšeš, poté otevřeš soubor v módu "w" a vše tam znovu zapíšeš už po úpravě, mazání opět není nic složitého, můžeš to řešit stejně jak při editaci, najdeš řádek, který potřebuješ smazat a poté jednoduše z té dané pozice můžeš udělat něco jako:

for(i = radek; i < pocet - 1; i++) //Jsem na řádku, který chci odstranit
{
        polozka[i] = polozka[i + 1]; //Přepisuji od řádku až do konce následujícím prvkem
}

--pocet; //Jelikož jsem položku odebral, tak snížím počet

Poté opět zapíšeš do souboru :) Doufám že jsem tě aspoň trošku nakopl, ale opravdu doporučuji se naučit pracovat s dynamickou alokací paměti, tam to jde dělat mnohem čistěji než vše mít staticky :) Podívej se jak fungují struktury a tu uživatelskou nabídku udělej univerzálnější, zkus nad tím ještě popřemýšlet :) Kdyby jsi něco nevěděl tak se klidně ptej ;-).

Nahoru Odpovědět
28.11.2019 20:43
Za zeptání nic nedáš.
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka Kadlec
DarkCoder:28.11.2019 22:25

Tak jak to máš tak takto jednoduché to rozhodně nebude. Zadání je natolik rozsáhlé a komplexní, že jen základní kostra programu Ti zabere několik stovek řádků. Na to se připrav. Navíc procházení mezi položkami má konkrétní strukturu. Nemůžeš vše zadávat v jednom kroku, nic na sebe nenavazuje. Podívej se znova na nějaké stránky sázkové kanceláře a prohlédni si veškeré vazby.

Už úvodní stránka má nějakou podobu. Nelze začínat volbou když nevíš na so reaguješ. Na první stránce bude seznam sportů a pod ním nabídka volby. Uvědom si, že počet voleb bude dynamický v závislosti na počtu sportů. Pokud jich bude více, přibyde volba posun na další stránku. V závislosti na aktuální pozici v seznamu může přibýt posun na předchozí stránku. Kde bude volba ukončení aplikace je na tobě. Volby které budou dole bude Pridání, Editace, Mazání. Je třeba si uvědomit, že to je jen volba k typu sportu, tedy k úvodnímu seznamu.

Z volby sportu přecházíš na název ligy, z názvu ligy na zápas, ze zápasu na kurzy v zápasech mezi dvěma či vícero účastníky. Odtud na informace o týmu, soupisky, předchozí zápasy, statistiky, apod.

Pro jednoduchost použij pouze soubory, práce s adresáři si vyžaduje už pokročilejší znalost programování. Pro volbu můžeš použít to co se Ti zobrazuje na obrazovce nebo ID daného úkonu. Na základě výsledku volby přecházíš na další zobrazení a možnosti volby. Uvědom si, co ovlivňují zadané volby. Pokud například smažeš sport Fotbal, smažou se Ti všechny podkategorie pod ním. Když Edituješ položku, projeví se změna na všech dalších místech, apod.

ID je dobrá volba pro pohyb v aplikaci. Můžeš tak vyhledat daný úkon. Během programu si udržuješ informaci o maximálním ID. Když přidáváš novou položku, přiřazuješ mu unikátní ID.

Když budeš vědět spojitost mezi položkami a budeš mít nějaký návrh, můžeš začít tvořit. Při práci se soubory vnímej to, v jakém módu soubor otevíráš. Mnoho dobrých rad ohledně programátorského konceptu už bylo řečeno. Pokud se vydáš cestou čistého ID pro výběr volby, scanf() je postačující. V opačném případě používej fgets() a analyzuj a upravuj vstup. Bez dobré znalosti souborů a konceptu dynamické alokace se pro efektivně vypadající aplikaci neobejdeš.

Nahoru Odpovědět
28.11.2019 22:25
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Jirka Kadlec
Člen
Avatar
Odpovídá na Erik Hawlasek
Jirka Kadlec:29.11.2019 17:10

@DarkCoder Díky moc za rady, projekt má být jednoduchý, jsem na fakultě elektrotechniky a ostatní projekty typu jednoduchých old school her jsou na +- 50-100 řádků, takže jsem vážně nečekal, že to bude až tak složité... @Eric Hawlasek Díky moc, moc si vážím, že se snažíte pomoct, zatím mi na facebooku a ostatních fórech řekli akorát že se na to potřebuju naučit nějaké složité věci a že mi to bude trvat hodně dlouho.... Takže pokud to chápu dobře, mám si udělat jedno pole ve kterém budou všechny data jako název sportu, ligy, týmu atd... Vždycky jednu tu kompletní sadu dat budu ukládat na jeden řádek, takže bude na každém řádku jeden záznam. Ty jednotlivé věci v tom záznamu jako sport tým liga atd si mám oddělit třeba čárkou a pak když budu chtít změnit třeba nějaký tým, tak si najdu všechny řádky s tím týmem "pak je vymažu" a napíšu tam nové stejné řádky akorát s jiným názvem týmu? Jak mám vzít ten zbytek údajů v řádku který má zůstat stejný a vložit do něj tým, který je v tom řádku dejme tomu uprostěd... Smazat budu chtít potom celý řádek, to ano, ale jak to mám teda editovat, když měním jenom jednu věc v řádku? Potřebuju co nejjednodušší a nejméně časově náročné řešení, má to být projekt, na který mám dohromady 3 týdny (teď už jen 2) a měl by mít opravdu pár desítek řádků.. Probíráme jenom základy C++ konzolovek, je to předmět na pár kreditů který mám mimo obor... Ještě jednou díky moc..

Editováno 29.11.2019 17:11
 
Nahoru Odpovědět
29.11.2019 17:10
Avatar
Jirka Kadlec
Člen
Avatar
Odpovídá na Erik Hawlasek
Jirka Kadlec:29.11.2019 20:23

Resp. nevíte prosím jak přesně bych mohl najít v tom souboru všechny záznamy (řádky) ve kterých je slovo, které předtím uživatel zadá a pak je všechny vymazat? Našel jsem na to nějaké funkce, ale žádnou jsem nerozjel... Díky moc, pěkný večer.

 
Nahoru Odpovědět
29.11.2019 20:23
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka Kadlec
DarkCoder:29.11.2019 21:31

Hledání slova v záznamu se dá jinak prezentovat jako hledání subřetězce v řetězci. K tomu v C slouží funkce strstr(), která se součástí knihovny string.h

Prototyp funkce je:

char *strstr(const char *mainstring, const char *substring)

kde:

  • mainstring představuje konstantní ukazatel na začátek řetězce u kterého chceme přítomnost subřetězce otestovat
  • substring představuje konstantní ukazatel na začátek řetězce jehož přítomnost chceme v hlavním řetězci otestovat

V případě úspěchu vrací funkce strstr() ukazatel na první výskyt subřetězce v řetězci. V opačném případě vrací NULL.

Následující příklad ukazuje použití funkce strstr().

#include <stdio.h>
#include <string.h>

int main(void) {
        const char str[] = "Mam rad retezce";
        const char substr[] = "retez";

        if (strstr(str, substr)) printf("subretezec nalezen\n");
        else printf("subretezec nenalezen\n");

        return(0);
}

Pozn:
V některých programech může být použití této funkce nebezpečné a je to i tvůj případ. Pokud budeš mít veškerá data uložena v jednom souboru, popř. ne úplně rozdělena zvlášť, může mít nevhodná volba subřetězce vliv i na záznamy, které měnit nechceš. Následné mazání záznamů spojené s subřetězcem může mít fatální důsledky na správnou funkčnost tvé aplikace.

Nahoru Odpovědět
29.11.2019 21:31
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na Jirka Kadlec
Erik Hawlasek:30.11.2019 0:02

Ahoj, DarkCoder už tuto problematiku velmi krásně vysvětlil, no, otázka teda je, co to znamená, že to má být jednoduché, pokud to má být vše provázané mezi sebou, jak vysvětloval DarkCoder, doporučuji si prvně nakreslit jakési tabulky, které mezi sebou propojíš aby jsi viděl, do čeho se vlastně chystáš jít. Podobně to tedy realizuješ i v souboru. Struktura je zjednodušeně řečeno schránka schopná uchovávat data, je jen na tobě, jak s ní naložíš, dejme tomu že struktura Sport, by mohla obsahovat například:

struct Sport
{
int id_sportu;
char nazevSportu[100];
// další data, která potřebuješ
};

Řádek můžeš ukládat do souboru například takto:

1|Fotbal //Další data

Máš více možností, ve funki fscanf pro čtení ze souboru jde použít krásný regulární výraz, kde si řetězec rozkouskuješ a celý ho do struktury uložíš, poté už budeš mít nějakou podmínku, kde se budeš ptát, jestli je id týmu shodné s tím, o který si žádáš (může to být i název týmu, vše je na tobě :)) Pokud zjistíš, že je shoda, znamená to, že jsi našel i onen řádek v souboru, který máš načtený ve struktuře, s těmito daty už si můžeš dělat operace které se ti zlíbí, pokud by jsi tyto hodnoty načetl do toho pole, ale opravdu doporučuji používat dynamickou alokaci paměti :) tak jsi schopný daný řádek upravit a pak to znova do souboru zapsat... V knihovně <string.h> je funkce strtok, pomocí které můžeš opět řádek rozdělit pomocí oddělovačů :) ale rychlejší je to opravdu tím regulárním výrazem přes fscanf(), zmínil jsi základy C++, tam bych se už určitě začal dívat na objektové programování :) tvůj kód totiž prvky C++ nevyužívá vůbec. Takto zapsaný kód vypadá jako čisté Cčko :). Pokud by jsi chtěl použít funkci strtok, načti celý řádek funkcí fgets() a ten pak zpracuj, tuto funkci už taky zmínil DarkCoder. Jedná se tedy pouze o načtení dat ze souboru, vyhledání daného prvku, například pro editaci a jen úprava jeho jména a následné zapsání zpět do souboru, jo pokud to má být provázané, nebude to tak jednoduché a budeš muset například na základě získaných dat z jednoho souboru vyhledat data, která na to navazují, jak může taková návaznost vypadat bylo již řečeno od DarkCodera, pro ukázku ještě tedy přidám příklad s fscanf:

int i = 0;

FILE *file = fopen("sporty.txt", "r");

while(fscanf(file, "%d|%[^\n]", &sport[i].id_sportu, sport[i].nazevSportu) != EOF)
{
        if(id == sport[i].id_sportu)
        {
                //našel jsem ho, vyzvu uživatele například k úpravě názvu sportu...
        }
        ++i;
}

//zapíšeš po úpravě do souboru

fclose(file);

Kód jsem netestoval, takže tam může být nějaká chybka, ale jde o to že nějak takto podobně to může vypadat, snad ti to tedy nějak pomohlo :).

Nahoru Odpovědět
30.11.2019 0:02
Za zeptání nic nedáš.
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 7 zpráv z 7.