This commit is contained in:
bronku 2025-10-14 16:35:41 +02:00
parent 2b222dda0b
commit 3b1db93d74
5 changed files with 126 additions and 72 deletions

11
TODO.md
View file

@ -1,14 +1,13 @@
- [ ] file operations - [ ] file operations
- [ ] write to file (at index) - [ ] write to file (at index)
- [ ] read from file (at index)
- [ ] print_file (maybe just calling cat???) - [ ] print_file (maybe just calling cat???)
- [ ] a tape type - representing a file? - [ ] a tape type - representing a file?
- [x] a record type - x1,x2,x3,x4,x5 - [x] a record type - x1,x2,x3,x4,x5
- [x] comparing records - [x] comparing records
- [ ] natural merge sort - [ ] buffer merge sort
- [ ] configuration - [x] configuration
- [ ] cmd args - man getopts - [x] cmd args - man getopts
- [ ] file input - [x] file input
- [ ] keyboard input - [x] keyboard input
- [ ] testing - [ ] testing
- [ ] report - [ ] report

125
main.c
View file

@ -1,89 +1,124 @@
#include "record.h" #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#define MAX_RECORDS 1000 #define DEFAULT_NN 10000000
#define DEFAULT_N 1001
#define DEFAULT_B 10
#define END_PROGRAM -1 #define END_PROGRAM -1
#define SUCCESS 0 #define SUCCESS 0
#define ERROR -2 #define ERROR -2
void print_usage() void print_usage()
{ {
printf("Usage: [-f filename] [-h]\n");
printf("Options:\n"); printf("Options:\n");
printf(" -f filename\tRead records from file\n"); printf(" -f [filename]\tRead/Generate records from [filename]\n");
printf(" -h\tShow this help message"); printf(" -r\t randomly generate N records, and process them\n");
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(" -h\tShow this help message\n");
} }
// stream is function output typedef struct
int process_args(int argc, char** argv, FILE** stream)
{ {
FILE* input;
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->generate_data = false;
opts->manual_input = false;
opts->N = DEFAULT_NN;
opts->n = DEFAULT_N;
opts->b = DEFAULT_B;
char* filename = NULL; char* filename = NULL;
int opt; int opt;
while ((opt = getopt(argc, argv, "f:h")) != -1) { while ((opt = getopt(argc, argv, "f:N:n:b:rhm")) != -1) {
switch (opt) { switch (opt) {
case 'f': case 'f':
filename = optarg; filename = optarg;
break; 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;
case 'h': case 'h':
print_usage(); print_usage();
return END_PROGRAM; return END_PROGRAM;
case '?': case '?':
printf("invalid option, terminating\n"); fprintf(stderr, "invalid option, terminating\n");
return ERROR; return ERROR;
} }
} }
if (filename != NULL) { if (opts->manual_input == true && opts->generate_data == true) {
printf("%s\n", filename); fprintf(stderr, "Incompatible arguments: mr, aborting\n");
*stream = fopen(filename, "r"); return ERROR;
if (!*stream) {
fprintf(stderr, "Error: Cannot open file '%s'\n", filename);
return END_PROGRAM;
} }
if (filename == NULL) {
fprintf(stderr, "No file specified, aborting\n");
return ERROR;
}
opts->input = fopen(filename, "a+");
if (!opts->input) {
fprintf(stderr, "Error: Cannot open file '%s'\n", filename);
return ERROR;
} }
return SUCCESS; return SUCCESS;
} }
void process_input(FILE* input) void generate_file(options* opts)
{ {
record records[MAX_RECORDS]; }
int count = 0;
while (count < MAX_RECORDS) {
if (read_record(input, &records[count]) != SUCCESS) {
break;
}
count++;
}
printf("\nRead %d records\n", count); void write_file(options* opts)
qsort(records, count, sizeof(record), compare_records); {
printf("\nSorted records:\n"); }
for (int i = 0; i < count; i++) {
printf("Record %d: ", i); void sort_file(options* opts)
print_record(stdout, &records[i]); {
printf("\n");
}
} }
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
FILE* input = NULL; options opts;
if (argc > 1) { if (argc <= 1) {
int result = process_args(argc, argv, &input); fprintf(stderr, "please specify input args\n");
return ERROR;
}
int result = process_args(argc, argv, &opts);
if (result != SUCCESS) { if (result != SUCCESS) {
return result; return result;
} }
if (input == NULL) { if (opts.generate_data) {
printf("ok\n"); srand(time(0));
generate_file(&opts);
} }
if (opts.manual_input) {
write_file(&opts);
} }
if (input == NULL) { sort_file(&opts);
printf("Enter records (format: a_0 a_1 a_2 a_3 a_4 x), or 'q' to quit:\n"); fclose(opts.input);
input = stdin;
}
process_input(input);
if (input != stdin) {
fclose(input);
}
} }

View file

@ -1,25 +1,13 @@
# Compiler build/main: main.c build
CC = clang clang main.c -o build/main
CFLAGS = -Wall -Wextra -g
TARGET = file_sorting
BUILD_DIR = build
SRCS = main.c build:
OBJS = $(SRCS:%.c=$(BUILD_DIR)/%.o) mkdir -p build
$(BUILD_DIR)/$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(BUILD_DIR)/$(TARGET)
$(BUILD_DIR)/%.o: %.c | $(BUILD_DIR)
$(CC) $(CFLAGS) -c $< -o $@
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
clean: clean:
rm -rf build rm -rf build
run: $(BUILD_DIR)/$(TARGET) run: build/main
$(BUILD_DIR)/$(TARGET) build/main -f tests/1.in
.PHONY: clean run .PHONY: clean run

View file

@ -43,3 +43,11 @@ static inline int read_record(FILE* stream, record* out)
} }
return -2; return -2;
} }
static inline void random_record(record* out)
{
for (int i = 0; i < 5; i++) {
out->a[i] = rand();
}
out->x = rand();
}

24
tape.h Normal file
View file

@ -0,0 +1,24 @@
#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 quicksort(buffer* buff);
// reads [capacity] records
void read_buffer(buffer* buff, tape* tape);
// writes everything
void write_buffer(buffer* buff, tape* tape);
void clear_tape(tape* tape);