Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #define MAXROWS 10000
- #define MAXCOLS 1000
- #define START_YEAR 1900
- #define DATE_COLUMNS 3
- int reportRows, reportColumns, itemsColumns = 4;
- const char *reportFileName = "montly_report.csv";
- struct Date //Datata na koja e kupen produktot
- {
- int day;
- int month;
- int year;
- };
- struct Item //Stavkata ovojpat ke ima ogranicen broj na koloni
- {
- char *name; //imeto na stavkata
- int quantity; //kolicina
- int price; //cena
- Date *date; //data na kupuvanje
- };
- struct Category //една колона од montly_report.csv
- {
- char *name; //ime na kategorijata
- Item items[MAXROWS]; //(референца кон табела со ставки)
- int numItems; //број на ставки
- char **values; //(низа од ќелии во таа колона)
- unsigned int isCategory; //булова вредност за тоа дали категоријата содржи табела со ставки
- };
- int countRows(const char *file_name) //broi linii od dadoteka
- {
- FILE *f = fopen(file_name, "r+");
- int count = 0;
- char buff[MAXCOLS];
- while (fgets(buff, MAXCOLS, f) != NULL)
- {
- count++;
- }
- fclose(f);
- return count;
- }
- int countColumns(char *s, char separator) //broi zborovi od linija
- {
- int count = 0;
- while (*s != '\0')
- {
- if (*s == separator)
- {
- count++;
- }
- s++;
- }
- return ++count;
- }
- char **words(char *s, char sep, int numCols) //separate the line to words, using the number of columns
- {
- char **seps = new char*[numCols];
- char *nextStart = s;
- for (int i = 0; i < numCols; i++)
- {
- while (*s != sep && *s != '\n' && *s != '\0')
- {
- s++;
- }
- int len = s - nextStart;
- seps[i] = new char[len];
- strncpy(seps[i], nextStart, len);
- seps[i][len] = '\0';
- nextStart = ++s;
- }
- return seps;
- }
- void initializeItems(Category *category) //so ovaa funkcija se otvora tabelata so stavki za da se inicijaliziraat
- {
- char *tempName = new char[strlen(category->name)+1];
- strcpy(tempName, category->name);
- tempName[strlen(tempName)] = '\0';
- FILE *f = fopen(strcat(tempName, ".csv"), "r");
- if (f == NULL) //dokolku ne postoi ne pravi nishto
- {
- category->isCategory = 0; //se oznacuva deka ne e "kategorija"
- return;
- }
- category->isCategory = 1;
- category->numItems = 0;
- char buff[MAXCOLS];
- fgets(buff, MAXCOLS, f); //prvata redica so iminjata se preskoknuva
- char *line;
- while ((line = fgets(buff, MAXCOLS, f)) != NULL)
- {
- char **itemSubs = words(line, ',', itemsColumns); //se deli linijata na niza od stringovi
- category->items[category->numItems].name = itemSubs[0]; //ime na stavka
- category->items[category->numItems].quantity = atoi(itemSubs[1]); //kolicina
- category->items[category->numItems].price = atoi(itemSubs[2]); //cena
- category->items[category->numItems].date = (Date*)malloc(sizeof(Date)); //data na kupuvanje
- char **dateSubs = words(itemSubs[3], '.', DATE_COLUMNS);
- category->items[category->numItems].date->day = atoi(dateSubs[0]); //den
- category->items[category->numItems].date->month = atoi(dateSubs[1]); //mesec
- category->items[category->numItems].date->year = atoi(dateSubs[2]); //godina
- category->numItems++; //realniot broj na stavki se zgolemuva
- }
- fclose(f);
- }
- Category **initializeCategory()
- {
- reportRows = countRows(reportFileName);
- FILE *f = fopen(reportFileName, "r+");
- char buff[MAXCOLS];
- char *line = fgets(buff, MAXCOLS, f);
- reportColumns = countColumns(line, ',');
- Category **categories = new Category*[reportColumns]; //kategorii kolku sto imam koloni vo dadotekata , niza od tolku kategorii
- if (line != NULL)
- {
- char **splited = words(line, ',', reportColumns);
- for (int i = 0; i < reportColumns; i++)
- {
- categories[i] = (Category*)malloc(sizeof(Category));
- categories[i]->values = new char*[reportRows-1];
- categories[i]->name = new char[strlen(splited[i])+1]; //name - string
- strcpy(categories[i]->name, splited[i]);
- categories[i]->name[strlen(splited[i])] = '\0';
- initializeItems(categories[i]);
- }
- }
- int j = 0;
- while ((line = fgets(buff, MAXCOLS, f)) != NULL)
- {
- char **splited = words(line, ',', reportColumns);
- for (int i = 0; i < reportColumns; i++)
- {
- categories[i]->values[j] = new char[strlen(splited[i])+1];
- strcpy(categories[i]->values[j], splited[i]);
- categories[i]->values[j][strlen(splited[i])] = '\0';
- }
- j++;
- }
- fclose(f);
- return categories;
- }
- char **insertInto(char **src, const char *colName, int index, int numColumns)
- {
- char **dest = new char*[numColumns + 1]; //нова ноза од категории со должина поголема за 1 од претходната
- for (int i = 0; i < index; i++) //se dodeka ne sum stignala do indeksot gi dodeluvam istite kategorii od starata vo novata niza
- {
- dest[i] = new char[strlen(src[i])+1];
- strcpy(dest[i], src[i]);
- dest[i][strlen(src[i])] = '\0';
- }
- dest[index] = new char[strlen(colName)+1]; //koga ke stignam, tuka ja stavam novata kategorija so soodvetnoto ime
- strcpy(dest[index], colName);
- dest[index][strlen(colName)] = '\0';
- for (int i = index + 1; i < numColumns + 1; i++)
- {
- dest[i] = new char[strlen(src[i-1])+1]; //prodolzuvam od pozicija i=index+1 i od starata niza gi dodeluvam onie na pozicija i-1 vo novata
- strcpy(dest[i], src[i - 1]);
- dest[i][strlen(src[i-1])] = '\0';
- }
- return dest; //nova niza od kategorii / nova kolona
- }
- int calcLen(char **src, int numColumns) //Вкупна должина на низа од стрингови, "Jas" "ti" "Toj" = 8
- {
- int len = 0;
- for (int i = 0; i < numColumns; i++)
- {
- len += strlen(src[i]);
- }
- return len;
- }
- char *stringOutOfArray(char **src, int numColumns) //Од низа од стрингови прави еден стринг одделен со сепаратор, запирка
- {
- int len = calcLen(src, numColumns) + numColumns-1;
- char *temp = new char[len+1];
- strcpy(temp, "\0");
- for (int i = 0; i < numColumns; i++)
- {
- strcat(temp, src[i]);
- if (i < numColumns - 1)
- {
- strcat(temp, ",");
- }
- }
- temp[len] = '\0';
- return temp;
- }
- void insertCategory(int index, const char *colname)
- {
- int numRows = countRows(reportFileName);
- char **lines = new char*[numRows];
- FILE *f = fopen(reportFileName, "r+");
- char buff[MAXCOLS];
- //
- char *line = fgets(buff, MAXCOLS, f);
- char numColumns = countColumns(line, ',');
- if (index > numColumns)
- {
- printf("You entered an index which does not fit in this table. Please try again!!!\n");
- return;
- }
- char **splited = words(line, ',', numColumns);
- lines[0] = stringOutOfArray(insertInto(splited, colname, index, numColumns), numColumns+1);
- //
- int i = 1;
- while ((line = fgets(buff, MAXCOLS, f)) != NULL)
- {
- splited = words(line, ',', numColumns);
- lines[i] = stringOutOfArray(insertInto(splited, "0", index, numColumns), numColumns+1);
- }
- fclose(f);
- //
- f = fopen(reportFileName, "w");
- for (int i = 0; i < numRows; i++)
- {
- fprintf(f, "%s", lines[i]);
- }
- fclose(f);
- //
- }
- int getIndexForName(char **words, int numColumns, const char *name)
- {
- for (int i = 0; i < numColumns; i++)
- {
- if (!strcmp(words[i], name))
- {
- return i;
- }
- }
- return -1;
- }
- int getIndexForName(Category **categories, int numColumns, const char *name)
- {
- for (int i = 0; i < numColumns; i++)
- {
- if (!strcmp(categories[i]->name, name))
- {
- return i;
- }
- }
- return -1;
- }
- char **removeFrom(char **src, int index, int numColumns)
- {
- char **dest = new char*[numColumns - 1];
- for (int i = 0; i < index; i++)
- {
- dest[i] = new char[strlen(src[i])];
- strcpy(dest[i], src[i]);
- }
- for (int i = index; i < numColumns - 1; i++)
- {
- dest[i] = new char[strlen(src[i + 1])];
- strcpy(dest[i], src[i + 1]);
- }
- return dest;
- }
- void removeCategory(const char *name)
- {
- int numRows = countRows(reportFileName);
- char **lines = new char*[numRows];
- FILE *f = fopen(reportFileName, "r+");
- char buff[MAXCOLS];
- //
- char *line = fgets(buff, MAXCOLS, f);
- char numColumns = countColumns(line, ',');
- char **splited = words(line, ',', numColumns);
- int indexOfOccurence = getIndexForName(splited, numColumns, name);
- if (indexOfOccurence == -1)
- {
- printf("There's no such column with the given name. Please try again!!!\n");
- return;
- }
- lines[0] = stringOutOfArray(removeFrom(splited, indexOfOccurence, numColumns), numColumns-1);
- //
- int i = 1;
- while ((line = fgets(buff, MAXCOLS, f)) != NULL)
- {
- splited = words(line, ',', numColumns);
- lines[i] = stringOutOfArray(removeFrom(splited, indexOfOccurence, numColumns), numColumns - 1);
- }
- fclose(f);
- //
- f = fopen(reportFileName, "w");
- for (int i = 0; i < numRows; i++)
- {
- fprintf(f, "%s", lines[i]);
- }
- fclose(f);
- //
- }
- void printTable(Category **categories)
- {
- for (int i = 0; i < reportColumns; i++)
- {
- printf("%-20s", categories[i]->name);
- }
- printf("\n");
- for (int i = 0; i < reportRows - 1; i++)
- {
- for (int j = 0; j < reportColumns; j++)
- {
- printf("%-20s", categories[j]->values[i]);
- }
- printf("\n");
- }
- }
- char *constructLineFromExpected(int firstIndex, int secondIndex, int eCost, tm *local, int numColumns) //konstruiram string od vnesena ocekuvana potrosuvacka i datum
- {
- char *result = new char[MAXCOLS];
- strcpy(result, "\0");
- for (int j = 0; j < firstIndex; j++)
- {
- strcat(result, "0,");
- }
- char buff[32];
- strcat(result, strcat(_itoa(eCost, buff, 10), ","));
- for (int j = firstIndex + 1; j < secondIndex; j++)
- {
- strcat(result, "0,");
- }
- _itoa(local->tm_mday, buff, 10); //denot
- strcat(buff, ".");
- strcat(result, buff);
- _itoa(local->tm_mon + 1, buff, 10); //mesecot
- strcat(buff, ".");
- strcat(result, buff);
- _itoa(START_YEAR + local->tm_year, buff, 10); //godinata (START_YEAR+) bidejki strukturata broi od 1900-tata
- strcat(buff, ",");
- strcat(result, buff);
- for (int j = secondIndex + 1; j < numColumns; j++)
- {
- strcat(result, "0,");
- }
- result[strlen(result) - 1] = '\0';
- return result;
- }
- int countStrings(char **s) //brojam kolku stringovi ima vo niza od stringovi
- {
- int count = 0;
- while (*s != "\0")
- {
- count++;
- s++;
- }
- return count;
- }
- int main()
- {
- struct Category **categories = initializeCategory();
- const char *naUp = "*********************", *na = "* NatashaAccounting *", *naDown = "*********************";
- printf("%50s\n", naUp);
- printf("%50s\n", na);
- printf("%50s\n", naDown);
- printf("\n\n\nWELCOME!\n");
- time_t curtime;
- int choice;
- while (1)
- {
- printf("\n1) Print the montly report (categories) table\n");
- printf("2) Insert a category\n");
- printf("3) Remove a category\n");
- printf("4) Change/Insert expected cost for the current/next month\n");
- printf("5) Insert an item\n");
- printf("6) EXIT\n");
- scanf("%d", &choice);
- if (choice == 1)
- {
- printTable(categories);
- }
- if (choice == 2)
- {
- int colIndex;
- char colName[50];
- printf("Enter the position on the new column (starting from 0): ");
- scanf("%d", &colIndex);
- printf("Enter a name for the new column (without blank space): ");
- scanf("%s", colName);
- insertCategory(colIndex, colName);
- categories = initializeCategory();
- getchar();
- char ans;
- printf("Would you like to create a new table for the given category?(Y/N): ");
- scanf("%c", &ans);
- if (ans == 'Y' || ans == 'y')
- {
- FILE *f = fopen(strcat(colName, ".csv"), "w");
- char s[] = "Name,Quantity,Price,Date\0";
- fwrite(s, 1, sizeof(s), f);
- fclose(f);
- }
- }
- if (choice == 3)
- {
- char colName[50];
- printf("Enter the name of the column which you want to be removed: ");
- scanf("%s", colName);
- removeCategory(colName);
- categories = initializeCategory();
- remove(strcat(colName, ".csv"));
- }
- if (choice == 4)
- {
- int eCost; //novata ocekuvana potrosuvacka
- printf("Vnesete go iznosot (vo denari) sto ocekuvate deka ke go potrosite: ");
- scanf("%d", &eCost);
- FILE *f = fopen(reportFileName, "r");
- char buff[MAXCOLS];
- char *line;
- int i;
- char **toBeWritten = new char*[reportRows + 2]; //noviot raspored na katerogii so dodadeni/izmeneti vrednosti
- for (i=0; i<reportRows; i++) //kopiranje na se sto e vo datotekata vo toBeWritten
- {
- line = fgets(buff, MAXCOLS, f);
- toBeWritten[i] = new char[strlen(line)+1];
- strcpy(toBeWritten[i], line);
- toBeWritten[i][strlen(line)] = '\0';
- }
- time(&curtime); //zemanje na tekovnoto vreme vo sekundi
- tm *local = localtime(&curtime); //gradenje struktura od koja ke gi izvlecam denot, mesecot i godinata
- int indexDate = getIndexForName(categories, reportColumns, "Date"); //baram na koj indeks e datata
- char *result = "\0"; //rezultantniot string so vnesenata expected potrosuvacka
- if (reportRows - 1 > 0 ) //dokolku veke ima vneseno potrosuvacka
- {
- char **catDate = words(categories[indexDate]->values[i - 2], '.', DATE_COLUMNS); //gi izdvojuvam denot mesecot i godinata od datumot
- int indexExpected = getIndexForName(categories, reportColumns, "Expected_cost"); //pronajdi ja kolonata Expected_Cost
- if (indexExpected < indexDate) //konstruiram string zavisno od redosledot
- {
- result = constructLineFromExpected(indexExpected, indexDate, eCost, local, reportColumns);
- }
- else {
- result = constructLineFromExpected(indexDate, indexExpected, eCost, local, reportColumns);
- }
- if (atoi(catDate[2]) == START_YEAR + local->tm_year && atoi(catDate[1]) == local->tm_mon + 1) //dokolku se poklopuvaat, azuriraj
- {
- toBeWritten[i - 1] = new char[strlen(result) + 1];
- strcpy(toBeWritten[i - 1], result);
- toBeWritten[i - 1][strlen(result)] = '\0';
- toBeWritten[i] = "\0";
- }
- else //vo sprotivno dodadi nova smetka za noviot mesec
- {
- toBeWritten[i] = new char[strlen(result) + 1];
- strcpy(toBeWritten[i], result);
- toBeWritten[i][strlen(result)] = '\0';
- toBeWritten[i + 1] = "\0";
- }
- }
- else //vo sprotivno odnesuvaj se kako da treba da dodades nova smetka
- {
- int indexExpected = getIndexForName(categories, reportColumns, "Expected_cost");
- if (indexExpected < indexDate)
- {
- result = constructLineFromExpected(indexExpected, indexDate, eCost, local, reportColumns);
- }
- else {
- result = constructLineFromExpected(indexDate, indexExpected, eCost, local, reportColumns);
- }
- toBeWritten[i] = new char[strlen(result) + 1];
- strcpy(toBeWritten[i], result);
- toBeWritten[i][strlen(result)] = '\0';
- toBeWritten[i + 1] = "\0";
- }
- fclose(f);
- f = fopen(reportFileName, "w+");
- for (int j = 0; j < i + 1; j++) //gi stavam azuriranite/dodadenite smetki vo istata tabela
- {
- fprintf(f, "%s\n", toBeWritten[j]);
- }
- fclose(f);
- categories = initializeCategory();
- }
- if (choice == 5)
- {
- int catId;
- printf("Please select a category:\n");
- for (int i = 0; i < reportColumns; i++)
- {
- printf("%d) %s\n", i + 1, categories[i]->name);
- }
- scanf("%d", &catId);
- if (catId <= reportColumns) //dokolku e vnesen validen indeks
- {
- if (categories[catId - 1]->isCategory == 1) //dokolku kategorijata ima tabela
- {
- char cName[50], cQuantity[32], cPrice[32], cDate[12];
- printf("Ime na produktot (praznoto mesto zameneto go so dolna crta)? ");
- scanf("%s", cName);
- printf("Kolicina? ");
- scanf("%s", cQuantity);
- printf("Cena? ");
- scanf("%s", cPrice);
- printf("Data na kupuvanje (d.m.yyyy)? ");
- scanf("%s", cDate);
- char itemRow[MAXCOLS];
- strcpy(itemRow, "\n");
- strcat(itemRow, cName);
- strcat(itemRow, ",");
- strcat(itemRow, cQuantity);
- strcat(itemRow, ",");
- strcat(itemRow, cPrice);
- strcat(itemRow, ",");
- strcat(itemRow, cDate);
- itemRow[strlen(itemRow)] = '\0';
- char *tempName = new char[strlen(categories[catId - 1]->name)+1];
- strcpy(tempName, categories[catId - 1]->name);
- tempName[strlen(tempName)] = '\0';
- FILE *tempF = fopen(strcat(tempName, ".csv"), "a");
- fprintf(tempF, itemRow);
- fclose(tempF);
- initializeItems(categories[catId - 1]);
- }
- else
- {
- printf("Izbranata kategorija na sodrzi tabela so produkti. Ve molime izberete soodvetna katerogija!");
- }
- }
- else
- {
- printf("Vnesovte nevalidna opcija!!! Obidete se povtorno.\n");
- }
- }
- if (choice == 6)
- {
- break;
- }
- }
- system("PAUSE");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement