Introducing the "C-- database", the solution to "C/C++ language".
We noticed that the famous “the matrix” is made up of only four ideas: Sound (no evil), Complete (yes good), Unsound (yes evil), Incomplete (no good). So what? What is the pragmatic value of this finding? Well, if we have a need to help an accountant, we'll make a small “accounting book” app. This is “sound”. But then, we'll notice we can make this new feature and that new feature. This is us trying to be “complete”. Unfortunately, the more lines of code we write, the higher the chances of us making a mistake. This is the “unsound” that is inextricably linked to the “complete”. So, we are honest with the accountant, and we tell him that the small app is better for him, since in computing, very often, if not always, “less is more”. This is us remaining “incomplete” to avoid the “complete + unsound” problem. Very nice! We are now practicing “masters” of computer science. The client is not our king, “santa simplicita” is our king, and it shows in all of our products. What if, at work, they make us bow to the client? We’ll quit. This is an existential threat to our sanity and professional integrity.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
const char *field[] = {"Id", "Name", "Note", "Date", "Amount"};
#define COLUMNS sizeof(field)/sizeof(field[0])
#define ROWS 65000
typedef struct { char f[COLUMNS][256]; } Row;
Row t[ROWS];
int count = 0, sel = 0;
const char *fn = "db.bin";
void save() {
FILE *f = fopen(fn, "wb");
if (f) { fwrite(t, sizeof(Row), count, f); fclose(f); }
}
void append() {
for (int i = 0; i < COLUMNS; i++) {
printf("Enter field %d (%s): ", i, field[i]);
scanf(" %255[^\n]", t[count].f[i]);
}
}
void verify() {
printf("Id | Amount | \n");
for (int i = 0; i < count; i++) {
printf("%s | %s (number: %f) | \n", t[i].f[0], t[i].f[sel], atof(t[i].f[sel]));
}
// Calculations
double total = 0.0;
for (int i = 0; i < count; i++) {
double value = atof(t[i].f[sel]);
total += value;
}
printf("\nSum of Amount is: %f\n", total);
}
void display(FILE *stream) {
// Header
fprintf(stream, "[0] ");
for (int j = 0; j < COLUMNS; j++) fprintf(stream, "%s | ", field[j]);
fprintf(stream, "\n");
// Data Rows
for (int i = 0; i < count; i++) {
fprintf(stream, "[%d] ", i + 1);
for (int j = 0; j < COLUMNS; j++) fprintf(stream, "%s | ", t[i].f[j]);
fprintf(stream, "\n");
}
// Calculations
double total = 0.0;
double min = (count > 0) ? atof(t[0].f[sel]) : 0.0;
double max = (count > 0) ? atof(t[0].f[sel]) : 0.0;
for (int i = 0; i < count; i++) {
double value = atof(t[i].f[sel]);
total += value;
if (value < min) min = value;
if (value > max) max = value;
}
// Statistics
fprintf(stream, "\nSum of field %d (%s) is: %f\n", sel + 1, field[sel], total);
fprintf(stream, "\nAverage of field %d (%s) is: %f\n", sel + 1, field[sel], count ? total / count : 0);
fprintf(stream, "\nMinimum of field %d (%s) is: %f\n", sel + 1, field[sel], min);
fprintf(stream, "\nMaximum of field %d (%s) is: %f\n", sel + 1, field[sel], max);
}
void output() {
// 1. Show to user on screen
display(stdout);
// 2. Commit to file
FILE *textfile = fopen("export.txt", "w");
if (textfile) {
display(textfile);
fclose(textfile);
printf("\nAlso exported to 'export.txt'\n");
} else {
printf("\nFailed to export to 'export.txt'(File Error).\n");
}
}
int cmp(const void *a, const void *b) {
char *f1 = ((Row*)a)->f[sel], *f2 = ((Row*)b)->f[sel];
// Handle pure numbers
if (isdigit(*f1)) return atof(f1) - atof(f2);
// Fallback for Strings and ISO Dates
return strcmp(f1, f2);
}
int main() {
FILE *f = fopen(fn, "rb");
if (f) { count = fread(t, sizeof(Row), ROWS, f); fclose(f); }
while (1) {
printf("\nWe read %d rows in RAM memory\n", count);
printf("\n1:Write 2:Read 3:Verify 4:Exit\n> ");
int op; if (scanf("%d", &op) != 1) break;
if (op == 1) { // Create (Append)
if (count < ROWS) {
append(); count++;
save(); printf("\nDisk updated.\n");
} else {
printf("\nThe database file 'db.bin' is full. Replace it!\n");
}
} else if (op == 2) { // Read (Sort)
printf("Column (1-%d): ", COLUMNS); scanf("%d", &sel); sel--;
qsort(t, count, sizeof(Row), cmp);
output();
} else if (op == 3) { // Verify
sel = 4; // the "amount" column
qsort(t, count, sizeof(Row), cmp);
verify();
} else if (op == 4) break;
}
return 0;
}