if ( ((strcmp(argv[i],"-f") == 0) && (i++) && ((shift=0) || 1)) || ((strncmp(argv[i],"--file=", 7) == 0) && (shift=7)) ) { if (i >= argc) { /* Error. */ } char *input = argv[i] + shift; /* .. */ }
argv
- pole argumentů příkazové řádky (argc
je jejich počet)strcmp
vrátí 0, pokud jsou řetězce shodné
strncmp
porovnává jen prvních n znaků--file=soubor.txt
-f soubor.txt
Jde o (velmi nepodařené) zpracovávání argumentů z příkazové řádky.
Cílem je, aby program dokázal přijmout název vstupního souboru specifikovaného
jako -f
soubor.txt
nebo --file=soubor.txt
.
Korektní řešení je v tomto případě použít knihovnu getopt
popř. nějakou
její náhradu.
Cílem je
// Soubor libc.h void *malloc(const size_t); void free(const void *); int thread_create(void (*)(void *), void *, const char *, thread_id_t *); void thread_exit(int); void thread_detach(thread_id_t); int thread_join(thread_id_t); void *calloc(const size_t, const size_t); void *memalign(const size_t, const size_t); void *realloc(const void *, const size_t); thread_id_t thread_get_id(void);
// Soubor libc.h void *malloc(const size_t); void free(const void *); int thread_create(void (*)(void *), void *, const char *, thread_id_t *); void thread_exit(int); void thread_detach(thread_id_t); int thread_join(thread_id_t); void *calloc(const size_t, const size_t); void *memalign(const size_t, const size_t); void *realloc(const void *, const size_t); thread_id_t thread_get_id(void);
// Soubor thread.h int thread_create(void (*)(void *), void *, const char *, thread_id_t *); void thread_exit(int) void thread_detach(thread_id_t); int thread_join(thread_id_t); thread_id_t thread_get_id(void);
// Soubor malloc.h void *malloc(const size_t size); void *calloc(const size_t nmemb, const size_t size); void *memalign(const size_t align, const size_t size); void *realloc(const void *addr, const size_t size); void free(const void *addr);
class Score { public string Player => /*...*/; public int Score => /*...*/; }
class Game { private const string Sep1 = ".\t"; private const string Sep2 = "\t"; /* ... */ public void PrintHiscore(Score[] scores) { for (int scoreIndex = 0; scoreIndex < scores.Length; scoreIndex++) { Console.WriteLine( (scoreIndex + 1) + Sep1 + scores[scoreIndex].Player + Sep2 + scores[scoreIndex].Score ); } } }
Sep1
a Sep2
jsou platné v celé třídě
scoreIndex
je zbytečně dlouhá+ 1
, takže by se možná vyplatilo
mít ji bokemclass Game { private const string HiscoreIndexPlayerSeparator = ".\t"; private const string HiscorePlayerScoreSeparator = "\t"; /* ... */ public void PrintHiscore(Score[] scores) { for (int i = 0; i < scores.Length; i++) { Console.WriteLine( (i + 1) + HiscoreIndexPlayerSeparator + scores[i].Player + HiscorePlayerScoreSeparator + scores[i].Score ); } } }
class Game { // Prints 'index. name score' private const string HiscoreFormat = "{0}.\t{1}\t{2}"; /* ... */ public void PrintHiscore(Score[] scores) { for (int i = 0; i < scores.Length; i++) { Console.WriteLine(HiscoreFormat, i + 1, scores[i].Player, scores[i].Score); } } }
class Game { private string BuildScoreLine(Score score, int position) => $"{position}.\t{score.Player}\t{score.Score}"; public void PrintHiscore(IEnumerable<Score> scores) { for (int i = 0; i < scores.Length; i++) { Console.WriteLine(BuildScoreLine(scores[i], i + 1)); } } }
class Game { private string BuildScoreLine(Score score, int position) => $"{position}.\t{score.Player}\t{score.Score}"; public void PrintHiscore(IEnumerable<Score> scores) { scores .Select((score, i) => BuildScoreLine(score, i + 1)) .ToList() .ForEach(Console.WriteLine); } }
double getAverageSpeed(int distance, int time) { if (time != 0) { return distance / time; } else { throw new IllegalArgumentException( "Parameter time should not be zero."); } }
else
větvi
double getAverageSpeed(int distance, int time) { if (time != 0) { return distance / time; } else { throw new IllegalArgumentException( "Parameter time should not be zero."); } }
double getAverageSpeed(int distance, int time) { if (time == 0) { throw new IllegalArgumentException( "Parameter time should not be zero."); } return distance / time; }
public void SendMessage(Message message, User recipient, User sender) { if (message == null || recipient == null) { throw new ArgumentException("Message and recipient can't be null."); } /* ... */
Jak víme, kde může null nastat? Potřebujeme informaci v rámci rozhraní, ideálně typového systému. Problém je v tom, že dnešní jazyky neznají koncept referenčního typu, který nepodporuje null hodnoty. Přitom jde o velmi přirozený požadavek, z bodů uvedených na slidu je jasné, že nullabilita by měla být volitelná v rámci specifických rozhraní.
Tony Hoare (mj. autor quicksortu) null referenci "vynalezl" v roce 1965 při návrhu typového systému pro referenční typy v objektově orientované mutaci ALGOLu, ALGOGL W. Další jazyky potom tento koncept převzaly a stal se z něj více méně standard. Výše uvedený citát je z roku 2009.
public void sendMessage(@NotNull Message message, @NotNull User recipient, @Nullable User sender) {
NullReferenceException
fun sendMessage(message: Message, recipient: User, sender: User?) {
Anotace jsou k dispozici v Javě i v C#, ovšem v různých variantách (např. od JetBrains). IDE či pluginy dnes umí nad "svými" anotacemi provést statickou analýzu a identifikovat přiřazení nullable do non-nullable. Vynuceno při kompilaci ovšem není nic. Problémem je také nestandardizovanost.
Nově vznikající jazyky proto mají přimo v type systému zanesen fakt, že jak hodnotové tak referenční typy mohou být uvedeny jako nullable či non-nullable. Platí to jak pro deklaraci proměnných, tak pro deklaraci parametrů metod. Zdá se, že existuje proposal pro podobnou featuru do jedné z budoucích verzí C# (https://blogs.msdn.microsoft.com/dotnet/2017/11/15/nullable-reference-types-in-csharp/).
/* Emulate enum for log levels. */ define("LOG_LEVEL_INFO", 0); define("LOG_LEVEL_ERROR", 1); function log( $level, $message) { if ($level == LOG_LEVEL_INFO) { $color = "green"; } else { $color = "red"; } echo "<p style='color: $color'>" . htmlspecialchars($message, ENT_QUOTES) . "</p>"; }
default
větev (třeba s assertem)echo
příkazem printf
/* Emulate enum for log levels. */ define("LOG_LEVEL_INFO", 0); define("LOG_LEVEL_ERROR", 1); function log( $level, $message) { if ($level == LOG_LEVEL_INFO) { $color = "green"; } else { $color = "red"; } echo "<p style='color: $color'>" . htmlspecialchars($message, ENT_QUOTES) . "</p>"; }
/* Emulate enum for log levels. */ define("LOG_LEVEL_INFO", 0); define("LOG_LEVEL_ERROR", 1); function log( $level, $message) { switch ($level) { case LOG_LEVEL_INFO: $color = "green"; break; case LOG_LEVEL_ERROR: $color = "red"; break; default: assert(false && "Unreachable code"); } echo "<p style='color: $color'>" . htmlspecialchars($message, ENT_QUOTES) . "</p>"; }
switch
C/C++, Java
switch (value) { case 1: xy = 1; break; case 2: case 3: xy = 4; break; default: xy = 45; } |
Ruby
case inputLine when "debug" dumpDebugInfo dumpSymbols when /p\s+(\w+)/ dumpVariable($1) when "quit", "exit" exit else print "Illegal command!" end |
switch
switch (o) { case string s when s.Contains("Fizz") || s.Contains("Buzz"): Console.WriteLine(s); break; case int n when n % 5 == 0 && n % 3 == 0: Console.WriteLine("FizzBuzz"); break; case int n when n % 5 == 0: Console.WriteLine("Fizz"); break; case int n when n % 3 == 0: Console.WriteLine("Buzz"); break; case int n: Console.WriteLine(n); break; }
switch
switch
(zde nazvaný when
) může být výraz, tj. vracet hodnotuenum class LogLevel { INFO, ERROR } fun getLogColor(level: LogLevel): String = when (level) { LogLevel.INFO -> "green" LogLevel.ERROR -> "red" }
LogLevel
, funkce getLogColor
nepůjde zkompilovatvoid printClassParents(Class klass) { for ( Class c = klass.getSuperclass(); c != null; c = c.getSuperclass()) { System.out.println(c.getName()); } }
Tohle je ok.
Na for-cyklus se dá z pohledu sémantiky koukat dvojím způsobem: jako na cyklus s pevným počtem opakování a nebo na cyklus se strukturou "inicializace, podmínka, krok".
Uvedený příklad zapadá do obou pohledů. O něco spornější jsou takové případy, které mají potřebnou strukturu, ale nemají pevný počat opakování.
void printClassParents(Class klass) { for ( Class c = klass.getSuperclass(); c != null; c = c.getSuperclass()) { System.out.println(c.getName()); } }
while ( ( c = getchar() ) != '\t' ) { putchar( c ); }
Špatně je zde vedlejší efekt přiřazení (resp. znásilnění podmínky k přiřazení).
std::string read_data; while ( std::getline( input_stream, read_data, '\t' ) ) { std::cout << read_data; }
std::string read_data; while ( input_stream.good() ) { std::getline( input_stream, read_data, '\t' ) std::cout << read_data; }
Totéž, opravené
Mimochodem, CPPReference to v demonstračních příkladech má ještě hnusněji: http://en.cppreference.com/w/cpp/string/basic_string/getline
while read LINE ; do echo "$LINE" | sed 's/blbec/b---c/' done < INPUT_FILE
Tady je taky vedlejší efekt, ale je to v podstatě idiom, který používají všichni.
/* Pro účely úlohy předpokládejme, že "result" ukazuje na dostatečně dlouhé pole. */ unsigned array_remove_duplicite_items(int array[], unsigned length, int result[]) { int i, j; unsigned result_length = 0; for (i = 0; i < length; i++) { int found = FALSE; for (j = 0; j < result_length; j++) { if (array[i] == result[j]) { found = TRUE; break; } } if (!found) { result[result_length] = array[i]; result_length++; } } return result_length; }
*result
to o moc nevylepší)int
typ místo bool
for
cyklu/* Pro účely úlohy předpokládejme, že "result" ukazuje na dostatečně dlouhé pole. */ unsigned array_remove_duplicite_items(int array[], unsigned length, int result[]) { int i, j; unsigned result_length = 0; for (i = 0; i < length; i++) { int found = FALSE; for (j = 0; j < result_length; j++) { if (array[i] == result[j]) { found = TRUE; break; } } if (!found) { result[result_length] = array[i]; result_length++; } } return result_length; }
/* Pro účely úlohy předpokládejme, že "result" ukazuje na dostatečně dlouhé pole. */ unsigned array_remove_duplicite_items(int array[], unsigned length, int result[]) { unsigned result_length = 0; for (int i = 0; i < length; i++) { if (!array_find(result, result_length, array[i])) { result[result_length] = array[i]; result_length++; } } return result_length; }
/* Pro účely úlohy předpokládejme, že "result" ukazuje
na dostatečně dlouhé pole. */
unsigned array_remove_duplicite_items(int array[], unsigned length,
int result[]) {
unsigned result_length = 0;
for (int i = 0; i < length; i++) {
if (!array_find(result, result_length, array[i])) {
result[result_length] = array[i];
result_length++;
}
}
return result_length;
}
/* Pro účely úlohy předpokládejme, že "result" ukazuje
na dostatečně dlouhé pole. */
unsigned array_remove_duplicite_items(int array[], unsigned length,
int result[]) {
unsigned result_length = 0;
for (int i = 0; i < length; i++) {
if (!array_find(result, result_length, array[i])) {
result_length = array_append(result, result_length, array[i]);
}
}
return result_length;
}
/* Pro účely úlohy předpokládejme, že "result" ukazuje
na dostatečně dlouhé pole. */
unsigned array_remove_duplicite_items(int array[], unsigned length,
int result[]) {
unsigned result_length = 0;
for (int i = 0; i < length; i++) {
if (!array_find(result, result_length, array[i])) {
result_length = array_append(result, result_length, array[i]);
}
}
return result_length;
}
Ještě nám vadí pojmenování funkce array_find
. Vrací v podstatě boolean
a radši bychom měli is v názvu.
/* Pro účely úlohy předpokládejme, že "result" ukazuje
na dostatečně dlouhé pole. */
unsigned array_remove_duplicite_items(int array[], unsigned length,
int result[]) {
unsigned result_length = 0;
for (int i = 0; i < length; i++) {
if (!is_in_array(result, result_length, array[i])) {
result_length = array_append(result, result_length, array[i]);
}
}
return result_length;
}
Ctecka.cs
Opravte v kódu chyby.
Třída byla součástí většího programu, který implementoval Huffmanovo kódování. Vybraná třída načítá vstup ze souboru a připravuje ho pro další zpracování.
Neformální zápis funkce algoritmu, třídy, metody v téměř přirozeném jazyce.
increment resource number by 1 allocate a dlg struct using malloc if malloc() returns NULL then return 1 invoke OSrsrc_init to initialize a resource for the operating system *hRsrcPtr = resource number return 0
increment resource number by 1 allocate a dlg struct using malloc if malloc() returns NULL then return 1 invoke OSrsrc_init to initialize a resource for the operating system *hRsrcPtr = resource number return 0
Keep track of current number of resources in use If another resource is available Allocated a dialog box structure If a dialog box structure could be allocated Note that one more resource is in use Initialize the resource Store the resource number at the location provided by the caller Endif Endif Return TRUE if a new resource was created; otherwise return FALSE
Úloha je lehkým zjednodušením úlohy řešené v rámci kódu mé diplomové práce. Konkrétně jsem potřeboval implementovat bitové operace na "velkých číslech".
Pokud se vám zdá ukládání bitů po jednom jako neefektivní, máte pravdu. Ale je to nejjednodušší řešení a optimalizovat se ho vyplatí až v případě, že nás opravdu někde začne "tlačit bota". Což v případě diplomové práce taky nemusí nastat vůbec :-)
Pokud přemýšlíte, proč není číslo uloženo jako dvojkový doplněk rovnou, odpověď je inženýrská: PHP obsahuje knihovnu bcmath, která používá řetězcový zápis čísel a implementuje základní aritmetické operace (+, -, *, /, %,...). Je méně pracné implementovat převod mezi formáty a (triviálně) bitové operace, než (relativně obtížně) implementovat všechny operace.
Pokud si z prvního ročníku nepamatujete, co je to dvojkový doplněk, pomůže wikipedie.
V tomto příkladu bude vše v angličtině, protože to tak mám i v diplomové práci.
/** ... */ function bignum_to_bits($bignum) { /* Remember if the value is negative. */ /* If the value is negative, trim the sign (i.e. compute the absolute value). */ /* Compute the bits of the absolute value (using standard algorithm). */ /* If the first bit is non-zero, prefix the number with zero bit. */ /* If the number was negative, invert the bits and add one. */ /* Return the bits. */ }
function bignum_to_bits($bignum) {
/* Remember if the value is negative. */
$negative = ($bignum[0] == "-");
/* If the value is negative, trim the sign (i.e. compute the
absolute value). */
/* Compute the bits of the absolute value (using standard
algorithm). */
/* If the first bit is non-zero, prefix the number with
zero bit. */
/* If the number was negative, invert the bits and add one. */
/* Return the bits. */
}
function bignum_to_bits($bignum) {
/* Remember if the value is negative. */
$negative = ($bignum[0] == "-");
/* If the value is negative, trim the sign (i.e. compute the
absolute value). */
if ($negative) {
$bignum = substr($bignum, 1);
}
/* Compute the bits of the absolute value (using standard
algorithm). */
/* If the first bit is non-zero, prefix the number with
zero bit. */
/* If the number was negative, invert the bits and add one. */
/* Return the bits. */
}
function bignum_to_bits($bignum) {
/* Remember if the value is negative, trim the sign if so. */
if ($negative = ($bignum[0] == "-")) {
$bignum = substr($bignum, 1);
}
/* Compute the bits of the absolute value (using standard
algorithm). */
/* If the first bit is non-zero, prefix the number with
zero bit. */
/* If the number was negative, invert the bits and add one. */
/* Return the bits. */
}
Sloučení prvních dvou kroků.
function bignum_to_bits($bignum) {
/* Remember if the value is negative, trim the sign if so. */
if ($negative = ($bignum[0] == "-")) {
$bignum = substr($bignum, 1);
}
/* Compute the bits of the absolute value (using standard
algorithm). */
$bits = array();
do {
array_unshift($bits, (int)bcmod($bignum, 2));
$bignum = bcdiv($bignum, 2);
} while ($bignum != "0");
/* If the first bit is non-zero, prefix the number with
zero bit. */
/* If the number was negative, invert the bits and add one. */
/* Return the bits. */
}
function bignum_to_bits($bignum) {
/* Remember if the value is negative, trim the sign if so. */
if ($negative = ($bignum[0] == "-")) {
$bignum = substr($bignum, 1);
}
/* Compute the bits of the absolute value (using standard
algorithm). */
$bits = array();
do {
array_unshift($bits, (int)bcmod($bignum, 2));
$bignum = bcdiv($bignum, 2);
} while ($bignum != "0");
/* If the first bit is non-zero, prefix the number with
zero bit. */
if ($bits[0] != 0) {
array_unshift($bits, 0);
}
/* If the number was negative, invert the bits and add one. */
/* Return the bits. */
}
function bignum_to_bits($bignum) {
/* Remember if the value is negative, trim the sign if so. */
if ($negative = ($bignum[0] == "-")) {
$bignum = substr($bignum, 1);
}
/* Compute the bits of the absolute value (using standard
algorithm). */
$bits = array();
do {
array_unshift($bits, (int)bcmod($bignum, 2));
$bignum = bcdiv($bignum, 2);
} while ($bignum != "0");
/* If the first bit is non-zero, prefix the number with
zero bit. */
if ($bits[0] != 0) {
array_unshift($bits, 0);
}
/* If the number was negative, invert the bits and add one. */
if ($negative) {
for ($i = 0; $i < count($bits); $i++) {
$bits[$i] = 1 - $bits[$i];
}
for ($i = count($bits) - 1; $i >= 0; $i--) {
if ($bits[$i] == 0) {
$bits[$i] = 1;
break;
} else {
$bits[$i] = 0;
}
}
}
/* Return the bits. */
}
function bignum_to_bits($bignum) {
/* Remember if the value is negative, trim the sign if so. */
if ($negative = ($bignum[0] == "-")) {
$bignum = substr($bignum, 1);
}
/* Compute the bits of the absolute value (using standard
algorithm). */
$bits = array();
do {
array_unshift($bits, (int)bcmod($bignum, 2));
$bignum = bcdiv($bignum, 2);
} while ($bignum != "0");
/* If the first bit is non-zero, prefix the number with
zero bit. */
if ($bits[0] != 0) {
array_unshift($bits, 0);
}
/* If the number was negative, invert the bits and add one. */
if ($negative) {
for ($i = 0; $i < count($bits); $i++) {
$bits[$i] = 1 - $bits[$i];
}
for ($i = count($bits) - 1; $i >= 0; $i--) {
if ($bits[$i] == 0) {
$bits[$i] = 1;
break;
} else {
$bits[$i] = 0;
}
}
}
/* Return the bits. */
return $bits;
}
function bignum_to_bits($bignum) { /* Remember if the value is negative, trim the sign if so. */ if ($negative = ($bignum[0] == "-")) { $bignum = substr($bignum, 1); } /* Compute the bits of the absolute value (using standard algorithm). */ $bits = array(); do { array_unshift($bits, (int)bcmod($bignum, 2)); $bignum = bcdiv($bignum, 2); } while ($bignum != "0"); /* If the first bit is non-zero, prefix the number with zero bit. */ if ($bits[0] != 0) { array_unshift($bits, 0); } /* If the number was negative, invert the bits and add one. */ if ($negative) { for ($i = 0; $i < count($bits); $i++) { $bits[$i] = 1 - $bits[$i]; } for ($i = count($bits) - 1; $i >= 0; $i--) { if ($bits[$i] == 0) { $bits[$i] = 1; break; } else { $bits[$i] = 0; } } } /* Return the bits. */ return $bits; }
V tuto chvíli vypadá funkce jako hotová. Ale zdaleka není...
function bignum_to_bits($bignum) {
/* Remember if the value is negative, trim the sign if so. */
if ($negative = ($bignum[0] == "-")) {
$bignum = substr($bignum, 1);
}
/* Compute the bits of the absolute value (using standard
algorithm). */
$bits = array();
do {
array_unshift($bits, (int)bcmod($bignum, 2));
$bignum = bcdiv($bignum, 2);
} while ($bignum != "0");
/* If the first bit is non-zero, prefix the number with
zero bit. */
if ($bits[0] != 0) {
array_unshift($bits, 0);
}
/* If the number was negative, invert the bits and add one. */
if ($negative) {
$bits = bits_add_one(bits_invert($bits));
}
/* Return the bits. */
return $bits;
}
function bignum_to_bits($bignum) {
/* Remember if the value is negative, trim the sign if so. */
if ($negative = ($bignum[0] == "-")) {
$bignum = substr($bignum, 1);
}
/* Compute the bits of the absolute value (using standard
algorithm). */
$bits = positive_bignum_to_bits($bignum);
/* If the first bit is non-zero, prefix the number with
zero bit. */
if ($bits[0] != 0) {
array_unshift($bits, 0);
}
/* If the number was negative, invert the bits and add one. */
if ($negative) {
$bits = bits_add_one(bits_invert($bits));
}
/* Return the bits. */
return $bits;
}
function bignum_to_bits($bignum) {
/* Remember if the value is negative, trim the sign if so. */
if ($negative = ($bignum[0] == "-")) {
$bignum = substr($bignum, 1);
}
/* Compute the bits of the absolute value (using standard
algorithm). */
$bits = positive_bignum_to_bits($bignum);
/* If the first bit is non-zero, prefix the number with
zero bit. */
$bits = bits_prefix_with_zero_if_needed($bits);
/* If the number was negative, invert the bits and add one. */
if ($negative) {
$bits = bits_add_one(bits_invert($bits));
}
/* Return the bits. */
return $bits;
}
function bignum_to_bits($bignum) { /* Remember if the value is negative, trim the sign if so. */ if ($negative = bignum_is_negative($bignum)) { $bignum = bignum_abs($bignum); } /* Compute the bits of the absolute value (using standard algorithm). */ $bits = positive_bignum_to_bits($bignum); /* If the first bit is non-zero, prefix the number with zero bit. */ $bits = bits_prefix_with_zero_if_needed($bits); /* If the number was negative, invert the bits and add one. */ if ($negative) { $bits = bits_add_one(bits_invert($bits)); } /* Return the bits. */ return $bits; }
function bignum_to_bits($bignum) { if ($negative = bignum_is_negative($bignum)) { $bignum = bignum_abs($bignum); } $bits = positive_bignum_to_bits($bignum); $bits = bits_prefix_with_zero_if_needed($bits); if ($negative) { $bits = bits_add_one(bits_invert($bits)); } return $bits; }
Odstranění víceméně zbytečných komentářů
function bignum_to_bits($bignum) { if ($negative = bignum_is_negative($bignum)) { $bignum = bignum_abs($bignum); } $bits = positive_bignum_to_bits($bignum); $bits = bits_prefix_with_zero_if_needed($bits); if ($negative) { $bits = bits_add_one(bits_invert($bits)); } return $bits; } |
Remember if the value is negative. If the value is negative, trim the sign (i.e. compute the absolute value). Compute the bits of the absolute value (using standard algorithm). If the first bit is non-zero, prefix the bits with zero bit. If the number was negative, invert the bits and add one. Return the bits. |
Potřebuji proceduru, která vypíše chybovou hlášku odpovídající zadanému chybovému kódu.
ReportErrorMessage()
takes an error code as an input argument and
outputs an error message corresponding to the code.
It's responsible for handling invalid codes.
If the program is operating interactively, the procedure displays the error message to the user.
If it's operating in command line mode, the procedure logs the message to a message file.
After outputting the message, the procedure returns a status value indicating whether it succeeded or failed.
Požadavky jsou (snad) jasné a funkce se jeví jako logicky ucelená a "rozumná".
Success
nebo Failure
set the default status to "fail" look up the message based on the error code if the error code is valid if doing interactive processing, display the error message interactively and declare success if doing command line processing, log the error message to the message file and declare success if the error code isn't valid, notify the user that an internal error has been detected return status information
Napište v jazyce C funkci, která zkopíruje soubor na jiné místo. Funkce vrátí nenulovou hodnotu, pokud se zkopírování povedlo, jinak vrátí nulu.
Funkce nejdříve popište v pseudokódu, teprve pak napište implementaci v C.
goto
stdio.h
)FILE *fopen(const char *filename, const char *mode)
int fclose(FILE *stream)
int feof(FILE *stream)
size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream)
nitems
položek o velikosti size
do bufferu ptr
.
Vrací počet načtených položek.
Návratová hodnota 0 může znamenat jak pokus o čtení na konci souboru, tak chybu. size_t fwrite(void *ptr, size_t size, size_t nitems, FILE *stream)
nitems
položek o velikosti size
z bufferu ptr
.
Vrací počet zapsaných položek.
Pokud je návratová hodnota menší než nitems
, znamená to chybu. #define FALSE 0 #define TRUE (!FALSE) #define BUFFER_SIZE 4096 int copy_file(const char *src_filename, const char *dest_filename) { FILE *src_file = NULL; FILE *dest_file = NULL; if (src_filename == NULL) { return FALSE; } if (dest_filename == NULL) { return FALSE; } src_file = fopen(src_filename, "r"); if (src_file == NULL) { goto error_no_cleanup; } dest_file = fopen(dest_filename, "w"); if (dest_file == NULL) { goto error_cleanup_src; } while (!feof(src_file)) { char buffer[BUFFER_SIZE]; size_t bytes_read, bytes_written; bytes_read = fread(buffer, sizeof(char), BUFFER_SIZE, src_file); if (bytes_read == 0) { goto error_cleanup_both; } bytes_written = fwrite(buffer, sizeof(char), bytes_read, dest_file); if (bytes_written < bytes_read) { goto error_cleanup_both; } } if (fclose(dest_file)) { goto error_cleanup_src; } if (fclose(src_file)) { goto error_no_cleanup; } return TRUE; error_cleanup_both: fclose(dest_file); error_cleanup_src: fclose(src_file); error_no_cleanup: return FALSE; }
<body> <div id="nice-logo"><!-- Site logo --></div> <div id="leftbar"><!-- Navigation --></div> <div id="content"> <!-- Actual content --> <h2 class="big-blue">Comments</h2> <!-- Readers' comments --> </div> <div id="footer"><!-- Copyright, ... --></div> </body>
<body> <div id="nice-logo"><!-- Site logo --></div> <div id="leftbar"><!-- Navigation --></div> <div id="content"> <!-- Actual content --> <h2 class="big-blue">Comments</h2> <!-- Readers' comments --> </div> <div id="footer"><!-- Copyright, ... --></div> </body>
<body> <div id="top-logo"><!-- Site logo --></div> <div id="navigation"><!-- Navigation --></div> <div id="content"> <!-- Actual content --> <h2 class="comments">Comments</h2> <!-- Readers' comments --> </div> <div id="footer"><!-- Copyright, ... --></div> </body>
bool pointInRect(int x, int y, int x1, int y1, int x2, int y2) { return x >= x1 && x <= x2 && y >= y1 && y <= y2; }
bool pointInRect(int x, int y, int x1, int y1, int x2, int y2) { return x >= x1 && x <= x2 && y >= y1 && y <= y2; }
bool pointInRect(int x, int y, int left, int top, int right, int bottom) { return x >= left && x <= right && y >= top && y <= bottom; }
isPointInRectangle
, pointIsInRect
...)bool pointInRect(Point point, Rect rect) { return point.getX() >= rect.getLeft() && point.getX() <= rect.getRight() && point.getY() >= rect.getTop() && point.getY() <= rect.getBottom(); }
if (*curr_pos == '/') { curr_pos++; if (*curr_pos == '/') { curr_pos++; while (*curr_pos && !is_newline(*curr_pos)) { curr_pos++; } } else { return NULL; } } else { return NULL; }
if (*curr_pos == '/') { curr_pos++; if (*curr_pos == '/') { curr_pos++; while (*curr_pos && !is_newline(*curr_pos)) { curr_pos++; } } else { return NULL; } } else { return NULL; }
if (*curr_pos != '/') { return NULL; } curr_pos++; if (*curr_pos != '/') { return NULL; } curr_pos++; while (*curr_pos && !is_newline(*curr_pos)) { curr_pos++; }
array.h
Opravte rozhraní C++ třídy zapouzdřující práci s polem.
Napište pseudokód funkce, která hledá soubor daného jména v určených adresářích. Hledání navíc dokáže rozpoznat archivy a hledat soubor i v nich.
Vstupem funkce je seznam míst, kde hledat a jaký soubor, výstupem pak seznam umístění.
.zip
, .tar.gz
apod.