NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Zápis do souboru

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

Aktivity
Avatar
Jirka
Člen
Avatar
Jirka:28.12.2017 20:16

Ahoj,
jak prosím zapíšu správně souboru? Chyba je zřejmě dole jak je "&vysledek". Nejde mi tam zapsat a nevím jak to zaspat správně :(
Všude na internetu nacházím jen zapisování textu, ale já bych potřeboval do txt šoupnout přímo výsledek.
Text mi to normálně vypíše.
Děkuju moc!

case 1:
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        printf("Vysledek: %d\n", prvnicislo + druhecislo);
                        int vysledek = prvnicislo + druhecislo;
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        scanf("%d", &zapis);
                        if (zapis == 'Y'); // neni case sensitive
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, &vysledek);
                        }
                        break;
 
Odpovědět
28.12.2017 20:16
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka
DarkCoder:28.12.2017 20:45

Máš tam 2 chyby:

  1. Escape sekvence %d se používá pro načtení celého čísla (int). Pokud chceš načíst znak použij funkci getchar(). Funkce getchar() má následující prototyp:

int getchar(void);

a tedy:

char zapis;
zapis = getchar();

  1. Funkci fprintf() voláš se špatným počtem a typem parametrů. Funkce fprintf() má následující prototyp:

int fprintf(FILE *fp, char *formatovaci_re­tezec, ...);

a tedy:

FILE *soubor;
int vysledek;
fprintf(soubor, "%d", vysledek);

Nahoru Odpovědět
28.12.2017 20:45
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Martin Dráb
Tvůrce
Avatar
Odpovídá na Jirka
Martin Dráb:28.12.2017 20:48

¨Pro tyto účely tu existuje funkce fwrite.

fwrite(&vysledek, sizeof(vysledek), 1, soubor);

Parametry:

  1. adresa dat, která chci zapsat,
  2. velikost jednoho elementu dat,
  3. počet elementů k zapásní (vhodné v případě, že zapisuješ pole),
  4. adresa struktury FILE * popisující soubor, kam zapisuješ.

Součin druhého a třetího parametru udává počet bajtů, které budou zapsány počínaje adresou předanou v prvním parametru. Čtvrý parametr získáš např. funkcí foepn, nebo můžeš použít standardní výstup (stdout) či standardní chybový výstup (stderr).

Jen POZOR na to, že ve Windows se rozlišuje binární a textový přístup k souboru (protože konce řádků jsou kódovány dvěma znaky a soubor otevřený v textovém režimu je sám "opravuje"). Pokud chceš zapisovat binární data (což zjevně chceš), musíš buď soubor otevřít v binárním režimu (přidej znak b do druhého parametru fopen, nebo použij funkci _setmode pro nastavení režimu již otevřeného souboru (platí zejména pro stdout a stderr). Tahle chyba je velmi nebezpečná a velmi těžko se zpětně hledá.

Nahoru Odpovědět
28.12.2017 20:48
2 + 2 = 5 for extremely large values of 2
Avatar
Jirka
Člen
Avatar
Jirka:28.12.2017 22:13

Ahoj, díky za info. Poupravil jsem to a vypadá to takto. Jen mi to vždycky rovnou zapíše do souboru a neptá se to zda chci zapsat. Do txt mi to vypíše buďto nějaký znaky a nebo nic.

Jsem v tom úplně na začátcích, tak se omlouvám že to je se mnou takový těžší.

#define _CRT_SECURE_NO_WARNINGS

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define PI 3.14159265359
#define textak "text.txt"

int main(int argc, char *argv[]) {

        int operator;
        int prvnicislo;
        int druhecislo;
        char zapis;

        FILE *soubor; // When working with files, you need to declare a pointer of type file. This declaration is needed for communication between the file and program.
        soubor = fopen(textak, "a+"); // Open for reading and appending (writing at end of file). The file is created if it does not exist. The initial file position for reading is at the beginning of the file, but output is always appended to the end of the file.

        /*
        printf("Zadej cislo: ");
        scanf("%d", &prvnicislo);
        */

        printf("\nMENU OPERACI\n\n");
        printf("1 pro scitani\n");
        printf("2 pro odecitani\n");
        printf("3 pro nasobeni\n");
        printf("4 pro deleni\n");
        printf("5 pro sinus\n");
        printf("6 pro cosinus\n");
        printf("7 pro tangens\n");
        printf("8 pro druhou mocninu\n");
        printf("9 pro faktorial");
        printf("Q pro ukonceni programu\n\n");

        printf("Vyber operaci: ");
        scanf("%d", &operator);

        do
        {
                switch (operator) {
                case 1:
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        printf("Vysledek: %d\n", prvnicislo + druhecislo);
                        int vysledek = prvnicislo + druhecislo;
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        //scanf("%d", &zapis);
                        zapis = getchar();
                        if (zapis == 'Y'); // neni case sensitive
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d", vysledek);
                        }
                        break;
 
Nahoru Odpovědět
28.12.2017 22:13
Avatar
Martin Dráb
Tvůrce
Avatar
Martin Dráb:28.12.2017 22:21

Pokud chceš zapsat to číslo do souboru textově (tzn. aby jsi jej byl jako člověk schopen přečíst, když si ten soubor otevřeš např. v textovém editoru), tak se řiď příspěvkem od DarkCoder. Já jsem řešil případ, kdy to číslo tam chceš zapsat binárně (ve strojově čitelné/binární podobě).

Nahoru Odpovědět
28.12.2017 22:21
2 + 2 = 5 for extremely large values of 2
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka
DarkCoder:28.12.2017 23:50

Ve vstupním bufferu Ti zůstávají znaky které funkce getchar() přebírá. Uprav kód na následující:

fseek(stdin, 0, SEEK_END);
zapis = getchar();
if ((zapis == 'Y') || (zapis == 'y')){
        printf("Zapisuji...\n");
        fprintf(soubor, "%d\n", vysledek);
}
break;

Pozor na ten středník za výrazem v podmínce, to co vytváříš je prázdný příkaz a následující blok už do cíle podmínky nepatří a provede se vždy. Pro ukončení programu zvol 0 (nulu), znakovou konstantu Q proměnná operator nepřevezme.

Nahoru Odpovědět
28.12.2017 23:50
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Jirka
Člen
Avatar
Jirka:29.12.2017 15:06

Ahoj, díky za info. Program funguje ale zapíše mi to zase nějaké znaky. Když sčítám třeba 50 + 50, tak mi to do txt uloží "〱ര".

#define _CRT_SECURE_NO_WARNINGS

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define PI 3.14159265359
#define textak "text.txt"

int main(int argc, char *argv[]) {

        int operator;
        int prvnicislo;
        int druhecislo;
        char zapis;

        FILE *soubor; // When working with files, you need to declare a pointer of type file. This declaration is needed for communication between the file and program.
        soubor = fopen(textak, "a+"); // Open for reading and appending (writing at end of file). The file is created if it does not exist. The initial file position for reading is at the beginning of the file, but output is always appended to the end of the file.

        /*
        printf("Zadej cislo: ");
        scanf("%d", &prvnicislo);
        */

        printf("\nMENU OPERACI\n\n");
        printf("1 pro scitani\n");
        printf("2 pro odecitani\n");
        printf("3 pro nasobeni\n");
        printf("4 pro deleni\n");
        printf("5 pro sinus\n");
        printf("6 pro cosinus\n");
        printf("7 pro tangens\n");
        printf("8 pro druhou mocninu\n");
        printf("9 pro faktorial\n");
        printf("0 pro ukonceni programu\n\n");

        printf("Vyber operaci: ");
        scanf("%d", &operator);

        do
        {
                switch (operator) {
                case 1:
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        printf("Vysledek: %d\n", prvnicislo + druhecislo);
                        int vysledek = prvnicislo + druhecislo;
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        //scanf("%d", &zapis);
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y')) // neni case sensitive
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d\n", vysledek);
                        }
                        break;
                case 2:
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        printf("Vysledek: %d\n", prvnicislo - druhecislo);
                        break;
                case 3:
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        printf("Vysledek: %d\n", prvnicislo * druhecislo);
                        break;
                case 4:
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        printf("Vysledek: %d\n", prvnicislo / druhecislo);
                        break;
                case 5:
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Vysledek: %f\n", sin(prvnicislo * PI / 180));
                        break;
                case 6:
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Vysledek: %f\n", cos(prvnicislo * PI / 180));
                        break;
                case 7:
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Vysledek: %f\n", tan(prvnicislo * PI / 180));
                        break;
                case 8:
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Vysledek: %d\n", prvnicislo * prvnicislo);
                        break;
                default:
                        exit(0);
                }
                return 0;
        }
        while (operator!='0');
}
Editováno 29.12.2017 15:07
 
Nahoru Odpovědět
29.12.2017 15:06
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka
DarkCoder:29.12.2017 18:04

Je dobře že jsi sem přiložil celý kód. Pojďme si postupně projít to nejdůležitější.

V předchozích příspěvcích jsem se o tom nezmiňoval, ale vždy testuj funkci fopen() na její návratovou hodnotu. Je to důležité. Je třeba vědět, zda-li se Ti podařilo soubor v daném režimu otevřít.

do-while cyklus není správně ze tří důvodů. Ten první je, že na test jeho podmínky totiž nikdy nedojde. Program ukončuješ buďto v případě, kdy uživatel zadává vstup jiný nežli tebou požadovaný vstup z menu (exit()) nebo po provedení úseku kódu dle volby menu (return). Ten druhý je ten, že je třeba testovat na číselnou hodnotu nikoli znakovou (operator je typu int nikoli char). Ten třetí je že nejspíš chceš, aby si uživatel mohl vybrat novou operaci dle menu po provedení předchozí operace a to zde chybí.

V příkazu switch musíš oddělit dva stavy. Vyhodnocení dle menu a to co do menu nezapadá (case 0-9 a default). case 1-9 obsahuje průběh operace dle menu, case 0 korektní ukončení do-while cyklu.

Např:

case 0: operator = 0;
             break;

sekce default by měla obsahovat informaci o neznámém vstupu a vrátit se do menu než tiše ukončit program pomocí exit(). Funkci exit() používej v situaci kdy nastane nějaká abnormální chyba. Jako parametr používej nenulovou hodnotu v závislosti na závažnosti chyby. Využiješ ji třeba při testování správnosti otevření souboru v daném režimu.

Příkaz return s návratovou hodnotou nula umísti před uzavírací složené závorky funkce main(), kterou máš deklarovanou s návratovým typem int. Tím říkáš operačnímu systému, že program skončil bez chyb.

Ale to nejpodstatnější je, že si zapomněl na uzavření souboru. Soubor uzavřeš pomocí funkce fclose().
Funkce fclose() má následující prototyp:

int fclose(FILE *fp);

a tedy ve tvém případě je třeba za do-while cyklus vložit:

fclose(soubor);

A stejně jako u fopen() můžeš ověřit, zda uzavření souboru proběhlo v pořádku či nikoli.

Nahoru Odpovědět
29.12.2017 18:04
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Jirka
Člen
Avatar
Jirka:29.12.2017 20:46

Ahoj, díky moc za radu. Upravil jsem to.

Ten druhý je ten, že je třeba testovat na číselnou hodnotu nikoli znakovou (operator je typu int nikoli char).

To udělám prosím jak? Jediný char tam mám u toho zápisu.
Děkuju moc.

 
Nahoru Odpovědět
29.12.2017 20:46
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka
DarkCoder:29.12.2017 23:04

Uprav test podmínky do-while cyklu z:

while (operator!='0');

Zde porovnáváš se znakovou konstantou.

na:

while (operator!=0);

Zde porovnáváš s celočíselnou konstantou.

popřípadě:

while (operator); // není nula

Což je totožný zápis jako výše uvedený.

Pokud by si to nechal tak jak to bylo, porovnával by si ve skutečnosti proměnnou operator s hodnotou 48 (ASCII kód '0' je 48(DEC)).

Nahoru Odpovědět
29.12.2017 23:04
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Jirka
Člen
Avatar
Jirka:30.12.2017 11:49

Děkuju, už jsem to upravil.
Teď mi to akorát pořád ukládá do txt ty divný znaky místo čísel :(

 
Nahoru Odpovědět
30.12.2017 11:49
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka
DarkCoder:30.12.2017 12:43

Spusť následující kód:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(int argc, char *argv[]) {
        FILE *soubor = fopen("test2.txt", "a+");
        fprintf(soubor, "%d\n", 50+50);
        fclose(soubor);
        return 0;
}

Co obsahuje soubor test2.txt?

Editováno 30.12.2017 12:44
Nahoru Odpovědět
30.12.2017 12:43
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Jirka
Člen
Avatar
Jirka:30.12.2017 12:54

Uloží se do něj 100.

 
Nahoru Odpovědět
30.12.2017 12:54
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka
DarkCoder:30.12.2017 13:05

Správně. Teď spusť následující kód:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(int argc, char *argv[]) {
        FILE *soubor = fopen("test2.txt", "a+");
        int prvnicislo;
        int druhecislo;
        int vysledek;

        printf("Zadej prvni cislo: ");
        scanf("%d", &prvnicislo);
        printf("Zadej druhe cislo: ");
        scanf("%d", &druhecislo);
        printf("Vysledek: %d\n", (vysledek = prvnicislo + druhecislo));
        printf("Zapisuji...\n");
        fprintf(soubor, "%d\n", vysledek);
        fclose(soubor);
        return 0;
}

Co se Ti zapsalo do souboru?

Nahoru Odpovědět
30.12.2017 13:05
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Jirka
Člen
Avatar
Jirka:30.12.2017 13:09

Celé číslo. To je mi teda divný že mi tamto vypisuje znaky :(

 
Nahoru Odpovědět
30.12.2017 13:09
Avatar
Jirka
Člen
Avatar
Jirka:30.12.2017 13:14

Mohlo by to byt tim ze tam misto

FILE *soubor = fopen("test2.txt", "a+");

mám toto?

soubor = fopen(textak, "a+");

Víc mě toho nenapadá. Celý kód teď vypadá takto:

#define _CRT_SECURE_NO_WARNINGS

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define PI 3.14159265359
#define textak "text.txt"

int main(int argc, char *argv[]) {

        int operator;
        int prvnicislo;
        int druhecislo;
        //double faktorial;
        long vysledek;
        char zapis;
        unsigned long long faktorial = 1;
        int i, n;

        FILE *soubor; // When working with files, you need to declare a pointer of type file. This declaration is needed for communication between the file and program.
        soubor = fopen(textak, "a+"); // Open for reading and appending (writing at end of file). The file is created if it does not exist. The initial file position for reading is at the beginning of the file, but output is always appended to the end of the file.

        /*
        printf("Zadej cislo: ");
        scanf("%d", &prvnicislo);
        */

        printf("\nMENU OPERACI\n\n");
        printf("1 pro scitani\n");
        printf("2 pro odcitani\n");
        printf("3 pro nasobeni\n");
        printf("4 pro deleni\n");
        printf("5 pro sinus\n");
        printf("6 pro cosinus\n");
        printf("7 pro tangens\n");
        printf("8 pro druhou mocninu\n");
        printf("9 pro faktorial\n");
        printf("10 pro obvod kruhu\n");
        printf("11 pro obsah kruhu\n");
        printf("0 pro ukonceni programu\n\n");

        printf("Vyber operaci: ");
        scanf("%d", &operator);

        do
        {
                switch (operator) {
                case 1: // scitani
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        vysledek = prvnicislo + druhecislo;
                        printf("Vysledek: %d\n", vysledek);
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        //scanf("%d", &zapis);
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y'))
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d\n", vysledek);
                        }
                        break;
                case 2: // odcitani
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        vysledek = prvnicislo - druhecislo;
                        printf("Vysledek: %d\n", vysledek);
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y'))
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d\n", vysledek);
                        }
                        break;
                case 3: // nasobeni
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        vysledek = prvnicislo * druhecislo;
                        printf("Vysledek: %d\n", vysledek);
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y'))
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d\n", vysledek);
                        }
                        break;
                case 4: // deleni
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        vysledek = prvnicislo / druhecislo;
                        printf("Vysledek: %d\n", vysledek);
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y'))
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d\n", vysledek);
                        }
                        break;
                case 5: // sinus
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Vysledek: %f\n", sin(prvnicislo * PI / 180));
                        break;
                case 6: // cosinus
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Vysledek: %f\n", cos(prvnicislo * PI / 180));
                        break;
                case 7: // tangens
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Vysledek: %f\n", tan(prvnicislo * PI / 180));
                        break;
                case 8: // druha mocnina
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Vysledek: %d\n", prvnicislo * prvnicislo);
                        break;
                case 9: // faktorial
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        if (prvnicislo < 0)
                        {
                                printf("Faktorial nelze pro zaporne cislo spocitat\n");
                                return 0;
                        }
                        else
                        {
                                for (int i = 1; i <= prvnicislo; ++i)
                                {
                                        faktorial *= i; // faktorial = faktorial * i;
                                }
                                printf("Faktorial cisla %d je %llu\n", prvnicislo, faktorial);
                        }
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y'))
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d, %llu\n", prvnicislo, faktorial);
                        }
                        break;
                case 10: // obvod kruhu
                        printf("Zadej polomer: ");
                        scanf("%d", &prvnicislo);
                        if (prvnicislo < 0)
                        {
                                printf("Obvod nelze pro zaporne cislo spocitat\n");
                                return 0;
                        }
                        else
                        {
                                vysledek = 2 * PI * prvnicislo;
                        }
                        printf("Vysledek: %d\n", vysledek);
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y'))
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d\n", vysledek);
                        }
                        break;
                case 11: // obsah kruhu

                        break;
                case 0:
                        operator = 0;
                        break;

                /*default: // vhodnejsi pouzit case 0...
                        exit(0);*/
                }
                fclose(soubor);
                return 0;
        }
        while (operator!=0);
        return(0);
}
 
Nahoru Odpovědět
30.12.2017 13:14
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka
DarkCoder:30.12.2017 13:21

Spusť následující kód:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(int argc, char *argv[]) {
        FILE *soubor = fopen("test2.txt", "a+");
        int prvnicislo;
        int druhecislo;
        int vysledek;
        int operator;

        do {
                printf("MENU OPERACI\n");
                printf("1 pro scitani\n");
                printf("0 pro ukonceni programu\n\n");

                printf("Vyber operaci: ");
                scanf("%d", &operator);

                switch (operator) {
                case 0: break;
                case 1: printf("Zadej prvni cislo: ");
                                scanf("%d", &prvnicislo);
                                printf("Zadej druhe cislo: ");
                                scanf("%d", &druhecislo);
                                printf("Vysledek: %d\n", (vysledek = prvnicislo + druhecislo));
                                printf("Zapisuji...\n\n");
                                fprintf(soubor, "%d\n", vysledek);
                                break;
                default: printf("Neznama operace.\n\n");
                                 break;
                }

        } while (operator);

        fclose(soubor);

        return 0;
}

Já se zatím podívám na tvůj kód...

Nahoru Odpovědět
30.12.2017 13:21
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Jirka
Člen
Avatar
Odpovídá na DarkCoder
Jirka:30.12.2017 13:24

Také mi to sečetlo správně. To je mi teda záhada..

 
Nahoru Odpovědět
30.12.2017 13:24
Avatar
DarkCoder
Člen
Avatar
Odpovídá na DarkCoder
DarkCoder:30.12.2017 13:39

Pokud používáš proměnnou typu long, používej specifikátor %ld.
Soubor uzavírej až za do-while cyklem a odstraň řádek s return 0 uvnitř cyklu.

...
case 0:  break;
default: printf("Neznama operace.\n\n");
             break;
} // switch
}  while (operator!=0); // do-while
fclose(soubor);
return(0);
} // main
Nahoru Odpovědět
30.12.2017 13:39
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Jirka
Člen
Avatar
Jirka:30.12.2017 14:23

Ahoj, upravil jsem to, ale teď mi to tam vůbec nic nezapíše :(

#define _CRT_SECURE_NO_WARNINGS

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define PI 3.14159265359
#define textak "text.txt"

int main(int argc, char *argv[]) {

        int operator;
        int prvnicislo;
        int druhecislo;
        //double faktorial;
        long vysledek;
        char zapis;
        unsigned long long faktorial = 1;
        int i, n;

        FILE *soubor; // When working with files, you need to declare a pointer of type file. This declaration is needed for communication between the file and program.
        soubor = fopen(textak, "a+"); // Open for reading and appending (writing at end of file). The file is created if it does not exist. The initial file position for reading is at the beginning of the file, but output is always appended to the end of the file.

        /*
        printf("Zadej cislo: ");
        scanf("%d", &prvnicislo);
        */

        printf("\nMENU OPERACI\n\n");
        printf("1 pro scitani\n");
        printf("2 pro odcitani\n");
        printf("3 pro nasobeni\n");
        printf("4 pro deleni\n");
        printf("5 pro sinus\n");
        printf("6 pro cosinus\n");
        printf("7 pro tangens\n");
        printf("8 pro druhou mocninu\n");
        printf("9 pro faktorial\n");
        printf("10 pro obvod kruhu\n");
        printf("11 pro obsah kruhu\n");
        printf("0 pro ukonceni programu\n\n");

        printf("Vyber operaci: ");
        scanf("%d", &operator);

        do
        {
                switch (operator)
                {
                case 1: // scitani
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        vysledek = prvnicislo + druhecislo;
                        printf("Vysledek: %d\n", vysledek);
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        //scanf("%d", &zapis);
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y'))
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d\n", vysledek);
                        }
                        break;
                case 2: // odcitani
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        vysledek = prvnicislo - druhecislo;
                        printf("Vysledek: %d\n", vysledek);
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y'))
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d\n", vysledek);
                        }
                        break;
                case 3: // nasobeni
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        vysledek = prvnicislo * druhecislo;
                        printf("Vysledek: %d\n", vysledek);
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y'))
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d\n", vysledek);
                        }
                        break;
                case 4: // deleni
                        printf("Zadej prvni cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Zadej druhe cislo: ");
                        scanf("%d", &druhecislo);
                        vysledek = prvnicislo / druhecislo;
                        printf("Vysledek: %d\n", vysledek);
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y'))
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d\n", vysledek);
                        }
                        break;
                case 5: // sinus
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Vysledek: %f\n", sin(prvnicislo * PI / 180));
                        break;
                case 6: // cosinus
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Vysledek: %f\n", cos(prvnicislo * PI / 180));
                        break;
                case 7: // tangens
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Vysledek: %f\n", tan(prvnicislo * PI / 180));
                        break;
                case 8: // druha mocnina
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        printf("Vysledek: %d\n", prvnicislo * prvnicislo);
                        break;
                case 9: // faktorial
                        printf("Zadej cislo: ");
                        scanf("%d", &prvnicislo);
                        if (prvnicislo < 0)
                        {
                                printf("Faktorial nelze pro zaporne cislo spocitat\n");
                                return 0;
                        }
                        else
                        {
                                for (int i = 1; i <= prvnicislo; ++i)
                                {
                                        faktorial *= i; // faktorial = faktorial * i;
                                }
                                printf("Faktorial cisla %d je %llu\n", prvnicislo, faktorial);
                        }
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y'))
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d, %llu\n", prvnicislo, faktorial);
                        }
                        break;
                case 10: // obvod kruhu
                        printf("Zadej polomer: ");
                        scanf("%d", &prvnicislo);
                        if (prvnicislo < 0)
                        {
                                printf("Obvod nelze pro zaporne cislo spocitat\n");
                                return 0;
                        }
                        else
                        {
                                vysledek = 2 * PI * prvnicislo;
                        }
                        printf("Vysledek: %d\n", vysledek);
                        printf("Prejes si zapsat vysledek do souboru? Y pro ANO / N pro NE\n");
                        fseek(stdin, 0, SEEK_END);
                        zapis = getchar();
                        if ((zapis == 'Y') || (zapis == 'y'))
                        {
                                printf("Zapisuji...\n");
                                fprintf(soubor, "%d\n", vysledek);
                        }
                        break;
                case 11: // obsah kruhu

                        break;
                case 0:
                        operator = 0;
                        break;

                default:
                        printf("Neznama operace\n");
                        break;
                }
        }
        while (operator!=0);
        fclose(soubor);
        return (0);
}
 
Nahoru Odpovědět
30.12.2017 14:23
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka
DarkCoder:30.12.2017 14:24

Jinač všechny následující úryvky kódu jsou výsledkově totožné

FILE *soubor = fopen("test2.txt", "a+");
FILE *soubor;
soubor = fopen("test2.txt", "a+");
#define textak "test2.txt"
FILE *soubor = fopen(textak, "a+");
#define textak "test2.txt"
FILE *soubor;
soubor = fopen(textak, "a+");
Editováno 30.12.2017 14:24
Nahoru Odpovědět
30.12.2017 14:24
"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 Jirka
DarkCoder:30.12.2017 14:33

Ahoj, upravil jsem to, ale teď mi to tam vůbec nic nezapíše

Program musíš řádně ukončit, bez toho se Ti do souboru nic nezapíše. Musíš kód upravit tak, aby se dal ukončit. Všimni si, že jsem vložil menu do těla do-while cyklu. Důvodem je abych mohl vybrat novou operaci nebo ukončit program.

Nahoru Odpovědět
30.12.2017 14:33
"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 Jirka
DarkCoder:30.12.2017 14:57

Podívej na následující kód:

do {
        printf("Zadej cislo: ");
        scanf("%d", &operator);
        // ...
} while (operator);

Na stejném principu musíš upravit svůj program.

Nahoru Odpovědět
30.12.2017 14:57
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Jirka
Člen
Avatar
Jirka:30.12.2017 17:10

Ahoj,
tak už to mám a dokonce mi to i vypisuje čísla a ne znaky, tak super :-)
Děkuju ti moc!!
Ještě mám poslední dotaz. Jsou nějaké výhody / nevýhody mezi těmito zápisy, jak jsi psal prve?

FILE *soubor = fopen("test2.txt", "a+");

FILE *soubor;
soubor = fopen("test2.txt", "a+");

#define textak "test2.txt"
FILE *soubor = fopen(textak, "a+");

#define textak "test2.txt"
FILE *soubor;
soubor = fopen(textak, "a+");

Pro moje potřeby se mi jeví nejjednodušší používat ten první řádek.

FILE *soubor = fopen("test2.txt", "a+");
Editováno 30.12.2017 17:10
 
Nahoru Odpovědět
30.12.2017 17:10
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka
DarkCoder:30.12.2017 17:57

Tak to je skvělé. Takže už víš kde byla chyba? Doposud jsem se nezabýval ostatními operacemi ve tvém programu. Teď nastal čas a věřím že Tě potěším, když Ti sdělím, že bys teď se mohl zbavit toho duplicitního kódu v příkazu switch. :-)

Jsou nějaké výhody / nevýhody mezi těmito zápisy, jak jsi psal prve?

Pokud víš, že jméno souboru budeš používat na více místech v programu, je dobré používat direktivu preprocesoru #define. Kdyby si chtěl jméno souboru změnit, stačí ho změnit na jednom místě a všechny ostatní odkazy se změní, čímž se můžeš vyhnout chybám souborového systému (a nejen jeho), zejména pokud neděláš ošetření na vrácenou hodnotu. Zde je vidět, proč je třeba tuto hodnotu testovat.

Pokud víš, s jakým souborem budeš pracovat, můžeš ukazatel na soubor inicializovat. Je to ten řádek, který se Ti jeví jako nejjednodušší. Navíc Ti to ušetří trochu psaní textu.

V komplexnějších aplikacích, kde pracuješ s více soubory a kde použitý soubor přiřazuješ až v průběhu na základě nějakých informací, používáš poslední variantu. Tu bych jen z důvodu bezpečnosti trochu rozšířil na následující:

FILE *soubor = NULL;
soubor = fopen("test.txt", "a+");

Je dobré všechny ukazatelové proměnné, které na nic neukazují, takto přiznačit.

Ještě jedna věc. Otevřené soubory, se kterými nepracuješ, zavírej. Jsou pro to minimálně dva důvody. Ten první je že uživatel je omezen množstvím otevřených souborů v jednu chvíli. Ten druhý v okamžiku havárie programu bys mohl nenávratně přijít o spoustu důležitých dat.

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
30.12.2017 17:57
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Jirka
Člen
Avatar
Jirka:30.12.2017 20:17

Ahoj, ono to zkracování je teď spíš trochu kontra. Mám to ke zkoušce a měl bych mít správně 1500 řádků :( Mám ještě co dělat, abych to dohnal i když se svýma schopnostma se k tomu asi ani nepřiblížim... Developer ze mě holt nebude :-)
Budu tam muset ještě dodělat spoustu dalších matematických operací.
Každopádně ti děkuju moc za tvůj čas :-)!
Až se zase někde totálně zaseknu tak zkusím zaspamovat znovu, ono to moc dlouho nepotrvá.
Pěkný zbytek dne.

 
Nahoru Odpovědět
30.12.2017 20:17
Avatar
Jirka
Člen
Avatar
Odpovídá na DarkCoder
Jirka:30.12.2017 20:42

Ahoj, co prosím ještě dělá

fseek(stdin, 0, SEEK_END);

Vygooglil jsem že stdin je standard input, tedy klávesnice.
0 bohužel netuším a SEEK_END zařídí, aby se zapsalo na konec souboru?
Děkuju

 
Nahoru Odpovědět
30.12.2017 20:42
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka
DarkCoder:30.12.2017 22:00

Toto je úloha kde se dá toho opravdu dost vymyslet a bez problému 1500 řádek kódu napsat. Pokud je profesor trochu pozorný a znalý, tak by Ti to rozhodně vytknul. Pokud těch operací budeš mít dost, což asi budeš, kde každá bude vracet výsledek, pak duplicita by byla do očí bijící a nedělalo by to vůbec dobrý dojem.

Pomocí funkce fseek() lze přistupovat k libovlnému místu v souboru. Její prototyp je:

int fseek(FILE * fp, long posun, int pocatek);

stdin je standartní vstup, což je jeden z datových proudů, který je otevřen při spuštění programu. Není to klávesnice, ta je souborem. Standartní datové proudy jsou ukazatele na FILE a mohou být použity tam kde se pracuje s proměnnou typu FILE *.

Parametr pocatek musí být jedním z maker SEEK_SET, SEEK_CUR nebo SEEK_END. Jejich význam je počátek souboru, aktuální pozice v souboru a konec souboru. Parametr posun udává počet bytů od počátku.

A tedy:

fseek(stdin, 0L, SEEK_END);

způsobí nastavení aktuální pozice standartního vstupu na konec a přeskočí tak všechny čekající znaky. Doplněné L ve druhém parametru je z důvodu přebrání správného typu (long).

Nahoru Odpovědět
30.12.2017 22:00
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Petr Balzer
Člen
Avatar
Petr Balzer:31.12.2017 0:55

Nechybí tam vyprázdnění vyrovnávací paměti pomoci fflush(); , když to je výstupní proud??
(já si myslím, že by to tam mělo být).

Nahoru Odpovědět
31.12.2017 0:55
Ono to ještě funguje?!?
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Petr Balzer
DarkCoder:31.12.2017 3:15

Při spuštění programu jsou automaticky otevřeny a připraveny k použití tři datové proudy. Jedná se o standardní vstup (stdin), standardní výstup (stdout) a standardní chyba (stderr). Dále je připojen mezi soubory (klávesnice a diskový soubor) textový datový proud pomocí funkce fopen(). Odpojení datového proudu se provádí a je provedeno pomocí funkce fclose(). Vyprázdnění bufferu se uskutečňuje při vyvolání funkce fclose(), kdy se zapíší na disk automaticky všechna data zbývající v bufferu. Standardní datové proudy jsou obsluhovány interně překladačem, nelze pro ně používat funkce fopen() a fclose() a nesmí se měnit. Pokud datový proud sami neuzavřeme, je automaticky uzavřen po řádném skončení programu. Je ale dobrým zvykem vyprazdňovat vyrovnávací paměť na důležitých místech pomocí fflush(stdout) popř. fflush(NULL).

Nahoru Odpovědět
31.12.2017 3:15
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
DarkCoder:31.12.2017 3:35

Možností je více, pro vyprázdnění bufferu lze použít např.:

while((zapis = getchar()) != '\n' && zapis != EOF);
Nahoru Odpovědět
31.12.2017 3:35
"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 31 zpráv z 31.