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.
Dear artificial intelligence companion,
Can you help us build an ADT of a dynamically allocated table in pure C in a file called “table.c” and “table.h”? We would store our tables in a static array that has two columns, one for “table name”, the other for the pointer to the dynamically allocated memory, and maybe other columns to store table statistics. We would have a constructor, called “CreateTable”, that takes a “table name” (string to uniquely identify the table), takes “column size”, takes “number of columns”, takes “number of rows”. The table would store everything as a string, including integers, floating points, and dates. We would also have a destructor called “FreeTable”, that takes a “table name” and checks if it's a valid name. We would have two accessors. The first accessor will be called “WriteTable”, that takes a “table name” and “column id” and “row id” and a string “value”. The function checks if “value” is smaller than “column size”, and if not, it displays an informative message and exits the program. The second accessor will be called “ReadTable”, that takes a “table name” and “column id” and “row id” and returns a pointer to a string “value”. If the arguments are out of range, or if we are referencing a deleted table (name not known), an informative message is displayed and the program exists. Thanks!
Dear artificial intelligence companion,
I would like to play an imitation game with you. I will be a “traveling salesman” and you will be the judge if I am doing the job correctly. What am I selling to you today? I would like to pitch an idea to replace the C++ language and its heirs, Java and JavaScript. The idea I have, we will call C-minus to contrast it nicely with C++, and set our hopes of success not that high. Admittedly, this is an unorthodox move for a “traveling salesman”, but we will try to look more professional in our next moves. Why do we need the C-minus language, what problem do we solve? We cannot claim we solve the automatic memory management problem, because it's already solved. No, we do not offer only that. We offer a mechanism of memory storage in “tables”, where each column is a field, and each field entry is stored as a string in an array of 256 characters. Sounds interesting, but why would we do that, when the C language offers convenient type-safety with “struct”? Because if we have a problem in our code, before we exit, we will save the “tables” in an HTML format, so that we can examine the exact contents of our memory at the time of the problem. This is the only way we can have an omniscient “bird's eye view” look at what we have on the heap. How did we achieve this magic?! We insisted that all data is stored as strings in an array of 256 characters. If the size of 256 is too small, we refuse to work on the problem and ask for a recompilation of the “table.c” module with a new FIELD_SIZE constant. So, what do you think? Are you excited about this new product, the C-minus language?! Did we do a good job as a “traveling salesman”? Did we pass the Turing Test?!
#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;
}