refactor
This commit is contained in:
parent
7c888a3dd0
commit
5d9fc7d18d
11 changed files with 247 additions and 297 deletions
21
README.md
Normal file
21
README.md
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
```
|
||||||
|
// Generates a random.txt file with parameters specified, and exits
|
||||||
|
// parameters besides N, are only used internally to specify how big are the chunks written
|
||||||
|
<main> -g -N 100000 -b 10 -n 101 -o <filename>
|
||||||
|
|
||||||
|
// Sort the input file, using the temporary dir, and the parameters specified, save to the output file
|
||||||
|
<main> -i <input-file> -o <output-file> -d <tmp dir> -N 100000 -b 10 -n 101
|
||||||
|
|
||||||
|
// If no option is specified, system will prompt for parameters, and use the input data from stdin
|
||||||
|
<main>
|
||||||
|
```
|
||||||
|
|
||||||
|
- option `-i` implies the program is supposed to sort something, and thus is incompatible with `-g`
|
||||||
|
- when a parameter is not specified the default values are used:
|
||||||
|
- i = "1.in"
|
||||||
|
- o = "1.out"
|
||||||
|
- d = "tmp"
|
||||||
|
- g isn't set (false)
|
||||||
|
- N = 100000
|
||||||
|
- b = 10
|
||||||
|
- n = 101
|
||||||
43
buffer.c
Normal file
43
buffer.c
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "record.h"
|
||||||
|
#include "status_codes.h"
|
||||||
|
|
||||||
|
buffer create_buffer(int capacity)
|
||||||
|
{
|
||||||
|
buffer out;
|
||||||
|
out.length = 0;
|
||||||
|
out.capacity = capacity;
|
||||||
|
out.location = malloc(sizeof(record) * capacity);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_buffer(buffer* buff, FILE* in)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
record* current = buff->location;
|
||||||
|
buff->length = 0;
|
||||||
|
for (int i = 0; i < buff->capacity; i++) {
|
||||||
|
status = read_record(in, current);
|
||||||
|
if (status != SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
buff->length++;
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_buffer(buffer* buff, FILE* out)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
record* current = buff->location;
|
||||||
|
for (int i = 0; i < buff->length; i++) {
|
||||||
|
status = print_record(out, current);
|
||||||
|
if (status < 0) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
fprintf(out, "\n");
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
12
buffer.h
Normal file
12
buffer.h
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
#include "record.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
record* location;
|
||||||
|
int length;
|
||||||
|
int capacity;
|
||||||
|
} buffer;
|
||||||
|
|
||||||
|
buffer create_buffer(int capacity);
|
||||||
|
int read_buffer(buffer* buff, FILE* in);
|
||||||
|
int write_buffer(buffer* buff, FILE* in);
|
||||||
52
config.c
Normal file
52
config.c
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include "config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int process_args(int argc, char** argv, Configuration* opts)
|
||||||
|
{
|
||||||
|
opts->input_file = DEFAULT_IN;
|
||||||
|
opts->output_file = DEFAULT_OUT;
|
||||||
|
opts->directory = DEFAULT_DIR;
|
||||||
|
opts->generate_data = false;
|
||||||
|
opts->N = DEFAULT_NN;
|
||||||
|
opts->n = DEFAULT_N;
|
||||||
|
opts->b = DEFAULT_B;
|
||||||
|
int opt;
|
||||||
|
bool input_set = false;
|
||||||
|
while ((opt = getopt(argc, argv, "i:o:d:gN:n:b:")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'i':
|
||||||
|
opts->input_file = optarg;
|
||||||
|
input_set = true;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
opts->output_file = optarg;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
opts->directory = optarg;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
opts->generate_data = true;
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
opts->N = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
opts->n = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
opts->b = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
printf("wrong argument\n");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (opts->generate_data && input_set) {
|
||||||
|
printf("incompatible arguments\n");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
23
config.h
Normal file
23
config.h
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
#include "status_codes.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define DEFAULT_IN "1.in"
|
||||||
|
#define DEFAULT_OUT "1.in"
|
||||||
|
#define DEFAULT_DIR "tmp"
|
||||||
|
#define DEFAULT_NN 100000
|
||||||
|
#define DEFAULT_N 101
|
||||||
|
#define DEFAULT_B 10
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char* input_file;
|
||||||
|
const char* output_file;
|
||||||
|
const char* directory;
|
||||||
|
bool generate_data;
|
||||||
|
int N; // number of records in a file
|
||||||
|
int b; // blocking factor
|
||||||
|
int n; // number of buffers
|
||||||
|
} Configuration;
|
||||||
|
|
||||||
|
int process_args(int argc, char** argv, Configuration* opts);
|
||||||
221
main.c
221
main.c
|
|
@ -1,167 +1,62 @@
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "config.h"
|
||||||
#include "record.h"
|
#include "record.h"
|
||||||
#include "tape.h"
|
#include "status_codes.h"
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define DEFAULT_FILE "tests/1.in"
|
int generate_file(int N, const char* filename)
|
||||||
#define DEFAULT_DIR "tmp"
|
|
||||||
#define DEFAULT_NN 100000
|
|
||||||
#define DEFAULT_N 101
|
|
||||||
#define DEFAULT_B 10
|
|
||||||
#define END_PROGRAM -1
|
|
||||||
#define SUCCESS 0
|
|
||||||
#define ERROR -2
|
|
||||||
|
|
||||||
void print_usage()
|
|
||||||
{
|
{
|
||||||
printf("Options:\n");
|
srand(time(0));
|
||||||
printf(" -f [filename]\tRead/Generate records from [filename], default %s\n", DEFAULT_FILE);
|
FILE* f = fopen(filename, "w");
|
||||||
printf(" -d [dirname]\tSet the directory used for temporary files, default %s\n", DEFAULT_DIR);
|
record rec;
|
||||||
printf(" -N [count]\tSet total number of records, default %d\n", DEFAULT_NN);
|
|
||||||
printf(" -n [count]\tSet blocking factor, default %d\n", DEFAULT_N);
|
|
||||||
printf(" -b [count]\tSet number of buffers, default %d\n", DEFAULT_B);
|
|
||||||
printf(" -r\t randomly generate N records\n");
|
|
||||||
printf(" -h\tShow this help message\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct
|
for (int i = 0; i < N; i++) {
|
||||||
{
|
random_record(&rec);
|
||||||
FILE* input;
|
print_record(f, &rec);
|
||||||
char* filename;
|
fprintf(f, "\n");
|
||||||
char* dirname;
|
|
||||||
bool generate_data;
|
|
||||||
bool manual_input;
|
|
||||||
int N; // number of records in a file
|
|
||||||
int b; // blocking factor
|
|
||||||
int n; // number of buffers
|
|
||||||
} options;
|
|
||||||
|
|
||||||
// reads args into opts
|
|
||||||
int process_args(int argc, char** argv, options* opts)
|
|
||||||
{
|
|
||||||
if (opts == NULL) {
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
opts->input = stdin;
|
|
||||||
opts->filename = DEFAULT_FILE;
|
|
||||||
opts->dirname = DEFAULT_DIR;
|
|
||||||
opts->generate_data = false;
|
|
||||||
opts->manual_input = false;
|
|
||||||
opts->N = DEFAULT_NN;
|
|
||||||
opts->n = DEFAULT_N;
|
|
||||||
opts->b = DEFAULT_B;
|
|
||||||
int opt;
|
|
||||||
while ((opt = getopt(argc, argv, "f:d:N:n:b:rhm")) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case 'f':
|
|
||||||
opts->filename = optarg;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
opts->dirname = optarg;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
opts->generate_data = true;
|
|
||||||
break;
|
|
||||||
case 'N':
|
|
||||||
opts->N = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
opts->n = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
opts->b = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
opts->manual_input = true;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
print_usage();
|
|
||||||
return END_PROGRAM;
|
|
||||||
case '?':
|
|
||||||
fprintf(stderr, "invalid option, terminating\n");
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (opts->manual_input == true && opts->generate_data == true) {
|
|
||||||
fprintf(stderr, "Incompatible arguments: mr, aborting\n");
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
opts->input = fopen(opts->filename, "r+");
|
|
||||||
if (!opts->input) {
|
|
||||||
opts->input = fopen(opts->filename, "w+");
|
|
||||||
}
|
|
||||||
if (!opts->input) {
|
|
||||||
fprintf(stderr, "Error: Cannot open file '%s'\n", opts->filename);
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
struct stat st = { 0 };
|
|
||||||
if (stat(opts->dirname, &st) == -1) {
|
|
||||||
mkdir(opts->dirname, 0777);
|
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_file(options* opts)
|
int sort_file(Configuration* opts)
|
||||||
{
|
{
|
||||||
srand(time(0));
|
// create buffer
|
||||||
record rec;
|
buffer buff = create_buffer(opts->b * opts->n);
|
||||||
for (int i = 0; i < opts->N; i++) {
|
// open file
|
||||||
random_record(&rec);
|
FILE* in = fopen(opts->input_file, "r");
|
||||||
print_record(opts->input, &rec);
|
// <stage 1>
|
||||||
fprintf(opts->input, "\n");
|
// while !eof:
|
||||||
}
|
for (int i = 0; true; i++) {
|
||||||
fseek(opts->input, 0, SEEK_SET);
|
// read buffer
|
||||||
}
|
int status = read_buffer(&buff, in);
|
||||||
|
printf("buffer i:%d, status: %d\n", i, status);
|
||||||
|
// sort buffer
|
||||||
|
|
||||||
void write_file(options* opts)
|
// write run
|
||||||
{
|
write_buffer(&buff, stdout);
|
||||||
}
|
if (status != SUCCESS) {
|
||||||
|
break;
|
||||||
int sort_block(tape* t, buffer* buff)
|
}
|
||||||
{
|
|
||||||
static int counter = 0;
|
|
||||||
int status = read_buffer(buff, t);
|
|
||||||
if (status != SUCCESS && status != EOF) {
|
|
||||||
fprintf(stderr, "Error reading file: %d\n", status);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
sort_buffer(buff);
|
|
||||||
printf("sorted the buffer %d, the results:\n", counter);
|
|
||||||
print_buffer(buff);
|
|
||||||
counter++;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sort_file(options* opts)
|
|
||||||
{
|
|
||||||
tape a = { 0, 0, opts->input };
|
|
||||||
buffer buff;
|
|
||||||
buff.capacity = opts->b * opts->n;
|
|
||||||
buff.location = malloc(sizeof(record) * buff.capacity);
|
|
||||||
int status = 0;
|
|
||||||
while (status == SUCCESS) {
|
|
||||||
status = sort_block(&a, &buff);
|
|
||||||
}
|
|
||||||
if (status != EOF) {
|
|
||||||
free(buff.location);
|
|
||||||
fclose(a.file);
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
// <stage 2>
|
||||||
|
// while tmp:
|
||||||
|
// merge b-1 runs
|
||||||
|
//
|
||||||
|
// close file
|
||||||
|
// free buffer
|
||||||
|
fclose(in);
|
||||||
free(buff.location);
|
free(buff.location);
|
||||||
fclose(a.file);
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
options opts;
|
Configuration opts;
|
||||||
if (argc <= 1) {
|
if (argc <= 1) {
|
||||||
|
// #todo: stdin input
|
||||||
fprintf(stderr, "please specify input args\n");
|
fprintf(stderr, "please specify input args\n");
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
@ -170,12 +65,42 @@ int main(int argc, char** argv)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (opts.generate_data) {
|
if (opts.generate_data) {
|
||||||
generate_file(&opts);
|
return generate_file(opts.N, opts.output_file);
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
if (opts.manual_input) {
|
|
||||||
write_file(&opts);
|
|
||||||
}
|
}
|
||||||
sort_file(&opts);
|
sort_file(&opts);
|
||||||
fclose(opts.input);
|
|
||||||
}
|
}
|
||||||
|
// int sort_block(tape* t, buffer* buff)
|
||||||
|
// {
|
||||||
|
// static int counter = 0;
|
||||||
|
// int status = read_buffer(buff, t);
|
||||||
|
// if (status != SUCCESS && status != EOF) {
|
||||||
|
// fprintf(stderr, "Error reading file: %d\n", status);
|
||||||
|
// return status;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// sort_buffer(buff);
|
||||||
|
// printf("sorted the buffer %d, the results:\n", counter);
|
||||||
|
// print_buffer(buff);
|
||||||
|
// counter++;
|
||||||
|
// return status;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int sort_file(options* opts)
|
||||||
|
// {
|
||||||
|
// tape a = { 0, 0, opts->input };
|
||||||
|
// buffer buff;
|
||||||
|
// buff.capacity = opts->b * opts->n;
|
||||||
|
// buff.location = malloc(sizeof(record) * buff.capacity);
|
||||||
|
// int status = 0;
|
||||||
|
// while (status == SUCCESS) {
|
||||||
|
// status = sort_block(&a, &buff);
|
||||||
|
// }
|
||||||
|
// if (status != EOF) {
|
||||||
|
// free(buff.location);
|
||||||
|
// fclose(a.file);
|
||||||
|
// return status;
|
||||||
|
// }
|
||||||
|
// free(buff.location);
|
||||||
|
// fclose(a.file);
|
||||||
|
// return SUCCESS;
|
||||||
|
// }
|
||||||
|
|
|
||||||
29
makefile
29
makefile
|
|
@ -1,30 +1,33 @@
|
||||||
CFLAGS = -g
|
CFLAGS = -g
|
||||||
|
|
||||||
build/main: build/main.o build/tape.o build
|
build/main: build/main.o build/config.o build/buffer.o
|
||||||
clang $(CFLAGS) build/main.o build/tape.o -o build/main
|
clang $(CFLAGS) build/main.o build/config.o build/buffer.o -o build/main
|
||||||
|
|
||||||
build/main.o: main.c build
|
build/main.o: main.c build
|
||||||
clang $(CFLAGS) -c main.c -o build/main.o
|
clang $(CFLAGS) -c main.c -o build/main.o
|
||||||
|
|
||||||
build/tape.o: tape.c build
|
build/config.o: config.c build
|
||||||
clang $(CFLAGS) -c tape.c -o build/tape.o
|
clang $(CFLAGS) -c config.c -o build/config.o
|
||||||
|
|
||||||
|
build/buffer.o: buffer.c build
|
||||||
|
clang $(CFLAGS) -c buffer.c -o build/buffer.o
|
||||||
|
|
||||||
build:
|
build:
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
|
|
||||||
tests:
|
build/run: build
|
||||||
mkdir -p tests
|
mkdir -p build/run
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf build tests tmp
|
rm -rf build
|
||||||
|
|
||||||
run: build/main tests/1.in
|
build/run/1.in: build/run build/main
|
||||||
build/main -f tests/1.in | less
|
build/main -g -o build/run/1.in
|
||||||
|
|
||||||
|
run: build/main build/run/1.in
|
||||||
|
build/main -i build/run/1.in | less
|
||||||
|
|
||||||
debug: build/main tests/1.in
|
debug: build/main tests/1.in
|
||||||
lldb -- build/main -f tests/1.in
|
lldb -- build/main
|
||||||
|
|
||||||
tests/1.in: build/main tests
|
|
||||||
build/main -f tests/1.in -r
|
|
||||||
|
|
||||||
.PHONY: clean run debug
|
.PHONY: clean run debug
|
||||||
|
|
|
||||||
4
record.h
4
record.h
|
|
@ -28,9 +28,9 @@ static inline int compare_records(const void* a, const void* b)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void print_record(FILE* stream, const record* out)
|
static inline int print_record(FILE* stream, const record* out)
|
||||||
{
|
{
|
||||||
fprintf(stream, "%d %d %d %d %d %d",
|
return fprintf(stream, "%d %d %d %d %d %d",
|
||||||
out->a[0], out->a[1], out->a[2], out->a[3], out->a[4], out->x);
|
out->a[0], out->a[1], out->a[2], out->a[3], out->a[4], out->x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
5
status_codes.h
Normal file
5
status_codes.h
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define END_PROGRAM -1
|
||||||
|
#define SUCCESS 0
|
||||||
|
#define ERROR -2
|
||||||
108
tape.c
108
tape.c
|
|
@ -1,108 +0,0 @@
|
||||||
#include "record.h"
|
|
||||||
#include "tape.h"
|
|
||||||
|
|
||||||
int partition(record* arr, int start, int end)
|
|
||||||
{
|
|
||||||
int i = start;
|
|
||||||
record* pivot = arr;
|
|
||||||
pivot += end;
|
|
||||||
for (int j = start; j < end; j++) {
|
|
||||||
record* current = arr;
|
|
||||||
current += j;
|
|
||||||
if (compare_records(current, pivot) > 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
record* i_rec = arr;
|
|
||||||
i_rec += i;
|
|
||||||
record tmp = *i_rec;
|
|
||||||
*i_rec = *current;
|
|
||||||
*current = tmp;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
record* i_rec = arr;
|
|
||||||
i_rec += i;
|
|
||||||
record tmp = *i_rec;
|
|
||||||
*i_rec = *pivot;
|
|
||||||
*pivot = tmp;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
void quicksort(record* arr, int start, int end, int depth)
|
|
||||||
{
|
|
||||||
if (start >= end || start < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int p = partition(arr, start, end);
|
|
||||||
quicksort(arr, start, p - 1, depth + 1);
|
|
||||||
quicksort(arr, p + 1, end, depth + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sort_buffer(buffer* buff)
|
|
||||||
{
|
|
||||||
quicksort(buff->location, 0, buff->length - 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int read_buffer(buffer* buff, tape* tape)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
record* destination = buff->location;
|
|
||||||
buff->length = 0;
|
|
||||||
while (buff->capacity > buff->length) {
|
|
||||||
status = read_record(tape->file, destination);
|
|
||||||
if (status != 0) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
destination++;
|
|
||||||
buff->length++;
|
|
||||||
tape->reads++;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_full_buffer(buffer* buff)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < buff->length; i++) {
|
|
||||||
record* current = buff->location;
|
|
||||||
current += i;
|
|
||||||
printf("i: %d\tg: %d\t", i, g(current));
|
|
||||||
print_record(stdout, current);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_buffer(buffer* buff)
|
|
||||||
{
|
|
||||||
if (buff->length <= 10) {
|
|
||||||
print_full_buffer(buff);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
record* current = buff->location;
|
|
||||||
current += i;
|
|
||||||
printf("i: %d\tg: %d\t", i, g(current));
|
|
||||||
print_record(stdout, current);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
for (int i = buff->length - 5; i < buff->length; i++) {
|
|
||||||
record* current = buff->location;
|
|
||||||
current += i;
|
|
||||||
printf("i: %d\tg: %d\t", i, g(current));
|
|
||||||
print_record(stdout, current);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int write_buffer(buffer* buff, tape* tape)
|
|
||||||
{
|
|
||||||
record* current = buff->location;
|
|
||||||
record* last = current;
|
|
||||||
last += buff->length;
|
|
||||||
while (current < last) {
|
|
||||||
print_record(tape->file, current);
|
|
||||||
fprintf(tape->file, "\n");
|
|
||||||
current++;
|
|
||||||
tape->reads++;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
26
tape.h
26
tape.h
|
|
@ -1,26 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int reads;
|
|
||||||
int writes;
|
|
||||||
FILE* file;
|
|
||||||
} tape;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
void* location;
|
|
||||||
int length;
|
|
||||||
int capacity;
|
|
||||||
} buffer;
|
|
||||||
|
|
||||||
// sorts the entire buffer
|
|
||||||
void sort_buffer(buffer* buff);
|
|
||||||
|
|
||||||
// reads [capacity] records
|
|
||||||
int read_buffer(buffer* buff, tape* tape);
|
|
||||||
// writes everything
|
|
||||||
int write_buffer(buffer* buff, tape* tape);
|
|
||||||
// for debugging
|
|
||||||
void print_buffer(buffer* buff);
|
|
||||||
|
|
||||||
void clear_tape(tape* tape);
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue