Práce se soubory v C – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Práce se soubory v C – C / C++ – Fórum – Programujte.comPráce se soubory v C – C / C++ – Fórum – Programujte.com

 

Siggi
~ Anonymní uživatel
84 příspěvků
9. 12. 2014   #1
-
0
-

Zdravím, mám úkol do prog. v jazyce C a tentokrát jsem totálně beznadějný.

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

int main(void)
{
    int kontrolaPismen;

    printf("3.domaci ukol\nKolik chcete pismen z abecedy? (4-7): ");

    while((kontrolaPismen < 4) || (kontrolaPismen > 7)){
        scanf("%d", &kontrolaPismen);
    }
    char pismeno[kontrolaPismen];

    for(int i = 0; i < kontrolaPismen; i++){
        scanf("%c", &pismeno[i]);
        while((pismeno[i] < 'a') || (pismeno[i] > 'z')){
            scanf("%c", &pismeno[i]);
        }
    }

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

    if(eng == NULL){
        printf("Error: Zadany soubor neexistuje.");
        return 1;
    }
    char slovaVSouboru[50];

    while(fscanf(eng,"%49s", slovaVSouboru) != EOF){
        printf("%s ", slovaVSouboru);

    }

    fclose(eng);


    puts("");
    return 0;
}

Uživatel zadá 4 - 7 pismen abecedy, to mám. Ale za prvé nevím jak to kontrolovat, aby se neopakovali.

Zkoušel jsem to přes 2cykly for, ale bohužel jsem se s tím nepopral. To není ten hlavní problém.

Hlavní je, že mám otevřít soubor(mám) a v tom jsou slova a jsou jich tam stovky slov. 

Problém začíná, kdy po mně chtějí, abych bral slovo po slově a kontroloval, jestli obsahuje všechny písmena, které jsme zadali na začátku. Pak s těma slovy, mám dělat další hokusy pokusy, ale to bych snad zvládl už sám.

Abych to zhrnul. Nevím jak vzít to slovo a rozsekat ho na písmena a kontrolovat ty písmena, či obsahuje.

Někdo radil přes dynamické pole. Koukal jsem na net, ale nic moc.

Pokud vám to není jasné, tak tu je zadání: 

Užívateľ zadá na štandardný vstup 4 až 7 rôznych písmen abecedy. Program testuje ich počet aj rôznosť.

Následne program určí všetky slová zo súboru, ktoré obsahujú všetky zadané písmena. Pre každé takéto slovo vypíše:

slovo

počet písmen slova

slovo odzadu

písmeno, ktoré je v slove obsiahnuté najviackrát (ak je takýchto písmen viac, vypíše ľubovoľné z nich)

---------------> nechci, abyste to za mě dělali, ale chci nakopnout, jak na to. Děkuji za váš čas.

Nahlásit jako SPAM
IP: 147.251.213.–
10. 12. 2014   #2
-
0
-

Jak jsou slova v souboru uložena? Jako v běžné větě nebo oddělená jediným typem oddělovače? Do začátku bych použil statické pole char s vědomím, že je omezená délka zpracovávaného slova. Čtu soubor po jednotlivých znacích a ukládám je do pole, pokud jsem přečetl oddělovač nebo je konec souboru, slovo je načteno celé - za poslední znak uložím 0x00. Pak se slovem mohu pracovat jako s řetězcem nebo jako s polem. Na výskyt písmen ve slově stačí projít řetězec (pole) znak po znaku a druhým cyklem kontrolovat, zda se shoduje se zadanými znaky - druhým cyklem procházíš pole zadaných znaků.

Ještě ke kontrole, zda je každý zadaný znak unikátní. Zadávané znaky ukládej do pole char. Při každém novém znaku projdi již zadané znaky a porovnej, zda právě zadaný není mezi již zadanými, pokud není, ulož ho do pole. Pokud to uložíš jako řetězec - za posledním uloženým znakem v poli bude 0x00, můžeš použít funkci strchr

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:c929:52...–
Siggi
~ Anonymní uživatel
84 příspěvků
10. 12. 2014   #3
-
0
-

V texťáku to je oddělené jen entrem bez teček nebo čárek. Takže ty slova jsou pod sebou.

Mohl bys uvést malý příklad jakto myslíš? 

Nahlásit jako SPAM
IP: 147.251.213.–
Siggi
~ Anonymní uživatel
84 příspěvků
10. 12. 2014   #4
-
0
-

   

for(int i = 0; i < kontrolaPismen; i++){
	for(int j = 0; j < i; j++){
		if(pismeno[i] != pismeno[j]){
			scanf("%c", &pismeno[i]);
     			while((pismeno[i] < 'a') || (pismeno[i] > 'z')){
     				scanf("%c", &pismeno[i]);
			}
		}
     	}
}

Zkoušel jsem něco takového, ale to pak mi nebere první znak, protože tam je ta podmínka a když dám for j = 1, tak to hází náhodný znak, protože ho ještě nevím.

Těch cyklů je tam tolik, že se v tom pomalu ztrácím. A ukládám to jako znaky a ne řetězec.

Nahlásit jako SPAM
IP: 147.251.213.–
10. 12. 2014   #5
-
0
-

pokud jsou oddělené koncem řádku, pak lze ze souboru číst slova funkcí fgets.

Zadávání unikátních znaků - návod: 

	char znaky[8];   //pole umozni ulozit az 7 znaku jako retezec
	int pocet, i;
	char znak;

	//do promenne pocet nactes z klavesnice pocet znaku
	//osetris hodnotu v pocet tak aby splnila zadani 4 az 7
	znaky[0] = 0x00;
	for (i = 0; i < pocet; i++) {
	   do {
	   //precti znak z klavesnice do promenne znak
	   } while (NULL != strchr(znaky, znak))
	   //unikatni znak je pridan na konec retezce
	   znaky[i] = znak;
	   znaky[i+1] = 0;
	}

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:c929:52...–
Siggi
~ Anonymní uživatel
84 příspěvků
10. 12. 2014   #6
-
0
-

Tak to ověření mám, jen by mě zajímalo načpak tam jsou dva řádky:

znaky[0] = 0x00; a znaky[i+1] = 0;   ==  když jsem je zkoušel zakomentovat, fungovalo mi to stejně.

Bralo mi to jen první znak, který nebyl daný + ignorovalo všechny znaky krom anglické abecedy.

    int kontrolaPismen;
    char pismenoAbecedy;

    printf("3.domaci ukol\nKolik chcete pismen z abecedy? (4-7): ");

    while((kontrolaPismen < 4) || (kontrolaPismen > 7)){
        scanf("%d", &kontrolaPismen);
    }
    char znaky[kontrolaPismen];
    //znaky[0] = 0x00;
    printf("Ted zadejte %d znaku: ", kontrolaPismen);

    for(int i = 0; i < kontrolaPismen; i++){
        do{
            scanf("%c", &pismenoAbecedy);
            while((pismenoAbecedy < 'a') || (pismenoAbecedy > 'z')){
                scanf("%c", &pismenoAbecedy);
            }
        }while(NULL != strchr(znaky,pismenoAbecedy));
        znaky[i] = pismenoAbecedy;
       // znaky[i+1] = 0;
    }
Nahlásit jako SPAM
IP: 147.251.213.–
Siggi
~ Anonymní uživatel
84 příspěvků
10. 12. 2014   #7
-
0
-

   

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

    if(eng == NULL){
        printf("Error: Zadany soubor neexistuje.");
        return 1;
    }
    char slovaVSouboru[25], pozpatku[25], opakujiciPismeno;
    int shodaPismene = 0;
    puts("");
    do{
        fgets(slovaVSouboru,25,eng);
        for(int i = 0; i < kontrolaPismen; i++){
            if(strchr(slovaVSouboru,znaky[i]) != NULL)
                shodaPismene++;
        }

        if(shodaPismene == kontrolaPismen){
            int pocetPismen = strlen(slovaVSouboru);
            for(int i = 0; i < pocetPismen; i++){
                pozpatku[i] = slovaVSouboru[pocetPismen-i-1];
            }
            pozpatku[pocetPismen] = '\0';

            printf("Slovo: %s, ma %d pismen, odzadu %s, nejvic opakujici pismeno %c\n", slovaVSouboru, pocetPismen,
                    pozpatku, opakujiciPismeno);
        }
        shodaPismene = 0;
    }while(feof(eng) == NULL); //TADY MAM WARNING (comparison between pointer and 	integer [enabled by default])

    fclose(eng);

Připojen obrázek.

Přitom to má být vše na jednom řádku: slovo, počet, odzadu a opak. písmeno
    strlen mi taky počítá o znak navíc až u toho poslední, tam počítá správně

A stím počítáním nejvíc opakujícího písmene zatím taky nějak nevím.

Jinak pokud by šel ten kód nějak z jednodušit, jestli to nemám nějak moc krkolomně složité.

Nahlásit jako SPAM
IP: 147.251.213.–
11. 12. 2014   #8
-
0
-

znaky[0] = 0x00; a znaky[i+1] = 0;   ==  když jsem je zkoušel zakomentovat, fungovalo mi to stejně.

protože jsi měl kliku a v neinicializované paměti bylo náhodou 0x00. Normálně platí: Co je v neinicializované paměti neví ani Bill Gates a Bůh ti to neřekne. Funkce strchr pracuje s řetězcem, ten je ukončen znakem s hodnotou 0x00. Do pole ukládáš znaky, aby z toho byl plnohodnotný řetězec, musíš za poslední uložený znak uložit 0x00. Pokud to neuděláš, strchr projede nejen tvoje znaky, ale i smetí v paměti za nimi dokud nenajde 0x00. Aby strchr pracovala správně i při načtení prvního znaku, před načtením jakéhokoliv znaku se nastaví prázdný řetězec, proto znaky[0] = 0x00;

Pokud to má bít jen písmeno abecedy, není nutná další cyklus, stačí složitějšší podmínka: 

do {

}while ( ((pismeno >= 'a') && (pismeno <= z)) || (NULL != strchr(znaky,pismeno)) )

Vysvětlení, proč jen anglická, najdeš v uspořádání ASCII tabulky. V rozsahu a až z jsou jen anglická písmena. Národní znaky jsou v ASCII tabulce v rozsahu 128 - 255. Česká abeceda tedy znamená složitější podmínku. Možná kvůli přehlednosti by bylo dobré si udělat funkci nebo makro int ZnakJePismeno()

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:e5d7:f2...–
Siggi
~ Anonymní uživatel
84 příspěvků
11. 12. 2014   #9
-
0
-

Nene já vím proč anglická abeceda, to už jsem jen ukazoval na fakt, že to správně pracuje.
Díky za vysvětlení těch dvou řádků, ale víc mě trápí ten příspěvek č. 7.

Nahlásit jako SPAM
IP: 147.251.213.–
11. 12. 2014   #10
-
0
-

Prohlídni si vstupní soubor binárně. Slova asi budou oddělená koncem řádku - "dvojznakem" CR LF. Pak se podívej na slovo přečtené ze souboru jestli na konci nezůstal některý z nich, tedy CR nebo LF.

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:e5d7:f2...–
Siggi
~ Anonymní uživatel
84 příspěvků
11. 12. 2014   #11
-
0
-

Tak jsem zjistil, že fgets bere i bílý znak do paměti, nebo-li u mě enter, ale místo toho fscanf pracuje stejně, ale bílý znak neuchovává. Takže už mi to vypisuje krásně na řádek.

Teď se poprat s posledním a to spočítat a vyhodnotit nejvíc opakující se písmeno. Kdyby to bylo číslo, tak je
to mnohem jednodušší.
Nějaký nápad, jak na to?

Nahlásit jako SPAM
IP: 147.251.213.–
11. 12. 2014   #12
-
0
-

Pro každý písmeno počitadlo a určit, které počitadlo má nejvíc

hu

Nahlásit jako SPAM
IP: 193.86.81.–
Michal
~ Anonymní uživatel
683 příspěvků
11. 12. 2014   #13
-
0
-

Siggi, ako vyzerá ten kód zatial? skopči

Nahlásit jako SPAM
IP: 147.251.209.–
Siggi
~ Anonymní uživatel
84 příspěvků
11. 12. 2014   #14
-
0
-

#13 Michal 

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

int main(void)
{
    int kontrolaPismen;
    char pismenoAbecedy;

    printf("3.domaci ukol\nKolik chcete pismen z abecedy? (4-7): ");

    while((kontrolaPismen < 4) || (kontrolaPismen > 7)){
        scanf("%d", &kontrolaPismen);
    }
    char znaky[kontrolaPismen];

    printf("Ted zadejte %d znaku: ", kontrolaPismen);

    for(int i = 0; i < kontrolaPismen; i++){
        do{
            scanf("%c", &pismenoAbecedy);
            while((pismenoAbecedy < 'a') || (pismenoAbecedy > 'z')){
                scanf("%c", &pismenoAbecedy);
            }
        }while(NULL != strchr(znaky,pismenoAbecedy));
        znaky[i] = pismenoAbecedy;
    }

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

    if(eng == NULL){
        printf("Error: Zadany soubor neexistuje.");
        return 1;
    }

    char slovaVSouboru[25], pozpatku[25], opakujiciPismeno;
    int shodaPismene = 0;
    printf("\nSlovo -> Pocet pismen -> Odzadu -> Nejvic se opakujici pismeno\n\n");

    do{
        fscanf(eng, "%s", slovaVSouboru);
        for(int i = 0; i < kontrolaPismen; i++){
            if(strchr(slovaVSouboru,znaky[i]) != NULL)
                shodaPismene++;
        }

        if(shodaPismene == kontrolaPismen){
            int pocetPismen = strlen(slovaVSouboru);
            for(int i = 0; i < pocetPismen; i++){
                pozpatku[i] = slovaVSouboru[pocetPismen-i-1];
            }
            pozpatku[pocetPismen] = '\0';

            printf("%20s -> %2d -> %20s -> %c\n", slovaVSouboru, pocetPismen, pozpatku, opakujiciPismeno);
        }

        shodaPismene = 0;
    }while(feof(eng) == NULL);

    fclose(eng);

    puts("");
    return 0;
}

Ten feof budu muset změnit na eof, bo tam mám warning.

Nahlásit jako SPAM
IP: 147.251.213.–
Siggi
~ Anonymní uživatel
84 příspěvků
15. 12. 2014   #15
-
0
-

Tak učitel odvolal psání toho největšího znaku, takže už to nemusím dělat, nicméně stejnak jsem nebyl schopen to udělat. Kdyby byl někdo hodný a ukázal mi ten kód měl vypadat; byl by moc hodný.

Dneska jsem odeslal ten úkol učiteli, tak uvidím.

Nahlásit jako SPAM
IP: 147.251.213.–
16. 12. 2014   #16
-
0
-

#15 Siggi
Zkus to cvičně naprogramovat: uživatel zadává 4 - 7 písmen (to máš) Ke každému z nich si uděláš počitadlo výskytu. Takže k poli znaků máš pole intů se stejným počtem prvků. Druhá možnost je mít strukturu s položkami znak a počitadlo pro každý zadaný znak. Pak budeš mít pole struktur. Před načtením každého slova počitadla vynuluješ (cyklus for). Při každém nalezení písmena ve slově inkrementuješ počitadlo písmena, musíš projít celé slovo znak po znaku. Po tom, co projdeš celé slovo, vybereš počítadlo, které má nejvyšší hodnotu (hledání maxima, zde musíš evidovat i znak, který má maximum), to vypíšeš spolu s písmenem kterému počitadlo patří. V případě, že více znaků má největší výskyt, tento jednoduchý algoritmus vypíše ten znak, který byl zadán nejdříve - zadání to splňuje.

Možná optimalizace: v cyklech, které prohledávají slovo na výskyt písmen současně inkrementovat počitadla výskytu písmen a vytvářet "mezivýsledek" maxima. S tím si můžeš pohrát až potom, co se ti podaří to realizovat jak bylo popsáno výše.

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:cc55:7d...–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 11 hostů

Podobná vlákna

Práce se soubory — založil polonium

Práce se soubory — založil Mára

Práce se soubory — založil Polarski

Práce se soubory — založil Borisek

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý