Jestli si to dobře pamatuju (za což neručím), dědí se rozhraní (interface) ze základního typu iinterface a ne tobject. Čili dva naprosto nepříbuzné rodokmeny.
Příspěvky odeslané z IP adresy 85.132.158.–
Přesně tak - jinak než překopírováním s vynecháním mazané položky to nejde.
Pokud ale máš opravdu velký soubor, který nechceš nebo nemůžeš pořád celý přepisovat, můžeš v něm tu jednu položku přepsat a dát jí nějakou hodnotu, kterou budeš považovat za "smazáno". Udělá se to tak, že před otevřením souboru nastavíš předdefinovanou globální proměnnou Filemode na hodnotu 2 (tj. čtení i zápis, je to v helpu; myslím, že ta dvojka je dokonce defaultní nastavení). Pak soubor otevřeš Resetem, příkazem Seek najedeš na tu xtou položku (číslují se od nuly) a příkazem Write ji přepíšeš.
Trochu si tím zkomplikuješ čtení souboru, protože budeš muset rozlišovat platné a "prázdné" položky podle hodnoty, ale u několikamegabytových databází to vychází jako výhodnější varianta.
To martin :
Pole čísel deklaruješ pomocí konstrukce array[min_index..max_index] of nějaký číselný typ, třeba word.
Číslo HS přečteš z klávesnice příkazem Readln.
Soubor připravíš ke čtení příkazy Assign a Reset. Načítání čísel vyřešíš pomocí příkazu Read v cyklu typu While (nebo Repeat, pokud si jsi jist, že soubor není prázdný) s ukončovací podmínkou Eof(soubor). V nějaké pomocné proměnné si pamatuj, kolik čísel jsi přečetl (na začátku ji vynuluj a při každém Read ji zvyš o 1). Nakonec soubor zavři příkazem Close.
Hledání sekvencí:
Levým ukazováčkem si ukaž na první číslo v poli.
Cyklus 1:
Pravým ukazováčkem ukaž na stejné místo, na které ukazuje levý.
Zapamatuj si, že součet je zatím 0.
Teď Cyklus 2 (While nebo Repeat, celý je uvnitř Cyklu 1):
- K součtu přičti číslo, na které ukazuje pravý ukazováček.
- Pokud se součet rovná HS, vypiš na obrazovku čísla od toho pod levým ukazováčkem po to pod pravým ukazováčkem (cyklus typu For, příkazy Write a Writeln). Pokud se nerovná, nedělej nic.
- Pravý ukazováček posuň o jedno číslo dál.
Cyklus 2 ukonči, pokud už je součet větší než HS nebo pokud se pravý ukazováček dostal za poslední číslo v poli.
Levý ukazováček přesuň za pravý.
Cyklus 1 ukonči, když se levý ukazováček dostane za poslední číslo v poli.
Teď si místo poloh ukazováčků představ indexy (pořadová čísla prvků pole) a pro ukládání součtu si deklaruj pomocnou proměnnou a už by neměl být problém přeložit to do pascalštiny :-) (a kdyby jo, hoď sem svůj zdroják a napiš, kde přesně se ti objevuje jaká chyba).
Zkusím ten algoritmus popsat trochu jinými slovy.
Procedura:
Vstupní parametry: indexy Začátek a Konec, které určují, jaký úsek pole chci třídit.
Lokální proměnné: pomocné indexy Levý, Pravý a Pivot.
Index Levý umístím na pozici Začátek, Pravý na Konec a Pivot na (Začátek+Konec) div 2 (tedy někam do poloviny tříděného úseku).
Cyklus:
Levý index postupně zvětšuji (tj. posouvám v poli doprava) do okamžiku, kdy buď narazím na prvek větší než prvek na indexu Pivot nebo dokud s Levým nedojedu až k Pivotu (takže Levý buď ukazuje na ten špatně umístěný prvek, nebo se rovná Pivotu).
To samé s Pravým, jenom posouvám doleva a ne doprava.
Pokud Levý<>Pravý, vyměním prvek na pozici Levého s prvkem na pozici Pravého (indexy Levý a Pravý se nemění). Navíc pokud Pivot=Levý, tak Pivot:=Pravý nebo pokud Pivot=Pravý, tak Pivot:=Levý (takže Pivot ukazuje stále na stejný prvek).
Celý tenhle Cyklus opakuji až do okamžiku, kdy Levý=Pravý=Pivot.
Pokud jsou před Pivotem ještě alespoň 2 prvky (tedy Pivot-Začátek>=2), zavolám rekurzivně tuhle proceduru na úsek Začátek..Pivot-1.
Pokud jsou za Pivotem ještě alespoň 2 prvky (tedy Konec-Pivot>=2), zavolám rekurzivně tuhle proceduru na úsek Pivot+1..Konec.
Konec procedury.
Nejdůležitější je:
- Index Levý musí být vždy vlevo od Pravého nebo nanejvýš shodný.
- Index Pivot musí ukazovat stále na stejný prvek (pokud se ten prvek přemístí, přemístí se tedy i Pivot).
- Pivot musí být neustále mezi Levým a Pravým nebo nanejvýš shodný s některým z nich.
- Po doběhnutí jednoho Cyklu jsou vlevo od Pivotu prvky menší nebo stejné než prvek na Pivotu, vpravo větší nebo stejné.
Fungovat to bude i v případě, že Pivot skončí někde na kraji pole - v takovém případě se pak procedura rekurzivně zavolá jenom na tu stranu, na které ještě něco zbylo (vliv to má pouze na efektivitu, ne na proveditelnost - ta je vždycky zaručená).
Rychlost výpočtů na rychlosti počítače pochopitelně závisí, časomíra se dá udělat tak, aby nezávisela - buď standardními funkcemi Getdate a Gettime (přesnost na setinu vteřiny) nebo vlastními prostředky přes přerušení časovače (např. http://mircosoft.ic.cz/download/CAS.PAS).
To evandar : Něco pro inspiraci: http://mircosoft.ic.cz/download/kviksort.zip. Když si ten program spustíš, uvidíš krok po kroku, jak algoritmus pracuje (a je tam i zdroják).
To Yety : Jak jsem psal už dříve - zadávat vzdálenost od Slunce (proměnná Slong) v typu integer je kravina, protože má moc malý rozsah. Takže při zadání miliardových hodnot zaručeně přeteče a vypočítá se nesmysl.
Mimochodem, nebylo by jednodušší vypočítat si převodní konstantu mezi km a pc a prostě jí zadané číslo vynásobit?
Near je blízký model volání, far vzdálený. Near se defaultně používá u procedur definovaných v programu a u procedur pouze v implementační části jednotky; far u těch, které mají hlavičku uvedenou v části interface.
Nucené volání všeho jako far se dá zařídit direktivou {$F+}. Místní procedury, u kterých by bylo daleké volání zbytečné, pak můžeš na blízké změnit slovem Near.
Rozdíl mezi near a far je takový, že při blízkém volání je segment stejný jako segment volajícího boku, tj. změní se jenom registr IP, ne CS. Při dalekém volání se volá z jiných segmentů, takže se mění i CS (a je to o pár taktů procesoru pomalejší). To platí pro 16bitový real mód. Ve 32bitovém režimu se všechno volá 32bitově, žádné segmenty se tam nevyskytují, takže není co řešit.
Jo, a možná by se ti mohl hodit tenhle text: http://mircosoft.ic.cz/texty/UKAZ.TXT.
To Anet : Aby bylo jasno, tohle fórum není určeno k tomu, aby se tu za kohokoli psaly domácí úkoly (i když to samozřejmě není zakázané). V optimálním případě by to tu mělo probíhat tak, že někdo se na něco zeptá a ostatní mu to vysvětlí tak, že to pochopí a příslušný úkol napíše sám a z diskuse potom budou mít užitek všichni ostatní, co přijdou později se stejným problémem.
Jestli jste, jak píšeš, celý rok probírali programování a doteďka je pro tebe nadlidský úkol napsat všeobecně jakýkoli program, zřejmě jsi celou tu dobu ve škole spala a na úspěšné zakončení předmětu IMHO nemáš nárok (tu známku máš dostat ty, ne my).
Chápu, že to zní dost drsně (neber to prosím jako útok na tebe nebo tak něco). Taky jsem někdy začínal. A i mě pár lidí poslalo přečíst si nějakou učebnici pro začátečníky a nenechávat za sebe pracovat ostatní.
>drobas:
Jestli chceš dokázat, že každé sudé číslo >2 se dá rozložit na součet dvou prvočísel, tak potřebuješ následující:
1) Zjistit, jestli je dané číslo větší než 2.
2) Zjistit, jestli je sudé.
3) For-cyklem projet od 1 do poloviny toho čísla. V každé iteraci si číslo rozložit na součet řídící proměnné cyklu a zbytek (číslo mínus ta proměnná) a zjistit, jestli jsou to obě prvočísla. Pokud ano, bingo, věta platí a cyklus může skončit.
4) Zjišťování, jestli jde o prvočíslo, se dá udělat buď dalším for-cyklem (testuj dělitelnost od 2 do poloviny toho čísla; jestli není dělitelné ničím, je to prvočíslo) nebo na to možná existuje nějaký patentní vzoreček, který ale neznám :-).
Ať na to koukám jak chci, nevidím, kde by se v tom dalo využít nějaké pole...
Jinak v real módu (TP, BP) je velikost polí a proměnných obecně, jak statických, tak dynamických, omezena na 64 KB. Jeden longint nebo pointer má 4 B, boolean 1 B. 1 KB = 1024 B, vyděl si to sám, vyjde ti maximální délka. Delší struktury jdou teoreticky udělat pomocí spojového seznamu, ale ty zabírají dost paměti (z těch základních 640 KB), takže prakticky se moc nehodí.
64 KB limit se dá překročit v protected módu (FP, Delphi, BP tuším taky, ale alokaci musíš řešit vlastními prostředky).
Zkus nějak upřesnit pojem "problém s řazením jmen a startovních čísel". Ať na to koukám jak chci důkladně, žádnou chybu nevidím - jména i startovní čísla jsou ošetřena správně. Je pravda, že s jedním polem recordů by to bylo přehlednější než se třemi oddělenými poli, ale to je jenom kosmetický detail bez vlivu na funkci.
Teď mě napadá... nemyslel jsi tím problémem náhodou to, že když má několik závodníků stejný počet bodů, tak bys je chtěl mít seřazené ještě podle startovního čísla nebo jména? Na to bys musel použít ještě jeden řadicí cyklus; to, co tam máš teď, ti řadí jenom podle počtu bodů.
Přes Gettime by to šlo tak, že si všechno převedeš na setiny sekundy, aby se s tím líp počítalo:
setiny:=setiny+100*sekundy+100*60*minuty+100*60*60*hodiny plus případně ještě datum z Getdate, jestli to chceš hrát přes půlnoc :-).
V programu od Laacy bys čtení Gettime a výpočet setin dal tam, kde je to ...:=meml[...]. n by pak byl počet setin.
To lama : Tuhle hlášku způsobuje většinou to, že nemáš BGI soubor (obvykle EGAVGA.BGI) ve stejném adresáři jako je ten, ve kterém ti běží program. Jestli ho spouštíš z IDE (Ctrl+F9), tak se jako aktuální adresář bere ten, ve kterém se nachází TURBO.EXE, takže jestli BGI nejsou přímo tady, přesuň je sem. Taky je možné, že máš nějak divně nastavené adresáře v Options - Directories, tak to zkontroluj.
Nechápu, co myslíš těmi okny (okno s programem, okno s grafikou a tak). Program normálně jede na celé obrazovce v grafickém režimu; jestli ne, tak je něco špatně (alt+enter jsi zkoušel?). Píšeš to v TP nebo v čem? Jestli v TP a máš dva monitory, tak na jednom máš vývojové prostředí (editor zdrojáku), a na druhém ti běží program se vším všudy, ale o klávesnici by se hádat neměly, ne?
Potřeboval bych poradit, už si nevím rady. Potřeboval bych v Pythonu přes XMPP přijímat zprávy a dále je zpracovávat, to by problem nebyl. Problem nastane až tehdy když jsou ve zprave znaky s diakritikou ěščřžýáíéůú. Řetězec který se nachází v proměnné tak nelze dále zpracovávat. Soubor se scriptem je uložen v UTF-8. Přečetl jsem i kdejakou dokumentaci ale stale nic. Moc prosím o jakoukoliv radu
Chybove hlaseni:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
Script:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import site
import xmpp
import os
import signal
import time
def messageCB(conn,msg):
zprava = str(msg.getBody())
print zprava
def StepOn(conn):
try:
conn.Process(1)
except KeyboardInterrupt:
return 0
return 1
def GoOn(conn):
while StepOn(conn):
pass
def main():
jid="abc@abc"
pwd="abc"
jid=xmpp.protocol.JID(jid)
cl = xmpp.Client(jid.getDomain(), debug=[])
if cl.connect() == "":
print "not connected"
sys.exit(0)
if cl.auth(jid.getNode(),pwd) == None:
print "authentication failed"
sys.exit(0)
cl.RegisterHandler('message', messageCB)
cl.sendInitPresence()
GoOn(cl)
main()
O slovech už se tu psalo dostkrát, stačí pohledat: počítání slov v řetězci http://programujte.com/index.php?akce=diskuze&kam=vlakno&tema=9177-pocet-slov-oddelenych-lubovolnym-poctom-medzier, výběr náhodných slov ze souboru (ale to asi nepomůže) http://programujte.com/index.php?akce=diskuze&kam=vlakno&tema=9222-potrebuju-poradit-s-ukolem, dělení stringu na slova http://programujte.com/index.php?akce=diskuze&kam=vlakno&tema=9328-helpplease-soubor-txt_nacteni_string a to byla teprve první stránka. Uznávám, že když se každé druhé vlákno jmenuje "prosím pomoc", tak se v tom hledá dost špatně :-/.
Tvůj případ by mohl vypadat nějak takhle:
1) Načtu celý řádek (Readln) do nějakého řetězce (string).
2) Na obrazovku napíšu číslo řádku (tj. kolikátý řádek už jsem načetl, tj. hodnotu nějaké proměnné, kterou po každém řádku zvýším o 1).
3) Procházím načtený řádek od začátku tak dlouho, dokud nenarazím na mezeru (se stringem se dá pracovat jako s polem znaků (array[1..length(ten řetězec)] of char) a pomocí indexu z něj číst jednotlivé znaky).
4) Podívám se, jak daleko od začátku řádku už jsem. Jestli dál než 3 písmena, tak je to slovo, které mám za úkol vypsat. Z řádku ho vytáhnu funkcí Copy, vypíšu ho na obrazovku.
5) Ať už bylo jakkoli dlouhé, z toho řádku ho procedurou Delete vymažu.
6) Pokud v řádku ještě něco zbylo, jedu znova od bodu 3.
7) Po zpracování celého řádku pokračuju načtením dalšího - bod 1. To celé až do konce souboru (funkce Eof).
Pusť se do programování a když narazíš na problém, hoď sem zdroják.
Dobrý - krátká, rychlá a docela povedená gameska :smile2: .
Nechtěl bys ji nechat ke stažení u mě na stránce?
P.S.: pokud to někomu nejde stáhnout, tak tady je opravený odkaz: http://cid-4bf53c03bf97f8bb.skydrive.live.com/self.aspx/Ve%c5%99ejn%c3%a9/RO%c4%8c%20Pascal.rar.
Aha.
Takže nejdřív si přečteš počet podmínek. Kolik podmínek je, tolikrát potom přečteš dvojici řádků - první text podmínky, druhý číslo. Předpokládám, že sada podmínek je daná, takže si můžeš předem nadefinovat seznam (pole) řetězců ('deli','nasobek' atd.), se kterými pak budeš načtenou podmínku porovnávat (procházej ten seznam a koukej, kdy narazíš na stejný text jako ten přečtený; samozřejmě je dobré z něj napřed ořezat případné mezery a jiné neplatné znaky a převést ho na stejnou velikost písmen, jakou máš v tom seznamu). Tím si v podstatě text podmínky přetransformuješ na číslo (kolikátá podmínka v tom seznamu to byla), které použiješ pro rozvětvení pomocí příkazu Case, ve kterém budeš mít připraveno vyhodnocení jednotlivých podmínek.
Na to vyhodnocení mě napadá použít množinu (typ Set). Na začátku ji naplníš všemi čísly od 1 do 500 a pak postupně, jak budeš načítat a zpracovávat jednotlivé podmínky, budeš z té množiny vyhazovat ta čísla, která je nesplňují (tj. třeba přečteš "větší než 200", tak vyhodíš všechno, co je <= 200). Po vyhodnocení všech podmínek ti v množině zůstanou všechna čísla, která je splňují (takže můžeš ošetřit i případy, kdy bude víc řešení). Protože se ale do standardní množiny vejde jenom 256 prvků, budeš muset buď použít množiny dvě, čímž se to trochu zkomplikuje (první třeba pro čísla od 0 do 250 a druhou od 251 do 500), nebo si napsat vlastní implementaci množiny a nebo použít nějakou už hotovou (např. http://mircosoft.ic.cz/download/NFSUP.PAS).
Převod z písmen na morseovku se řeší o pár řádků výš.
S obráceným převodem jsem si nedávno hrál :-). Dá se to docela elegantně udělat pomocí stromu, který implementuješ jako pole:
const pismena:array[1..31]of char=('HSVIFU?ELR?APWJ BDXNCKYTZGQM?O_');
(místo podtržítka má být CH, ale to mi nevychází do charu. Otazníky jsou neexistující kombinace)
Inicializace:
index:=16; {pozice mezery}
krok:=8;
Cyklus pro každý znak vstupu:
- Načti jeden znak.
- Pokud je to oddělovač, tak begin write(pismena[index]); index:=16; krok:=8; end;
- Pokud je to tečka, tak begin dec(index,krok); krok:=krok div 2; end;
- Pokud je to čárka, tak begin inc(index,krok); krok:=krok div 2; end;
- Pokud je to nějaký jiný znak, nahlaš chybu a skonči.
Na konci máš na obrazovce vypsaný překlad morseovky do textu.
Máš cca 3 možnosti:
1) Vypnout automatickou kontrolu I/O operací, mezi které se Readln počítá ({$I-}), tím zabráníš pádu programu při chybě. Po Readln se podívej, jestli Ioresult=0. Jestli jo, číslo bylo zadáno správně. Jestli ne, byla zadána kravina, tak uživateli vynadej a nech ho zadat něco lepšího.
2) Načíst to jako řetězec (string) a ten pak převést na číslo ručně procedurou Val. Ta ti přímo řekne, na kolikátém znaku je chyba, tak ji zase můžeš nahlásit a zařídit se podle ní.
3) Místo Readln použít nějakou vlastní proceduru na bázi Readkey, Gotoxy, kontroly každé stisknuté klávesy a ručního převodu na číslo. Ale to je zbytečně pracné.
Tyhle procedury jsou z jednotky System, čili vestavěné.
Deklarace souboru:
var soubor:file;
Otevření souboru:
reset(soubor,velikost_bloku);
nebo
rewrite(soubor,velikost_bloku);
Hodnota velikost_bloku určuje, po jak velkých blocích chceme číst nebo psát. V běžném typovém souboru (file of něco) je velikost bloku jasná (velikost_bloku=sizeof(něco)), proto se tam nepíše. U netypového souboru je všechno na nás. Nejuniverzálnější je, když dáme velikost 1, pak 1 blok = 1 byte. Pokud velikost neuvedeme, použije se defaultní hodnota 128 B (což obvykle nechceme).
Čtení:
blockread(soubor,promenna,kolik);
nebo
blockread(soubor,promenna,kolik,opravdu_precteno);
V prvním případě načteme do Proměnné Kolik bloků z daného Souboru. Jestli jsme při otvírání nastavili velikost bloku na 1, je tohle číslo rovné počtu bytů, které chceme načíst (neboli obvykle velikosti té proměnné). Pokud při čtení nastane chyba, řeší to klasicky Ioresult nebo automatická kontrola I/O.
V druhém případě se v posledním parametru vrátí počet bloků, které se skutečně podařilo přečíst. Pokud se nerovná zadané hodnotě Kolik, víme, že nastala chyba. Ioresult ani automatická kontrola teď nedělají vůbec nic.
Zápis:
blockwrite(soubor,promenna,kolik);
nebo
blockwrite(soubor,promenna,kolik,opravdu_zapsano);
Obdobně.
Zavírání souboru přes Close funguje pořád stejně.
A příklad použití?
var f:file;
i:integer;
s:string;
ch:char;
r:real;
BEGIN
assign(f,'bla.bla');
rewrite(f,1);
blockwrite(f,i,2);
blockwrite(f,s,sizeof(s));
blockwrite(f,ch,1);
blockwrite(f,r,6);
close(f);
END.
Jdou dělat i takové prasárny jako zápis necelé proměnné (třeba jenom prvních x prvků z nějakého velkého pole), podobně jako u Move. Jenom si pak musíme poznamenat, co jsme to vlastně zapsali, abychom to pak vůbec přečetli :-).
Dobrá, tady máš malý polopatický náznak:
const max=... {kolik fragmentu maximalne dostanes?}
var fragmenty:array[1..max] of record
obsah:string;
zpracovan:boolean;
end;
vysledek:string;
i,n:word;
pom:string;
...
{inicializace:}
for i:=1 to max do
with fragmenty[i] do begin
obsah:=... {nejak ho nacist}
zpracovan:=false;
end;
{ted zkontroluj, jestli jsou vsechny fragmenty aspon 6 znaku dlouhe, a jestli ne, tak nahlas chybu}
{algoritmus:}
vysledek:=fragmenty[1].obsah; fragmenty[1].zpracovan:=true;
for n:=6 to 10 do
begin
for i:=1 to max do with fragmenty[i] do {pro kazdy fragment}
if not zpracovan then begin
if copy(obsah,length(obsah)-n+1,n)=copy(vysledek,1,n); {kdyz jeho konec pasuje na zacatek vysledku}
then begin
vysledek:=copy(obsah,1,length(obsah)-n)+vysledek; {pripojime k vysledku}
zpracovan:=true; {tenhle fragment je vyrizeny}
break; {konec vnitrniho foru}
end;
if copy(obsah,1,n)=copy(vysledek,length(vysledek)-n+1,n)
then begin
...
{podobnym zpusobem over, jestli zacatek pasuje na konec vysledku}
...
end;
end;
end;
Šlo by to samozřejmě i obráceně - vnější cyklus točit pro všechny fragmenty a vnitřní pro 6..10 znaků. Ale celková ukončovací podmínka bude stejná: když byly všechny fragmenty zpracovány.
Neručím za správnost - důkladně to po mně zkontroluj. Taky tam neřeším chybové stavy, tj. kdyby mělo několik fragmentů stejný začátek nebo konec (proto by bylo lepší brát to naopak od 10 do 6 (downto), aby se nejdřív zpracovaly ty fragmenty, které se shodují delším úsekem) nebo kdyby některý fragment vůbec nepasoval (v takovém případě by se program zasekl v nekonečné smyčce).
Úsek pro kontrolu opačného konce řetězců a funkci, která zjistí, jestli mají všechny fragmenty nastavenou položku zpracovan na true, už si dopiš sám, to už není nic těžkého (doufám :-) ).
>Ace: Jasně, soubor typu File, zápis Blockwrite, čtení Blockread. Ale pro tenhle případ je to zbytečně pracné (plus ještě nutnost vytvořit editor, protože to už v Notepadu psát nepůjde).
>MZetko, Osiris: zajímavý nápad, ale naprogramovat čtečku XML (pokud vím, tak v Pascalu standardně neexistuje, nebo jo?) by dalo víc práce než celý ten program s otázkami (nevím, jak moc by použití hotové čtečky odněkud ze sítě vyučující tolerovali).
>schnappislav: věř Laacovi, radí ti dobře :-). Něco napiš, hoď sem zdroják a my ti ho zkritizujem a opravíme.
Takže jestli to dobře chápu, máš několik řetězců (string), které potřebuješ složit do jednoho. Hmm... zkusme to třeba takhle:
1) Deklaruj si pomocný řetězec, do kterého budeš ukládat výsledky, na začátku do něj vlož jeden ze zadaných fragmentů (tento fragment vyřaď ze seznamu, který budeš ještě zpracovávat).
2) Pro n od 6 do 10:
- Vezmi n znaků ze začátku toho pomocného řetězce (funkce Copy).
- Projdi postupně všechny zbývající fragmenty, vezmi z nich stejným způsobem konce a porovnej s tím začátkem.
- Pokud je některý konec stejný jako ten začátek, tak:
a) Ten konec z příslušného fragmentu ukroj (procedura Delete),
b) zbylou část fragmentu připoj zleva k pomocnému řetězci,
c) tento fragment vyřaď ze seznamu (abys ho nezačal zpracovávat podruhé),
d) ukonči tento cyklus (třeba příkazem Break nebo nějakou podmínkou) a začni znovu od bodu 2.
- Pokud jsme ještě tady, zleva se nic připojit nedá. Tak to celé proveď ještě jednou pro druhý konec řetězce (porovnávej konec pomocného řetězce se začátky fragmentů, v případě shody je připojuj zprava).
3) To celé opakuj tak dlouho, dokud nezpracuješ a nepřipojíš všechny fragmenty.
4) Výsledek je v tom pomocném řetězci.
Pozice fragmentů ve výsledném textu bych hledal až potom, co by byl celý text složený - na takovéhle věci je ideální funkce Pos.
Otevřeš ho pro zápis procedurou Rewrite (nebo Append, pokud chceš připisovat na konec) a píšeš do něj přes Write a Writeln stejným způsobem, jako kdybys psal na obrazovku. Jenom ještě přidej jako první parametr ten soubor, podobně jako při čtení.
zdravim, potřeboval bych, aby se mi např. u TextFieldu objevil na konci ten symbol, na ktery když kliknete tak můžete procházet soubory na disku a vybrat soubor. Existuje pro to přímo nějaká metoda? Nebo prosím nastiňte nějaký způsob řešení, protože já vůbec nevím, jak to udělat, v javě teprve začínám. Programek by měl umět to, že se takhle vyhledá soubor obrázku na disku, ten obrázek si zkopíruje a udělá jeho zmenšeninu,kterou si uloží.Zdánlivě jednoduchý problém, ale už si s tim hraju celkem pár dní, a ještě jsem nedal dohromady nic funkčního :-) Díky předem za rady
Počet slov := 0.
Nastav se na první znak řetězce.
Deklaruj si dvě proměnné typu char. Do první vlož mezeru.
Cyklus:
- Do druhé proměnné ulož obsah první.
- Do první proměnné načti jeden znak z aktuální pozice v řetězci.
- Pokud je v první proměnné písmeno a ve druhé mezera, našli jsme začátek slova - zvyš počet slov o 1.
- Posuň se v řetězci o znak dál.
Opakuj, dokud nedojdeš na konec řetězce.
Nebo kdybys chtěl odstranit vícenásobné mezery, tak můžeš opakovat hledání podřetězce ' ' (dvě mezery vedle sebe) pomocí funkce Pos a následné smazání jedné té mezery procedurou Delete, ale bude to méně efektivní.
Tuhle hlášku jsem ještě neviděl. Zkontroluj Compile -> Target a kdyžtak sem hoď screen (ale v GIFu a trochu ho ořízni, ať nemusím zase stahovat 300kilové JPG).
Soubor kul.txt jsi neposlal, tak jsem si musel udělat svůj:
10 20 30 1
100 50 1 12
2 5 66 10
Program jsem spustil, výstup je v příloze. Chyba 201 je Range check error a objevila se proto, že se snažíš přistupovat k prvkům pole s indexy c1 a c2, jenže tyhle proměnné mají zrovna hodnotu 0 a indexy pole začínají až od 1, takže jsi mimo a proto ta chyba.
Syntakticky je program v pořádku (opsal jsi to dobře), takže teď se zamysli nad funkcí a vlož do toho nějakou vlastní práci.
Z jakého souboru tu matici chceš načítat? Předpokládám, že z textového, takže použij procedury Read a Readln. Rozměry jsou pevně dané nebo je musíš zjišťovat při načítání?
Nadeklarovat dvojrozměrné pole (array [1..n,1..n] of ...) doufám není problém.
Takže dejme tomu, že matici máš načtenou.
Jestli je talismanová (obsahuje všechna čísla 1..n^2), poznáš tak, že (třeba) si uděláš množinu čísel (set of byte, snad ta matice nebude moc velká), do ní nasypeš čísla od 1 do n^2 (buď sjednocením (+) nebo procedurou Include nebo prostě zápisem mnozina:=[1..n], kde n je konstanta). Potom projdi tu matici prvek po prvku (dvojitým cyklem typu For) a každé nalezené číslo z té množiny vyhoď (rozdílem (-) nebo procedurou Exclude). Pokud je na konci množina prázdná (mnozina=[]), znamená to, že matice je talismanová.
Jestli nemáš rád množiny, tak můžeš v matici hledat postupně čísla od 1 do n^2 a jakmile zjistíš, že tam některé z nich není, tak víš, že matice není talismanová.
Jestli dobře chápu, že řád je to číslo k, tak je to celkem jednoduchá úloha na nalezení minima. Postup: deklaruj si pomocnou proměnnou a vlož do ní nějakou největší možnou hodnotu (nebo radši abs. hodnotu rozdílu libovolných dvou prvků matice). Potom opět projdi celou matici prvek po prvku, u každého spočítej absolutní hodnotu (funkce Abs) rozdílu se všemi jeho sousedy (pozor na okraje matice, to ošetři ifem) a porovnej ji s tou pomocnou proměnnou. Pokud je ten rozdíl menší než ta proměnná, ulož ho do ní. Na konci budeš v té proměnné mít minimum, čili hledaný řád talismanové matice.
Chceš obracet jeden string nebo nějaké pole?
Předně musíš z té procedury nějak dostat výsledek ven. Nejlépe tak, že z ní uděláš funkci: function obrat(s:string):string;
Pak si v ní deklaruj jeden lokální string. Ten na začátku funkce vyprázdni (pomocný:='';).
Pak ber postupně znaky od konce vstupního řetězce a připojuj je na konec toho pomocného. Počet znaků v řetězci ti dá funkce Length, pro zpětný průchod použij cyklus For se slovem Downto místo To.
Nakonec ten pomocný řetězec vrať jako výsledek funkce.
Stačí takhle?
Aha.
Nejjednodušší asi bude, když si napřed celý soubor načteš do pole stringů (pokud je moc velký, čti ho postupně po kouscích).
Začátek:
Nastav se na začátek tohoto pole.
Cyklus:
Vyprázdni pomocný string.
Hledej řetězec <waypoint>.
Od této pozice dál hledej řetězec <coord, příslušný řádek projeď a vytáhni z něj ta dvě čísla (tj. dojeď k první uvozovce, pak čti a ukládej znaky do druhého souboru tak dlouho, dokud to jsou čísla nebo tečka, pak zapiš čárku, přejeď koncovou úvozovku, dojeď ke druhé a stejným způsobem ulož druhé číslo a zase zapiš čárku).
Vrať se k řádku s waypointem a od něj hledej text <name id=". Z něj podobným způsobem vytáhni ten identifikátor a ulož ho.
Opět zpátky na waypoint, od něj najdi <text ![CDATA[ a ulož si všechno až k té uzavírající hranaté závorce (plus okolo toho připiš uvozovky).
Zpět na začátek cyklu, najdi následující <waypoint> a všechno opakuj tak dlouho, dokud nezpracuješ všechno.
Na hledání podřetězce v řetězci slouží funkce Pos, k procházení jednotlivých řádků stačí pomocný index a číst znak po znaku (řetězec[index]), na čtení řádku ze souboru je Readln, na zápis Writeln, konec souboru ti ohlásí funkce Eof, určitě budeš potřebovat cykly for a while a datové typy array, string a pár celých čísel.
Snad jsem na nic nezapomněl...
>Tocimanko: na foreach povím, že v Pascalu není :smile3:
>Cherokee:
- nevím, jestli má FP ve standardní výbavě (nebo v té jednotce Sysutils) funkci Inttostr. Jestli ti na ní hlásí chybu "unknown identifier", tak ten řádek přepiš na:
write('Zadaj ',i,'. zaznam v tvare drahaMEDZERAcas: ');
- Dráhu a čas (s, t) bych dal radši reálné (uživatel určitě nebude zadávat jen celá čísla).
- Místo Read(s,t) použij radši Readln(t,s) (Readln je stavěná na čtení z klávesnice, Read moc ne). Možná že se tím vyřeší problém s Readln na konci programu a bude stačit jedno.
- Před počítáním součtu musíš proměnnou Součet vynulovat, jinak se ti do ní připočítá nějaká nedefinovaná hodnota, která v ní byla před začátkem cyklu (globální proměnné sice bývají obvykle na začátku programu nulové, ale nespoléhal bych se na to)
- Nejmenší rychlost najdeš na opačném konci pole než jsi našel tu největší.
Zbytek mi připadá v pořádku.
V const pole stringů s indexy 'a'..'z' a obsahem '.-' až '--..' . V cyklu projedeš zadaný řetězec písmeno po písmenu, každé použiješ jako index toho pole a na obrazovku vypíšeš přímo string z té pozice.
V praxi readln, write, writeln, for, var, const, begin a end ;-).
To Marilyn666 :
Napřed rozhodíš celé fórum nesmyslně dlouhým nadpisem.
Potom chceš, abychom ti posílali odpovědi přes mail (fóra jsou od toho, aby z toho měli něco i ostatní).
Potom neumíš napsat do vyhledávače "základy freepascalu" a zmáčknout "vyhledat".
Potom sem uploadneš jednoapůlmegový screenshot.
Příště to prosím tě zkus trochu jinak, nebo se některý moderátor oprávněně naštve a vlákno ti smaže.
Můžu doporučit třeba tohle: http://int21h.ic.cz/?id=70 (až někde v polovině).
Tak jsem ten text o objektech poněkud překopal a už se za něj nestydím :-)
http://www.mircosoft.ic.cz/texty/OOP.TXT
Teď je tam všechno včetně virtuálních metod (a slova inherited, dík za upozornění).
Něco jako Arc bych měl: http://mircosoft.ic.cz/download/GRAFIKA3.PAS (hledej proceduru _Oblouk).
Pieslice vznikne drobnou modifikací oblouku: místo čar stačí kreslit trojúhelníky s jednou stranou místo té čáry a se třetím vrcholem ve středu výseče (buď si to napiš sám nebo počkej pár dní na aktualizaci té jednotky).
... A přitom stačilo hned na začátku říct něco ve smyslu "nevím jak se deklaruje matice" nebo "nevím, jak se v Pascalu násobí" nebo tak, abychom i my dementi pochopili, s čím přesně máme pomáhat :smile1: :smile5:
Tak si ještě naposledy vynadáme a poprosíme admina, aby to po nás zhruba odsud http://programujte.com/index.php?akce=diskuze&kam=vlakno&nove=1&tema=7187-domaci-ukol-pomozte#59763 smazal, OK? :smile3:
A já bych potřeboval, aby za mě někdo napsal semestrálku a nejlíp i diplomku :smile20: .
Sorry, ale tohle ne. Můžu ti s tím pomoct, ale ne to za tebe celé udělat (ne že bych neuměl, ale ze zásady).
Takže si někde najdi něco o polích (array) a cyklech (for) a násobení (*) a snaž se. A přijď, až budeš mít aspoň něco hotové.
No... existují i učitelé, kteří se moc nevyznají v látce, kterou učí :-).
Napadají mě tři možnosti:
Buď tvůrce zadání neví, že string obsahuje i údaj o své délce.
Nebo že proměnná Delka určuje, jak dlouhý úsek z toho řetězce máš formátovat: třeba dostaneš 100znakový řetězec, Delka bude 20 a L bude 50, tak prvních 20 znaků řetězce natáhneš na 50 a zbytek necháš v původní podobě.
Nebo že to ten člověk původně myslel jinak - položka Znaky byla array[1..hodně] of char, Delka byla třeba word a už to nebyl řetězec s max. délkou 255, ale něco většího. A pak si to rozmyslel, "zjednodušil" to použitím standardního stringu, ale nechal původní text zadání.
Vzhledem k tomu, jak jsou ty deklarace v zadání prasácky napsané (proč 0..255, když stačí napsat byte? Proč je L integer, když max. délka stejně nesmí přesáhnout 255 znaků?) bych to tipoval spíš na tu první možnost.
Kdybych takovéhle zadání dostal já, tak bych toho učitele otravoval tak dlouho, dokud by mi nevysvětlil, co po mě vlastně chce :smile20: .
Místo tohohle:
while not seekeof(f) do...
bych napsal tohle:
while not eof(f) do...
Teď si zrovna nepamatuju, co dělá seekeof, ale myslím, že to je procedura, která přesune kurzor na konec souboru, což určitě nechceš.
Tohle:
if soucet[i]+aktcislo[i]>10 then...
ti nebude fungovat. Tady už musíš mít znaky převedené na čísla:
if ord(soucet[i])-48+ord(aktcislo[i])-48>10 then...
Stejně tak tohle:
soucet[i]:=soucet[i]+aktcislo[i];
musíš přepsat takhle:
soucet[i]:=chr(ord(soucet[i])-48+ord(aktcislo[i])-48+48);
To plus mínus 48 na konci se samozřejmě vyruší, napsal jsem to tam pro přehlednost - odečtením převedeš znak na číslo, přičtením číslo na znak.
Ty totiž místo toho, abys načetl několik náhodně vybraných čísel z toho souboru (což předpokládám, že bylo předmětem zadání), tak načítáš čísla ze souboru a pak generuješ náhodná čísla od nuly do toho načteného čísla.
Potřebuješ asi tohle:
Pomocí Randomu vygeneruj pět náhodných čísel od 1 do 20 a zapamatuj si je (třeba v nějakém poli).
Pro každé z těchto čísel dělej:
- Otevři soubor, pomocí Readln v něm dojeď na tolikátý řádek, kolik je to číslo, u kterého zrovna jsi.
- Přečti ze souboru číslo z tohoto řádku a vypiš ho na obrazovku.
- Zavři soubor.
Samozřejmě tohle není jediná možnost a z hlediska rychlosti to není zrovna optimální, protože několikrát otvírám, zavírám a procházím soubor. Lepší by bylo, kdyby se soubor prošel jednou a naopak se u každého řádku prošlo pole těch pěti náhodných čísel a zkoušelo by se, jestli nějaké z nich odpovídá pořadovému číslu toho řádku. Ale fungovat to bude v obou případech. Realizaci nechám na tobě.
Jo, a Randomize použij jenom jednou na začátku programu. Jestli ho budeš volat před každým Randomem, budou ti nejspíš vycházet pořád stejná čísla.
Stačí tahle jednotka?
http://mircosoft.ic.cz/download/CAS.PAS
Pod W.98 zaručeně funguje.
Někde za implementation najdeš několik zakomentovaných konstant, pomocí kterých se nastavuje rychlost. Tak odkomentuj tu jednomilisekundovou a ostatní zase zakomentuj.
To je taková datová struktura složená z recordů a v každém z nich je ukazatel na ten následující. Celé se to alokuje dynamicky procedurou New.
Podrobnější info třeba tady: http://mircosoft.ic.cz/texty/UKAZ.TXT
Další pozorování na IE 6.0:
- Pole pro vložení přílohy (vpravo dole nad tlačítkem "Vložit odpověď") je jenom asi 2 znaky široké. Což vlastně ani nevadí, ale vypadá to dost divně.
- Nefunguje editace příspěvků. Kliknu na tlačítko Editovat a asi se nějak špatně předá adresa, protože se v adresním řádku objeví tohle: http://programujte.com/index.php?akce=diskuze&kam=vlakno&tema=# , čili obrazovka pro vložení nového příspěvku.
- Avataři se hrozně roztahují do výšky. Mám dojem, že se všem nastaví nějaký stejný fixní rozměr bez ohledu na skutečnou velikost a poměr stran.
- Odkazy Záložky, RSS fórum, Home a Menu jsem naknec náhodou objevil schované nalevo v takovém prázdném bílém obdélníku pod horní navigační lištou, tady je screenshot: http://mircosoft.ic.cz/obrazky/bug-scrshot.gif
Pod Firefoxem je to v pohodě, ale neměl by server zaměřený mj. na webdesign být příkladem pro všechny a fungovat všude? ;-)
Jestli je na začátku programu i=0, tak to znamená, že indexy pro kreslení toho černého hada (i-delkahada) vycházejí záporné a tak čteš souřadnice uložené "před" těmi poli. A samozřejmě to nejsou souřadnice, ale nějaká nesmyslná data, takže se černý had kreslí kdovíkde (to jsou ty divný čáry) a nemaže ti zeleného.
Možné řešení: na začátku programu nastav i rovné Delkahada+1.
Každopádně počítej s tím, že na tuhle úlohu potřebuješ kruhovou frontu. Čili buď pole, kde při přejetí konce skočíš s indexem zpátky na začátek (stejně tak při podjetí začátku skočíš na konec), nebo spojový seznam, který mi přijde jednodušší na naprogramování a nemá pevně určený počet prvků.