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

Tvůrce

Zobrazeno 50 zpráv z 102.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.
VUT FIT prvák?
Letos máte ten projekt nějaký jednoduchý.. Jinak bacha na používání jakéhokoliv cizího kódu.. Plagiátorství může být docela dost velký průser..
Co se týče implementace, tak se prvně zamysli nad tím, jak bys mohl definovat formát těch jednotlivých možností. Otázka - máte zakázané nějaké funkce?
doporučuji začít mainem a pak prostě zjišťovat co by to mohlo být. Začít nejkonktrétnějšími.
Jojo, FITko
Musím nějak rozlišit v těle programu rozlišit, že když se jedná o
zapnutí programu bez argumentu, aby se zapnul například
int main()
{
}
a pokud budou zadány argumenty, tak nějaká jiná metoda?
Co se týče omezení, nemsíme používat hlavičkový soubor string.h, volání z rodiny malloc a free - práce s dynamickou pamětí, a potom volání z rodiny fopen, fclose, fscanf, ... - práce se soubory (dočasnými) není v tomto projektu žádoucí
nie, stále ide o všetko v main, avšak musíš mu dať argumenty:
int main(int argc, char **argv)
a v prípade, že argumenty budeš brať pri zapnutí programu, nebudeš spracúvať text pomocou scanf, lebo jednotlivé vstupy budú už v argumente funkcie main char **argv
Takže můžu na začátku mainu dát třeba podmínku
if(argc)
...
a vykonat tedy program pokud jsou zadané argumenty při spuštění a potom
dám větev else, která bude mít totožné funkce na test čísla, palindromu
atd, ale jen pro scanf?
takže spíš to nebude else ale
if(!argc)
{
}
argc je vždy minimálně 1 - první argument (v argv[0]) je název programu.
Jinak alternativa k scanf je sscanf, která bere vstup ze stringu (přesněji pole znaků zakončené \0). Zapřemýšlel bych ale, jestli by nebylo lepší použít getc a řešit to po znacích (možná konečný automat?).
to bude asi jednoduchšie už je to asi zvyk, na všetko vyhľadávať anglické stránky
Joo, to je dobrý, tam jsem už koukal dřív
Teď mě napadá, existují už nějaké "hotové" funkce, které když napíšu
tak tím programu přímo říkám, že chci vědět, zda třeba argv[i] je
číslo,znak nebo datum?
Jsme v C...
Ne nadarmo se používá na výuku - skoro všechno si musíš udělat sám A kdybys měl takové fce, tak by
ten projekt byl na půl hodiny práce.. Na FITu se učí programovat, ne jak
poskládat už hotové celky
mrkni ale do ctype.h - tam jsou makra jako isdigit(), isalpha() apod. Pracují ovšem s jediným znakem, ne stringem.
Tu to mas na tanieri:http://skolka-jazyka-c.freespace.sk/viewtopic.php?…
Asi zase triviální dotaz, ale lze bez knihovny string.h nějak každý argument rozložit na znaky, které potom porovnám, zda to jsou čísla, písmena atd..? program mi nechce běžet, protože funkce z ctype.h jsou na znaky a já tomu vkládám celé řetězce, byť to má jeden znak..
máš dvojrozmetné pole znakov - keď použiješ argv[i] - tak berieš celý "riadok" znakov. Ak chceš iba jeden znak, musíš použiť toto: argv[i][j]
jen pro ujasnění, celou dobu beru to, že jakoby argc je počet slov
(argumentu) které zadám do terminálu a argv[i] potom reprezentuje každý
argument.. jinak s tím přidáním "j" bude určitě správná cesta jen tam dám další cyklus for
Akorát je třeba počítat s tím, že první argument je název - takže začneš od i = 1 a jedeš dokud je i < argc..
Nemôžeš použiť funkciu strlen() z knižnice string.h, tak si ju napíšeš, napríklad:
#include <stdio.h>
int strlen(char *slovo)
{
int velkost = 0;
while (*slovo++ != '\0')
velkost++;
return velkost;
}
int main()
{
char *slovo = "125485";
printf("%d\n", strlen(slovo));
return 0;
}
Malý nástrel:
#include <stdio.h>
#include <stdlib.h>
/** vrati pocet znakov v retazci */
int strlen(char *slovo)
{
int velkost = 0;
while (*slovo++ != '\0')
velkost++;
return velkost;
}
/** skontroluje ci je to cele cislo, ak ano, vrati ho, ank nie, vrati 0 */
int je_cislo(char *slovo)
{
int i, vysledok = 0;
char buffer[128] = "";
for (i = 0; i < strlen(slovo); i++) {
if (isdigit(slovo[i]))
buffer[i] = slovo[i];
else {
break;
}
}
if (strlen(buffer) == strlen(slovo)) {
buffer[i + 1] = 0;
vysledok = atoi(buffer);
}
return vysledok;
}
int main()
{
char *slovo1 = "125485", *slovo2 = "125,485";
printf("Slovo %s je cele cislo %d.\n", slovo1, je_cislo(slovo1));
printf("Slovo %s je cele cislo %d.\n", slovo2, je_cislo(slovo2));
return 0;
}
K čemu strlen?
for (i = 0; slovo[i] != '\0'; i++) {
Taky je naprosto zbytečné používat nějaký buffer a atoi... Jo a obecně používat buffer o pevné délce je problém - nevíš, jak dlouhé to může být.
int je_cislo(char *slovo)
{
for (int i = 0; slovo[i] != '\0'; i++) {
if (!isdigit(slovo[i])
return 0; // false
}
return 1; // true
}
Dá se celej ten program napsat pouze v mainu? Nebo to je sebevražda? A délku řetězce znát nepotřebuju, abych určil číslo, nebo snad jo?
Co dělám špatně, když se mi nedaří uložit hodnotu daného argumentu do proměnné číslo, pokud to číslo je?
for(i=1;i < argc; i++)
{
for(j=0; argv[i][j] != '\0'; j++)
{
if(isdigit(argv[i][j]))
{
cislo=argv[i];
}
}
Potom tam je podmínka, že jestli je číslo, tak se provede test na prvočíslo, ale to už by fungovat mělo..
Ja si robim testy, teda vypisal by som si vysledok casti kodu.
cislo je int?
Doporučuji se trochu zaměřit na teorii polí a stringů v C.. argv[i] je první znak v i-tém argumentu. Takže ti to do cislo vždy dá první znak. Ale nechápu, co tím sleduješ..??
Je to ASCII znak.. Jestli s tím chceš pracovat jako s číslem, musíš to na číslo převést - doufám, že víš, jak se ascii znak číslice převádí na číslo.. Jestli ne, tak doporučuji urychleně studovat (např. Učebnice jazyka C od Herouta je dobrá).
Pokud je cislo typu int, tak se ti tam neuloží požadované číslo, ale ASCII číslo cisla, 0 má třeba hodnotu 0x30.
Myslim, ze toto
cislo=argv[i];
nebude fungovat.
Asi je treba to prekopirovat po jednom znaku a ukoncit znakom '\0'.
David mas pravdu, zbytocne som to komplikoval.
argv je snad celý argument, dokud není mezera, ne? protože když procházím argument znak po znaku tak [i] značí číslo argumentu a [j] potom pořadí znaku v celém řetězci, ne?
Takže snazší jak převod je nezavádět si vůbec cislo typu int?
Délku řetězce znát nepotřebuješ.. Každý program se dá napsat jen do
mainu.. Ale smrčka by ti utrhl hlavu..
A navíc by se v tom nedalo vyznat. Pravidlo zní - kdykoliv se ti někde vyskytne stejný blok kódu vícekrát, udělej z toho funkci.
Sorry, neuvedomil som si, ze mas len vyhodnotit druh slova. Jasne, ze nepotrebujes nic prevadzat.
argv je pole argumentů oddělených mezerami, ano. A s i a j máš také
pravdu.. Proč to tedy v kódu tak nemáš?
Převod je jednoduchý.. A na ověřování prvočísla to asi budeš potřebovat.. Takže převést budeš muset. Jestli máte povoleno strtol, tak použij to, jinak si to udělej ručně. ze znaku uděláš číslo takto:
cislo = argv[i][j] - '0';
Pokud chceš převést řetězec, tak nejjednodušší je toto:
cislo = cislo*10 + (argv[i][j] - '0');
(samozřejmě v cyklu - zkontroluješ zda je konkrétní znak číslice a provedeš tenhle převod. když narazíš na nečíslici, tak skončíš a vrátíš chybu)
Nějak jsem to aspon trošku dokázal spustit, ale i tak - nedokáže to vypsat to číslo a na konec to ještě hodí tuto chybu: Neoprávněný přístup do paměti (SIGSEGV)
Tohle je prozatimní kód, ve kterém musím mít nějakou chybu, ale asi i
díky malým zkušenostem ji nenajdu
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
int i;
int j;
char *znak;
char *cislice;
int cislo;
int prvocislo;
if(argc > 1)
{
for(i=1;i < argc; i++)
{
for(j=0; argv[i][j] != '\0'; j++)
{
if(isdigit(argv[i][j]))
{
cislo=cislo*10 + (argv[i][j] - '0');
printf("cislo: \n",&cislo);
}
}}
if(cislo)
{
for(i=2; i < cislo; i++)
{
if(cislo % i)
prvocislo=0;
break;
}
if(prvocislo)
printf("Number: %s (prvocislo) \n",cislo);
else
printf("Number: %s \n",cislo);
}
}
Máte nějaký nápady někdo?
Vím že je to moje blbost, ale měl jsem kopu věcí a najednou musím rychle
tenhle první program splácat a odevzdat..
Nějak jsem to aspon trošku dokázal spustit, ale i tak - nedokáže to vypsat to číslo a na konec to ještě hodí tuto chybu: Neoprávněný přístup do paměti (SIGSEGV)
Tohle je prozatimní kód, ve kterém musím mít nějakou chybu, ale asi i
díky malým zkušenostem ji nenajdu
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
int i;
int j;
char *znak;
char *cislice;
int cislo;
int prvocislo;
if(argc > 1)
{
for(i=1;i < argc; i++)
{
for(j=0; argv[i][j] != '\0'; j++)
{
if(isdigit(argv[i][j]))
{
cislo=cislo*10 + (argv[i][j] - '0');
printf("cislo: \n",&cislo);
}
}}
if(cislo)
{
for(i=2; i < cislo; i++)
{
if(cislo % i)
prvocislo=0;
break;
}
if(prvocislo)
printf("Number: %s (prvocislo) \n",cislo);
else
printf("Number: %s \n",cislo);
}
}
Máte nějaký nápady někdo?
Vím že je to moje blbost, ale měl jsem kopu věcí a najednou musím rychle
tenhle první program splácat a odevzdat..
printf("Cislo: %d", &cislo);
To by mělo vyřešit problém s nevypsáním čísla
A taky bych raději dal na začátku do cisla nulu.
co má být tady toto?
printf("cislo: \n",&cislo);
&cislo ti vrátí adresu proměnné cislo a navíc printf neříkáš, že bys chtěl vypisovat proměnnou..
printf("cislo: %d\n",cislo);
Jinak tohle ti bude vypisovat hodnotu proměnné cislo po každém kroku převodu..
Další zásadní problém je, že nikde neinicializuješ prvocislo, takže
je možné, že se do něj budeš dívat a bude tam blbost.
Je třeba int prvocislo = 1;
Jo a to stejné s cislo.. Tu k němu přistupuješ, aniž by tam byla rozumná hodnota..
cislo=cislo*10...;
int cislo = 0; // treba deklarovat takto
Tu ti chybí závorky - break se tak provede pokaždé..
if(cislo % i)
{
prvocislo=0;
break;
}
A tu se snažíš vypisovat int jako string:
printf("Number: %s \n",cislo);
printf("Number: %d \n",cislo); // spravne
Jo a ještě:
if(cislo % i)
if(cislo % i == 0) // takhle
Modulo vrací nulu, když je zbytek nula (tedy cislo je delitelne i).
Ještě bys měl mít na začátku
int prvocislo = 1;
Když ho kontroluješ jestli není.
No fakt že jo, dělalo tam spoustu věcí neplechu, díky Aspon už mi část toho funguje..
jen mi to ještě lepí všechny argumenty jako jeden.. když napíšu ./proj1
857 tak to správně vypíše že se jedná o prvočíslo, ale když napíšu
./proj1 8 57 tak to znovu napíše že 857 je prvočíslo.. řekl bych, že
všechno dohromady lepím zde
if(isdigit(argv[i][j]))
{
cislo=cislo*10 + (argv[i][j] - '0');
}
nebo ne?
Proč se mi to ukládá jako jedno číslo, když jsou argumenty odděleny
mezerama?
Po každém průchodu musíš číslo přirozeně vynulovat...
a tady v tomto cyklu bys to měl mít celé - včetně ověření prvočísla a vypsání výsledku:
for(i=1;i < argc; i++)
{
...
}
Nejlepší by bylo to pak rozsekat na funkce
jojo, na ten cyklus jsem hned po odeslání komentáře přišel, ale
vynulovat jsem to zapomněl Já to asi nechám až na příští projekt to rozsekávání na
funkce, te´d bych se v tom ještě zamotal..
Koho máš jako cvičícího?
Každopádně fakt doporučuji si máknout.. Máš půlku semestru a nevím,
jak bys teď byl úspěšný v psaní něčeho podobného na papír.. Pujč si
tu učebnici, zahoď IDE a programuj v texťáku a každý den aspoň několik
hodin denně programuj.. Tyhle základy se budeš muset naučit
Na cvika mám Očenáška.
Já vím že čas kvapí, je to boj no.. Jinak k tomu psaní na papír - to se
taky v prváku dělá? Třeba jako písemka?
jinak ten projekt dělám normálně v terminálu ve Vi editoru. Rozsekám to teď na ty funkce, ať je to snazší a přehlednější..
Za vim máš mé úznání..
No celý bakalář se dělají písemné zkoušky.. Je příliš mnoho studentů, aby byli zkoušeni ústně. Prakticky bys měl být schopen sednout a napsat program, který by měl fungovat. Nějaké drobné syntaktické chyby se tolik neřeší, ale určitě za ně jdou body dolů.
Z IZP je zkouška ve formě několika otázek typu "co tento kód udělá",
pak nějaké deklarace většinou - "nadeklaruj ukazatel na pole ukazatelů na
funkce vracející int" (toto je teda extrémní zadání.. bývají
jednodušší
Dále tam najdeš nějaké zadání typu: "napiš program dělající xyz"
nebo "doplň tělo funkce tak, aby ...." Plus i nějaké teoretické otázky..
Takže radím u smrčky dávat pozor
Ale zas abych tě nevystrašil moc, tak průměrný programátor to v klidu
dá na to E. Já jsem tehdy uměl o dost méně než teď a na zkoušku se mi
nechtělo připravovat, takže jsem to dal na D..
To vím že je všechno písemně, což mě trošku uklidňuje..
Chtěl jsem nějaký lepší editor na terminálu než vim, který nám
ukazují, ale žádný jiný z asi 15 co jsem našel není na merlinovi.
Když se naučíš používat vim (zabere pár hodin), tak je to pak
jednoznačně nejlepší editor..
Jinak to klidně můžeš dělat i u sebe (jestli linux nemáš jako hlavní OS nebo aspoň dualboot, tak stejně to tak budeš muset udělat příští semestr, kde se v něm bude dělat hodně.. A merlin bývá okolo deadline projektů dosti zasekaný, takže se na něm blbě tvoří.
Tak deadline je až někdy za týden, tak zatím to teď jede dobře..
Ještě mě teď pořád trápí ten cyklus, že vypisuje jen jedno číslo a ne všechny z argumentů.. a to vždycky to cislo dám rovno nule, ale to se mi nezdá že by to mělo uplně na 100% fungovat..
for(i=1;i < argc; i++)
{
for(j=0; argv[i][j] != '\0'; j++)
{
if(isdigit(argv[i][j]))
{
cislo=cislo*10 + (argv[i][j] - '0');
}
}
if(cislo)
{
for(i=2; i < cislo; i++)
{
if(cislo % i==0)
{
prvocislo=0;
break;
}
}
if(prvocislo){
printf("Number: %d (prvocislo) \n",cislo);
cislo=0;}
else{
printf("Number: %d \n",cislo);
cislo=0;}
}
}
A když zadám více argumentů (okolo 6) tak to zacyklí celej program a
furt dokola to vypisuje 1-3 čísla (argumenty).. jsem z toho úplně zmatenej
No tohle určitě není moc dobré:
for(i=1;i < argc; i++)
for(i=2; i < cislo; i++)
Zobrazeno 50 zpráv z 102.