Re-wrote most of the program, last version was a mess

This commit is contained in:
Jack-Benny Persson 2017-11-09 06:15:57 +01:00
parent 4fc931579d
commit 113c591094

View File

@ -1,15 +1,15 @@
/* A simple inventory tool written in C, by
* Jack-Benny Persson (jack-benny@cyberinfo.se).
* Released under GNU GPLv2.
Jack-Benny Persson (jack-benny@cyberinfo.se).
Released under GNU GPLv2.
*/
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* Macros */
#define FILEMAXLENGTH 50
#define NAMEMAXLENGTH 30
/* Globals */
@ -20,12 +20,12 @@ struct myData
float price;
};
char filename[FILEMAXLENGTH] = "storage.bin";
char filename[] = "storage.bin";
/* Function prototype */
/* Function prototypes */
void list(struct myData *datap, int numRec);
void search(struct myData *datap, int numRec, char *name);
void modify(struct myData *datap, int numRec, char *name, char *num);
void modify(struct myData *datap, int numRec, char *name);
void delete(struct myData *datap, int numRec, char *name);
int new(struct myData *datap, int numRec);
void printUsage(char *arg);
@ -34,39 +34,67 @@ void printHeader(void);
int main(int argc, char* argv[])
{
FILE *fp;
int newart = 0;
int numRec;
int create;
int choice;
int opt;
struct myData *data;
/* Print help and exit if no arguments are given */
if (argc < 2)
{
printUsage(argv[0]);
return 1;
}
/* Process command line arugments */
while ((opt = getopt(argc, argv, "hlsmdnf:")) != -1)
/* Check file access mode */
if ( access(filename, R_OK|W_OK) != 0 )
{
fprintf(stderr, "Could not open %s\n", filename);
printf("Create the file and start adding records? (y/n): ");
create = getchar();
if ( create == 'y' )
{
/* Start createing records */
numRec = 1;
data = calloc(numRec, sizeof(struct myData));
new(data, numRec);
free(data);
}
else
return 1;
}
fp = fopen(filename, "rb");
fseek(fp, 0, SEEK_END);
numRec = ftell(fp) / sizeof(struct myData);
data = calloc(numRec, sizeof(struct myData));
rewind(fp);
fread(data, sizeof(struct myData), numRec, fp);
fclose(fp);
/* Process arguments with getopt() */
while ((opt = getopt(argc, argv, "hls:m:d:n")) != -1)
{
switch (opt)
{
case 'l':
choice = 'l';
list(data, numRec);
break;
case 's':
choice = 's';
search(data, numRec, optarg);
break;
case 'm':
choice = 'm';
modify(data, numRec, optarg);
break;
case 'd':
choice = 'd';
delete(data, numRec, optarg);
break;
case 'n':
choice = 'n';
break;
case 'f':
strncpy(filename, optarg, FILEMAXLENGTH-1);
newart = 1;
break;
case 'h':
printUsage(argv[0]);
@ -77,79 +105,24 @@ int main(int argc, char* argv[])
}
}
/* Check if file exists, if it dosen't, create it */
if ( access(filename, R_OK|W_OK) != 0 )
{
fprintf(stderr, "Could not open %s\n", filename);
printf("Create the file and start adding records? (y/n): ");
create = getchar();
if ( create == 'y' )
{
numRec = 1;
struct myData *data;
data = calloc(numRec, sizeof(struct myData));
new(data, numRec);
free(data);
}
else
return 1;
}
/* The structure to contain our database */
struct myData *data;
/* Continue processesing the command-line arugments */
if ( choice == 'l' || choice == 's' || choice == 'm' || choice == 'd' )
{
/* Open file in read-mode */
FILE *fp = fopen(filename, "rb");
/* Read in the content from the file to the structure */
fseek(fp, 0, SEEK_END);
numRec = ftell(fp) / sizeof(struct myData);
data = calloc(numRec, sizeof(struct myData));
rewind(fp);
fread(data, sizeof(struct myData), numRec, fp);
fclose(fp);
if ( choice == 'l' )
list(data, numRec);
else if ( choice == 's' && argc >= 2 )
search(data, numRec, argv[2]);
else if ( choice == 's' && argc <= 2)
search(data, numRec, NULL);
else if ( choice == 'm' && argc >= 3)
modify(data, numRec, argv[2], argv[3]);
else if ( choice == 'm' && argc <= 4)
modify(data, numRec, NULL, NULL);
else if ( choice == 'd' && argc >= 2 )
delete(data, numRec, argv[2]);
else if ( choice == 'd' && argc <= 2 )
delete(data, numRec, NULL);
}
else if ( choice == 'n' )
/* Continue here */
if ( newart == 1 )
{
data = calloc(1, sizeof(struct myData));
if ( new(data, numRec) == 1 )
return 1;
}
else
{
printUsage(argv[0]);
return 1;
}
/* Finished */
free(data);
return 0;
}
void list(struct myData *datap, int numRec)
{
int i;
printHeader();
for (int i = 0; i<numRec; i++)
for (i = 0; i<numRec; i++)
{
printf("%-30s\t", datap[i].name);
printf("%-10d\t", datap[i].quantity);
@ -161,22 +134,11 @@ void list(struct myData *datap, int numRec)
void search(struct myData *datap, int numRec, char *name)
{
char searchword[NAMEMAXLENGTH];
if (name != NULL)
int i;
/* Iterate over the database and search */
for (i = 0; i<numRec; i++)
{
strncpy(searchword, name, NAMEMAXLENGTH-1);
}
else
{
printf("Name: ");
fgets(searchword, NAMEMAXLENGTH, stdin);
/* Replace the newline character with a null character */
searchword[strcspn(searchword, "\n")] = '\0';
}
for (int i = 0; i<numRec; i++)
{
if ( strcmp(searchword, datap[i].name) != 0 )
if ( strcmp(name, datap[i].name) != 0 )
continue;
printHeader();
printf("%-30s\t", datap[i].name);
@ -186,66 +148,55 @@ void search(struct myData *datap, int numRec, char *name)
}
}
void modify(struct myData *datap, int numRec, char *name, char *num)
void modify(struct myData *datap, int numRec, char *name)
{
char searchword[NAMEMAXLENGTH];
FILE *newfp;
int i;
int match = 0;
char what[10];
char quant[20];
int interactive = 1;
if (name != NULL && num != NULL)
{
strncpy(searchword, name, NAMEMAXLENGTH-1);
strncpy(what, "quantity", 9);
strncpy(quant, num, 19);
interactive = 0;
}
else
{
printf("Name: ");
fgets(searchword, NAMEMAXLENGTH, stdin);
searchword[strcspn(searchword, "\n")] = '\0';
}
for (int i = 0; i<numRec; i++)
{
if ( strcmp(searchword, datap[i].name) == 0 )
{
if (interactive == 1)
{
printHeader();
printf("%-30s\t", datap[i].name);
printf("%-10d\t", datap[i].quantity);
printf("%.2f\t", datap[i].price);
printf("\n\n");
printf("What do you like to modify? (name, quantity, price): ");
fgets(what, 10, stdin);
what[strcspn(what, "\n")] = '\0';
}
/* Iterate over the database and search */
for (i = 0; i<numRec; i++)
{
if ( strcmp(name, datap[i].name) == 0 )
{
match = 1;
printHeader();
printf("%-30s\t", datap[i].name);
printf("%-10d\t", datap[i].quantity);
printf("%.2f\t", datap[i].price);
printf("\n\n");
printf("What do you like to modify? "
"(name, quantity, price): ");
fgets(what, 10, stdin);
what[strcspn(what, "\n")] = '\0';
if ( strcmp(what, "name") == 0 )
{
printf("Name: "); scanf("%29s", datap[i].name);
printf("Name: ");
fgets(datap[i].name, NAMEMAXLENGTH, stdin);
datap[i].name[strcspn(datap[i].name, "\n")] = '\0';
}
else if ( strcmp(what, "quantity") == 0 )
{
if (interactive == 1)
printf("Quantity (absolute value or "
"(a)dd/(s)ubtractNUMBER): ");
fgets(quant, 20, stdin);
quant[strcspn(quant, "\n")] = '\0';
if (quant[0] == 'a') /* a for add */
{
printf("Quantity (absolute value or (a)dd/(s)ubtractNUMBER): ");
fgets(quant, 20, stdin);
quant[strcspn(quant, "\n")] = '\0';
quant[0] = ' '; /* Remove the sign */
datap[i].quantity = datap[i].quantity +
atoi(quant);
}
/* Process the first character */
if (quant[0] == 'a')
{
quant[0] = ' '; /* We need to remove the character first */
datap[i].quantity = datap[i].quantity + atoi(quant);
}
else if (quant[0] == 's')
else if (quant[0] == 's') /* s for subtract */
{
quant[0] = ' ';
datap[i].quantity = datap[i].quantity - atoi(quant);
datap[i].quantity = datap[i].quantity -
atoi(quant);
}
else
datap[i].quantity = atoi(quant);
@ -256,87 +207,84 @@ void modify(struct myData *datap, int numRec, char *name, char *num)
printf("Price: "); scanf("%f", &datap[i].price);
}
}
else
{
fprintf(stderr, "Could not find %s in database\n", searchword);
exit(1);
}
}
FILE *newfp = fopen(filename, "wb");
if (match == 0)
{
fprintf(stderr, "Could not find %s in database\n", name);
exit(1);
}
/* Write out the new content to file */
if ( (newfp = fopen(filename, "wb")) == 0 )
{
fprintf(stderr, "Could not open file for writing\n");
exit(1);
}
fwrite(datap, sizeof(struct myData), numRec, newfp);
fclose(newfp);
}
void delete(struct myData *datap, int numRec, char *name)
{
char searchword[NAMEMAXLENGTH];
int i, j;
int match = 0;
FILE *newfp;
int answer;
int interactive = 1;
if (name != NULL)
{
strncpy(searchword, name, NAMEMAXLENGTH-1);
interactive = 0;
answer = 'y';
}
else
{
printf("Name: ");
fgets(searchword, NAMEMAXLENGTH, stdin);
searchword[strcspn(searchword, "\n")] = '\0';
}
for (int i = 0; i<numRec; i++)
{
if ( strcmp(searchword, datap[i].name) == 0 )
{
if (interactive == 1)
{
printHeader();
printf("%-30s\t", datap[i].name);
printf("%-10d\t", datap[i].quantity);
printf("%.2f\t", datap[i].price);
printf("\n\n");
printf("Delete the record listed above? (y/n): ");
answer = getchar();
}
/* Iterate the database and search */
for (i = 0; i<numRec; i++)
{
if ( strcmp(name, datap[i].name) == 0 )
{
match = 1;
printHeader();
printf("%-30s\t", datap[i].name);
printf("%-10d\t", datap[i].quantity);
printf("%.2f\t", datap[i].price);
printf("\n\n");
printf("Delete the record listed above? (y/n): ");
answer = getchar();
if ( answer == 'y' )
{
FILE *newfp = fopen(filename, "wb");
/* Write out all records, except the one we cant to delete,
back to the file, one record at a time */
for (int j = 0; j<numRec; j++)
if ( (newfp = fopen(filename, "wb")) == 0 )
{
if ( strcmp(searchword, datap[j].name) == 0 )
fprintf(stderr,
"Could not open file for writing\n");
exit(1);
}
/* Iterate the database and write out every
record except those that matched! */
for (j = 0; j<numRec; j++)
{
if ( strcmp(name, datap[j].name) == 0 )
continue;
fwrite(&datap[j], sizeof(struct myData), 1, newfp);
fwrite(&datap[j], sizeof(struct myData), 1,
newfp);
}
fclose(newfp);
}
}
else
{
fprintf(stderr, "Could not find %s in database\n", searchword);
exit(1);
}
}
if (match == 0)
{
fprintf(stderr, "Could not find %s in database\n", name);
exit(1);
}
}
int new(struct myData *datap, int numRec)
{
FILE *fp;
int bytes;
FILE *fp = fopen(filename, "ab");
if (fp == NULL)
if ( (fp = fopen(filename, "ab")) == 0 )
{
printf("Can't open file for writing\n");
fprintf(stderr, "Could not open file for writing\n");
return 1;
}
/* Ask for, and write out, one record at a time */
/* End loop when user types 'done' */
for (;;)
{
/* Clear the input buffer (from the previous iteration) */
setbuf(stdin, NULL);
printf("Name ('done' when finished): ");
fgets(datap->name, NAMEMAXLENGTH, stdin);
@ -360,33 +308,26 @@ int new(struct myData *datap, int numRec)
void printUsage(char *arg)
{
fprintf(stderr, "Usage: %s [-l] [-s [name]] [-m [name (a/s)quantity]]\n"
"[-d [name]] [-n] [-h] [-f filename]\n\n"
"-l = list the articles in the database\n"
"-s = search for an article in the database\n"
" If no name is given as argument, you will be prompted for a name.\n"
"-m = modify a article\n"
" If no name is given as argument, you will be prompted for a\n"
" name. You'll then have the choice to change name, quantity and price.\n"
" If a name is given as argument, the quantity can be changed from the\n"
" command line, such as subtracting the stock by three:\n"
" ./on-stock -m 'Nailgun' s3\n"
"-d = delete a article\n"
" If no name is given as argument, you will be prompted for an article\n"
" to delete.\n"
" If a name is given as argument, no confirmation will be required to\n"
" delete the article from the database.\n"
"-n = create new articles (interactive mode only)\n"
"-h = display this help message\n"
"-f = specifiy a filename for the database\n", arg);
fprintf(stderr, "Usage: %s [-l] [-s name]"
"[-m name \n"
"[-d name] [-n] [-h] [-f filename]\n\n"
"-l = list the articles in the database\n"
"-s name = search for an 'name' in the database\n"
"-m name = modify the article named 'name' in the database\n"
" You'll then have the choice to change name, quantity "
"and price.\n"
"-d name = delete the article named 'name'\n"
"-n = create new articles (interactive mode only)\n"
"-h = display this help message\n", arg);
}
void printHeader(void)
{
int i;
printf("\n%-30s\t", "Name");
printf("%s\t", "Quantity");
printf("%s\t\n", "Price");
for (int i = 0; i<=52; i++)
for (i = 0; i<=52; i++)
printf("=");
printf("\n");
}