Здравствуйте. Мне опять нужна ваша помощь. Программа для отгадывания правильного числа написана (guess.c). Дано число (secret number) и кто из участников ближе к правильному ответу, тот и побеждает. У каждого участника есть 3 попытки и не более для угадывания правильного числа. В текстовый файл сохраняются данные.
Вот программа guess.c
Код | #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <unistd.h>
#define FALSE (0) #define TRUE (1)
// Important definitions // #define MAX_TRIES (3)
typedef struct guess_record { int uid; int tries; int guess; } guess_record;
// check if a new guess is better than the old one // int is_better(int secret_number, int old_guess, int new_guess) { int old_distance = secret_number - old_guess; if( old_distance < 0 ) old_distance = -old_distance;
int new_distance = secret_number - new_guess; if( new_distance < 0 ) new_distance = -new_distance;
if( new_distance < old_distance ) return 1; return 0; }
// make a guess, if more tries are allowed // void make_a_guess(guess_record* guessrec, int secret_number, int guess) { if( guessrec->tries < MAX_TRIES ) { guessrec->tries = guessrec->tries + 1; if( is_better(secret_number, guessrec->guess, guess) ) { guessrec->guess = guess; } } }
// where all the work is done // int main(int argc, char** argv) { int uid = -1; int nums[MAX_TRIES]; int tries = 0; int secret_number = 0; guess_record* guessdb = NULL; int dbcount = 0;
// get uid (remember getpwuid is the way to map uid -> user_name_str) // { uid = getuid(); }
// get the current tries // { char** trystr = &argv[1]; int i;
for(i = 0; *trystr != NULL; ++i, ++trystr) { nums[i] = atoi(*trystr); ++tries; } }
if( tries == 0 ) { printf("Usage: doguess guess1 [[guess2] ... [guess_MAX_TRIES]]\n"); return -1; }
// read the secret number // { FILE* inf = fopen("secretnum.txt", "rt"); if( inf == NULL ) { printf("The secret number file secretnum.txt must exist\n"); return -1; }
fscanf(inf, "%d\n", &secret_number); fclose(inf); }
// read the guess db // { int i; // get the old records, with space allocated for one more
FILE* inf = fopen("guesses.txt", "rt"); if( inf == NULL ) { printf("The db file guesses.txt must exist\n"); return -1; }
fscanf(inf, "%d\n", &dbcount); guessdb = (guess_record*)calloc( dbcount+1, sizeof(guess_record) );
for(i = 0; i < dbcount; ++i) { fscanf(inf, "%d,%d,%d\n", & (guessdb[i].uid), & (guessdb[i].tries), & (guessdb[i].guess)); } fclose(inf); }
// update the guess db // { int is_already_updated = FALSE; int i;
// update in place, if already in db for(i = 0; i < dbcount; ++i) { if(guessdb[i].uid == uid) { int j; is_already_updated = TRUE;
for(j = 0; j < tries; ++j) { make_a_guess( &guessdb[i], secret_number, nums[j] ); } } }
// otherwise add to db if( ! is_already_updated ) { int j;
// add the initial guess guessdb[dbcount].uid = uid; guessdb[dbcount].tries = 1; guessdb[dbcount].guess = nums[0];
// make remaining guesses for(j = 1; j < tries; ++j) { make_a_guess( &guessdb[dbcount], secret_number, nums[j] ); }
// include row in db ++dbcount; } }
// write the updated guess db // { FILE* outf = fopen("guesses.txt", "wt");
int i; fprintf(outf, "%d\n", dbcount);
for(i = 0; i < dbcount; ++i) { fprintf(outf, "%d,%d,%d\n", guessdb[i].uid, guessdb[i].tries, guessdb[i].guess); }
fclose(outf); }
return 0; }
|
Преподователи не любят читать этот текстовый файл (guesses.txt) потому что он не отсортированный и использует идентификационные номара юзеров вместо имен.
Надо написать программу на С, файл назвать printguess.c, которая будет печатать 5 наиболее верных ответа с именами (вместо идентификационных номеров юзеров) кто отгадывал. Ограничения доступа к файлам должны быть:
"secretnum.txt" хранит точные данные дней и только программа имеет доступ к этим данным (contains the correct number of days and should only be accessible by the program itself.)
"guesses.txt" только программа имеет доступ к этому файлу (should only be accessible by the program itself.)
"mkguess" выполнять программу может только юзеры которые имеют доступ к отгадыванию чисел. ( the executable should only be runnable by users that are allowed to compete. Also, because the program may contain exploitable vulnerabilities, it should not run with administrative privileges, but with less privilege.)
(к сожалению концовка мне не понятна, пожалуйста посмотрите в английской версии).
Make use of the qsort standard C function and the getpwuid Unix routine to do the work. To make use of qsort, you need a comparison function. It will look something like the following:
функция для сравнения чисел в дальнейшем для установления 5-ти победителей:
Код |
int secret_number; int guess_distance(int guess) { int distance = secret_number - guess; if( distance < 0 ) distance = -distance; return distance; } int compare_guesses(const void* one, const void* one) { return guess_distance(((guess_record*)one)->guess) - guess_distance(((guess_record*)two)->guess); }
|
|