/* * File: WaterRetention.cpp * Author: S Harry White * Created: 2009-11-25 * Updated: 2020-01-12: Add option to color ponds by size in the Units square. * -01-17: Add comment on line 5. */ #include "stdafx.h" #include #include #include #include #include #include #include #include #include #include #define Uint unsigned long int int R, C, // The order of the rectangle. N, // R==C? R : sqrt(RC) Rm1, // R - 1 Cm1, // C - 1 RC; // R * C Uint rowConstant, // C * (RC + 1) / 2 colConstant; // R * (RC + 1) / 2 for 1 base //const int maxRRowConstant = 2047; // max R before 32-bit unsigned long // // overflow of RowConstant const int maxRC = 250000; // Some browsers can't handle big rectangle files. int maxNumber, // Biggest number in the rectangle. inputRectNumber, // Counts rectangles input from a .txt file. fileRectNumber, // Counts rectangles for the current output file. outputFileNumber, rectanglesPerFile; int **xRectangle = NULL, **water = NULL, **pond=NULL, *pondSize, allocatedR = 0, allocatedC = 0; const int startSize = 25; bool multicolor, *numUsed = NULL; // To check that numbers 1 to RC are in a magic rectangle. struct t_Cell { int priority, row, col; }; t_Cell *Queue = NULL; int allocatedQueueSize = 0, qIndex = 0; const int numColors=36; char *color[numColors] = { "bb0","bb1","bb2","bb3","bb4","bb5","bb6","bb7", "bb8","bb9","bbA","bbB","bbC","bbD","bbE","bbF", "bbG","bbH","bbI","bbJ","bbK","bbL","bbM","bbN", "bbO","bbP","bbQ","bbR","bbS","bbT","bbU","bbV", "bbW","bbX","bbY","bbZ" }; const int bufSize = 1024; //--------------------------------------------------------------------------- char *storeAllocFail = "Storage allocation failed"; bool bell = true; bool reportError(char *msg) { // ----------- printf("%sError: %s.\n", bell ? "\a\n" : "", msg); if (bell) bell = false; return false; } // reportError //--------------------------------------------------------------------------- void freeRectangle(int*** rectangle, int size) // ------------- { if (*rectangle != NULL) { for(int i = 0; i < size; i++) free((*rectangle)[i]); free(*rectangle); *rectangle = NULL; } } // freeRectangle void freeUsed() { if (numUsed != NULL) { free(numUsed); numUsed = NULL; } } // -------- void freeQueue() { if (Queue!=NULL) { free(Queue); Queue=NULL; allocatedQueueSize= 0; } } // --------- void freeStore() // --------- { freeRectangle(&pond, allocatedR); freeRectangle(&water, allocatedR); freeRectangle(&xRectangle, allocatedR); if (pondSize!=NULL) { free(pondSize); pondSize=NULL; } allocatedR = 0; allocatedC = 0; freeUsed(); freeQueue(); } bool allocateRectangle(int*** rectangle, const int nR, const int nC) { // ----------------- bool ok; *rectangle = (int**) malloc(nR * sizeof(int*)); ok = (*rectangle != NULL); if (ok) { int numAllocated = 0; for(int i = 0; i < nR; i++) { int* p = (int*) malloc(nC * sizeof(int)); (*rectangle)[i] = p; if (p == NULL) { numAllocated = i; ok = false; break; } } if (!ok) freeRectangle(rectangle, numAllocated); } return ok; } // allocateRectangle bool allocateUsed(int size) // ------------ { return ((numUsed = (bool*) malloc(size * sizeof(bool))) != NULL); } // allocateUsed //--------------------------------------------------------------------------- bool allocateQueue(int size) // ------------- { bool ok = true; if (allocatedQueueSize < size) { freeQueue(); Queue = (t_Cell *) malloc(size * sizeof(t_Cell)); if (ok = (Queue != NULL)) allocatedQueueSize = size; } return ok; } // allocateQueue bool increaseQueue() // ------------- { int size = allocatedQueueSize + allocatedQueueSize; t_Cell *tmp = (t_Cell *) malloc(size * sizeof(t_Cell)); if (tmp == NULL) { reportError(storeAllocFail); return false; } for (int i = 0; i < qIndex; i++) tmp[i] = Queue[i]; freeQueue(); Queue = tmp; allocatedQueueSize = size; return true; } // increaseQueue; bool allocateStore() // ------------- { bool ok = true; int nR = R, nC = C; if (nR < startSize) nR = startSize; if (nC < startSize) nC = startSize; if ((nR > allocatedR) || (nC > allocatedC)) { int nRnC=nR*nC; freeStore(); if (ok = allocateRectangle(&xRectangle, nR, nC)) if (ok = allocateRectangle(&water, nR, nC)) if (ok = allocateRectangle(&pond, nR, nC)) if (ok = allocateQueue(nRnC)) if (ok = allocateUsed(nRnC+1)) { pondSize = (int*) malloc(nRnC/2 * sizeof(int)); ok=(pondSize!=NULL); if (ok) {allocatedR = nR; allocatedC = nC; } } if (!ok) { reportError(storeAllocFail); freeStore(); } } return ok; } // allocateStore //-------------------------------------------------------------------------- //FILE *Qfp = NULL; //void printQueue() //// ---------- //{ // // int i = 0; // while (i < qIndex) { // t_Cell *q = &Queue[i]; // fprintf(Qfp,"priority %d row %d col %d\n", // q->priority, q->row, q->col); // i++; // } // fprintf(Qfp,"\n"); //} // printQueue //--------------------------------------------------------------------------- enum magicType {notMagic, notNormal, Normal}; typedef magicType (*t_mticb)(const bool); t_mticb isMagic; magicType isMagicSq(const bool checkZeroBased) { // R==C // --------- //if (R > maxRRowConstant) return Normal; // Overflow, can't check. Uint chkSum = 0; Uint magicSum = checkZeroBased ? rowConstant - R : rowConstant; int min = checkZeroBased ? 0 : 1, max = RC + min - 1; Uint sumX, sumY, sumXY = 0, sumYX = 0; for (int i = min; i <= max; i++) numUsed[i] = false; for (int r = 0; r < R; r++) { sumX = 0; sumY = 0; for (int c = 0; c < R; c++) { int tmp = xRectangle[r][c]; if ((min <= tmp) && (tmp <= max)) numUsed[tmp] = true; sumX += tmp; sumY += xRectangle[c][r]; } if (r==0) chkSum = sumX; if ((sumX != chkSum) || (sumY != chkSum)) return notMagic; sumXY += xRectangle[r][Rm1-r]; sumYX += xRectangle[r][r]; } if ((sumXY != chkSum) || (sumYX != chkSum)) return notMagic; if (chkSum != magicSum) return notNormal; for (int i = min; i <= max; i++) if (!numUsed[i]) return notNormal; return Normal; } // isMagicSq magicType isMagicRect(const bool checkZeroBased) { // ----------- //if (R > maxRRowConstant) return Normal; // Overflow, can't check. Uint chkSumR, chkSumC, rowSum, colSum; if (checkZeroBased) { rowSum = rowConstant-C; colSum = colConstant-R; } else { rowSum = rowConstant; colSum = colConstant; } int min = checkZeroBased ? 0 : 1, max = RC + min - 1; for (int i = min; i <= max; i++) numUsed[i] = false; for (int r = 0; r < R; r++) { Uint sum = 0; for (int c = 0; c < C; c++) { int tmp = xRectangle[r][c]; if ((min <= tmp) && (tmp <= max)) numUsed[tmp] = true; sum += tmp; } if (r==0) chkSumR=sum; else if (sum != chkSumR) return notMagic; } for (int c = 0; c < C; c++) { Uint sum = 0; for (int r = 0; r < R; r++) sum += xRectangle[r][c]; if (c==0) chkSumC=sum; else if (sum != chkSumC) return notMagic; } if ((chkSumR != rowSum) || (chkSumC != colSum)) return notNormal; for (int i=min; i<=max; i++) if (!numUsed[i]) return notNormal; return Normal; } // isMagicRect //--------------------------------------------------------------------------- int tableWidth() { return C * (N < 10 ? 25 : N < 32 ? 32 : 40); } bool writeHead(FILE *wfp) // --------- { int cellHeight = tableWidth()*(R < 100 ? 8 : 9)/(10*C)-2; // Numbers > 9999 are split over 2 lines, forcing a higher profile. return fprintf(wfp, "\n" "\n\n" "\nWater Retention\n" "\n\n\n\n\n", cellHeight) > 0; } // writeHead //--------------------------------------------------------------------------- bool writeEmptyCell(FILE *wfp, char *_class, int r) // -------------- { char v[bufSize]; if (r == 0) { strcpy_s(v, bufSize, "  "); if (N > 9) strcat_s(v, bufSize, "  "); // 3 digit numbers if (N > 31) strcat_s(v, bufSize, "  "); // 4 digit numbers } else { strcpy_s(v, bufSize, ""); } return fprintf(wfp, "%s\n", _class, v) > 0; } // writeEmptyCell bool writeCell(FILE *wfp, char *_class, int v) // --------- { if (v > 9999) return fprintf(wfp, "%d,
 %03d\n", _class, v/1000, v%1000) > 0; else return fprintf(wfp, "%d\n", _class, v) > 0; } // writeCell //---------------------------------------------------------------------------------------------- bool writeWaterRectangle(FILE *wfp, bool writeUnitsRectangle) // ------------------- { int tw = tableWidth(), cw = tw/C-2; if (writeUnitsRectangle) if (fprintf(wfp, "\n") < 0) return false; } return fprintf(wfp, "
\n") < 0) return false; if (fprintf(wfp, "\n" "\n", tw, C, cw) < 0) return false; if (writeUnitsRectangle) if (fprintf(wfp, "\n") < 0) return false; for (int r = 0; r < R; r++) { if (fprintf(wfp, "\n") < 0) return false; for (int c = 0; c < C; c++) { int v = xRectangle[r][c]; char *s = v == water[r][c] ? "fb" : "bb"; if (!writeCell(wfp, s, v)) return false; } } if (writeUnitsRectangle) { if (fprintf(wfp, "
Cells
\n" "\n" "\n" "\n", tw, C, cw) < 0) return false; for (int r = 0; r < R; r++) { if (fprintf(wfp, "\n") < 0) return false; for (int c = 0; c < C; c++) { int v = xRectangle[r][c], w = water[r][c]; if (v == w) { if (!writeEmptyCell(wfp, "eb", r)) return false; } else { char *col=multicolor?color[pond[r][c]]:"bb"; if (!writeCell(wfp, col, w - v)) return false; } } } if (fprintf(wfp, "
Units
\n

 

\n\n") > 0; } // writeWaterRectangle //--------------------------------------------------------------------------- void formatNum(char *s, Uint b, Uint u) { // --------- const int ct = 1000, cm = ct*ct; Uint m = u/cm, t = (u%cm)/ct, r = u%ct; if (b > 0) sprintf_s(s, 20, "%u,%03u,%03u,%03u", b, m, t, r); else if (m > 0) sprintf_s(s, 20, "%u,%03u,%03u", m, t, r); else if (t > 0) sprintf_s(s, 20, "%u,%03u", t, r); else sprintf_s(s, 20, "%u", r); } // formatNum bool writeCapacity(Uint unitsB, Uint units, Uint cells, FILE *wfp) // ------------- { char u[20], c[20], t[20]; formatNum(u, unitsB, units); formatNum(c, 0, cells); if (R==C) sprintf_s(t, 20, "%d", R); else sprintf_s(t, 20, "%dx%d", R, C); return fprintf(wfp, "

Order %s, cells retaining water %s " "(%2.1f%%), units retained %s

\n", t, c, (double)(100 * cells)/RC, u) > 0; } // writeCapacity //--------------------------------------------------------------------------- void writeFoot(FILE *wfp, bool *writeError) // --------- { *writeError = fprintf(wfp, "\n") < 0; } //--------------------------------------------------------------------------- bool writeHTML(FILE *wfp, Uint unitsB, Uint units, Uint cells) // --------- { return writeCapacity(unitsB, units, cells, wfp) && writeWaterRectangle(wfp, (unitsB > 0)||(units > 0)); } //=========================================================================== void initBounds() // ---------- { int mR = Rm1, mC = Cm1, **x = xRectangle; for (int r = 0; r < R; r++) { water[r][0] = x[r][0]; water[r][mC] = x[r][mC]; } for (int c = 1; c < mC; c++) { water[0][c] = x[0][c]; water[mR][c] = x[mR][c]; } for (int r = 1; r < mR; r++) for (int c = 1; c < mC; c++) water[r][c] = maxNumber; qIndex = 0; } // initBounds //--------------------------------------------------------------------------- void pushQueue(int priority, int row, int col) // --------- { t_Cell cell; cell.priority = priority; cell.row = row; cell.col = col; Queue[qIndex++] = cell; } // pushQueue bool insertQueue(int priority, int row, int col) // ----------- { if ((qIndex >= allocatedQueueSize) && !increaseQueue()) return false; t_Cell cell; cell.priority = priority; cell.row = row; cell.col = col; int i = qIndex-1; while (Queue[i].priority < priority) { Queue[i+1] = Queue[i]; if (--i < 0) break; } Queue[++i] = cell; ++qIndex; //printQueue(); return true; } // insertQueue void popQueue(t_Cell *cell) { *cell = Queue[--qIndex]; } // -------- //--------------------------------------------------------------------------- bool queueBorder() // ----------- { int mR = Rm1, mC = Cm1; pushQueue(water[1][0], 1, 0); if (!insertQueue(water[1][mC], 1, mC)) return false; for (int r = 2; r < mR; r++) { if (!insertQueue(water[r][0], r, 0)) return false; if (!insertQueue(water[r][mC], r, mC)) return false; } for (int c = 1; c < mC; c++) { if (!insertQueue(water[0][c], 0, c)) return false; if (!insertQueue(water[mR][c], mR, c)) return false; } return true; } // queueBorder //--------------------------------------------------------------------------- bool computeBounds(int p, int r, int c) // ------------- { int mR = Rm1, mC = Cm1; if ( ( (0 < r) && (r < mR) ) && ( (0 < c) && (c < mC) ) ) { int *bp = &water[r][c], tmp = max(xRectangle[r][c],p); if (tmp < *bp) { *bp = tmp; if (!insertQueue(tmp, r, c)) return false; } } return true; } // computeBounds //--------------------------------------------------------------------------- void computeCapacity(Uint *unitsB, Uint *units, Uint *cells) // --------------- { const Uint b = 1000000000; Uint count = 0, uB = 0, u = 0; for (int r = 0; r < R; r++) for (int c = 0; c < C; c++) { Uint delta = water[r][c] - xRectangle[r][c]; if (delta != 0) { ++count; u += delta; if (u >= b) { ++uB; u -= b; } } } *unitsB = uB; *units = u ; *cells = count; } // computeCapacity //--------------------------------------------------------------------------- bool checkPonds(const int p, const int r, const int c) { // ---------- int mR = Rm1, mC = Cm1; if ( ( (0 < r) && (r < mR) ) && ( (0 < c) && (c < mC) ) ) { bool wet=water[r][c]>xRectangle[r][c], visited=pond[r][c]!=0; if (wet&!visited) { if (qIndex==0) pushQueue(p, r, c); else if (!insertQueue(p, r, c)) return false; pond[r][c]=p; ++pondSize[p]; } } return true; } // checkPonds void putPondColors() { // ------------- for (int r=1; rxRectangle[r][c]; if (wet) pond[r][c]=pondSize[pond[r][c]]%numColors; } } // putPondColors bool getPonds() { // -------- for (int r=0; rxRectangle[r][c], visited=pond[r][c]!=0; if (wet&!visited) { pushQueue(++pnum, r, c); pond[r][c]=pnum; pondSize[pnum]=1; while (qIndex != 0) { t_Cell cell; popQueue(&cell); int p = cell.priority, r = cell.row, c = cell.col; if (wet) { if (!checkPonds(p, r-1, c)) return false; if (!checkPonds(p, r+1, c)) return false; if (!checkPonds(p, r, c-1)) return false; if (!checkPonds(p, r, c+1)) return false; } } } } putPondColors(); return true; } // getPonds /* * Based on an algorithm of Gareth McCaughan supplied by Craig Knecht. */ bool getWater(FILE *wfp, bool *writeError) // -------- { //fopen_s(&Qfp, "C:\\QueueTrace.txt", "w"); *writeError = false; initBounds(); if (!queueBorder()) return false; while (qIndex != 0) { //printQueue(); t_Cell cell; popQueue(&cell); int p = cell.priority, r = cell.row, c = cell.col; if (!computeBounds(p, r-1, c)) return false; if (!computeBounds(p, r+1, c)) return false; if (!computeBounds(p, r, c-1)) return false; if (!computeBounds(p, r, c+1)) return false; } if (multicolor&&!getPonds()) return false; Uint unitsB, units, cells; computeCapacity(&unitsB, &units, &cells); if (writeHTML(wfp, unitsB, units, cells)) { return true; } else { reportError("problem writing file"); *writeError = true; return false; } //fclose(Qfp); } // getWater //========================================================================== void outputLocalTime() // -------------- { time_t startTime = time(NULL); tm local; localtime_s(&local, &startTime); char dateTime[100]; size_t slen = strftime(dateTime, 100, "%A %Y-%m-%d %X %Z\n\n\0", &local); printf(dateTime); } // outputLocalTime //-------------------------------------------------------------------------- bool inputRectangle(FILE *rfp) // -------------- { if (!allocateStore()) return false; bool checkZeroBased = false; maxNumber = LONG_MIN; for (int r = 0; r < R; r++) for (int c = 0; c < C; c++) { int rv, tmp; if ( (rv = fscanf_s(rfp, "%d", &tmp)) != 1) { if ( (rv != EOF) || (r != 0) || (c != 0) ) return reportError("Reading rectangle from file"); return false; } if (tmp == 0) checkZeroBased = true; else if (tmp > maxNumber) maxNumber = tmp; xRectangle[r][c] = tmp; } ++inputRectNumber; ++fileRectNumber; magicType t = isMagic(checkZeroBased); if (t == notMagic) { char t[10]; sprintf_s(t, 10, "%s", (R==C)?"Square":"Rectangle"); printf("\n%s number %d is not magic.\n", t, inputRectNumber); } else if (t == notNormal) { printf("\n%s number %d is not normal magic.\n", t, inputRectNumber); } return true; } // inputRectangle //-------------------------------------------------------------------------- void initGlobals() // ----------- { Rm1 = R-1; Cm1 = C-1; RC = R*C; N = R==C? R : (int)sqrt((double)RC); rowConstant = C*(RC+1)/2; colConstant = R*(RC+1)/2; isMagic = (R==C)?isMagicSq:isMagicRect; rectanglesPerFile = 50000 / RC; // N == 5: 2000, N == 10: 500, N == 100: 5 if (rectanglesPerFile == 0) rectanglesPerFile = 1; multicolor=false; } // initGlobals //-------------------------------------------------------------------------- void get_rest_of_line(int c) // ---------------- { if (c != '\n') do { c = getchar(); } while (c != '\n'); } bool getY() // ---- { int c; do { c = getchar(); } while ((c == ' ') || (c == '\t') || (c == '\n')); get_rest_of_line(c); return (c == 'Y') || (c == 'y'); } // getY bool getInts(int *p, int *q, int c) { // ------- bool ok = false; *p = *q = 0; if (c<0) do { c = getchar(); } while ((c == ' ') || (c == '\t')); if ( ('1' <= c) && (c <= '9') ) { int i = c - '0'; while ( ('0' <= (c = getchar())) && (c <= '9') ) i = i*10 + c - '0'; *p = i; if ((c == ' ') || (c == '\t')) { do { c = getchar(); } while ((c == ' ') || (c == '\t')); if ( ('1' <= c) && (c <= '9') ) { int i = c - '0'; while ( ('0' <= (c = getchar())) && (c <= '9') ) i = i*10 + c - '0'; *q = i; } } if (*q==0) *q=*p; ok = true; } get_rest_of_line(c); if (!ok) return reportError("Invalid input"); return true; } // getInts bool getYorInts(int *p, int *q) { // ---------- bool ok = false; int c; *p=-1; do { c = getchar(); } while ((c == ' ') || (c == '\t') || (c == '\n') ); if ( (c == 'Y') || (c == 'y') ) ok = true; else if ( (c != 'N') && (c != 'n') ) return getInts(p, q, c); get_rest_of_line(c); return ok; } // getYorInts bool getFileName(char *buf, int size) { // ----------- int c, i = 0; char *s = buf; do { c = getchar(); } while ((c == ' ') || (c == '\t') || (c == '\n') ); *s = c; while (i++ < size) if ( (*++s = getchar()) == '\n') break; if (*s != '\n') { printf("\nFile name too long.\n"); get_rest_of_line(*s); return false; } *s = '\0'; return true; } // getFileName //-------------------------------------------------------------------------- FILE *openInput(char *buf, int size) // --------- { char *rFname = NULL; do { printf("\nEnter the name of the %ss file: ", (R==C)?"square":"rectangle"); if (getFileName(buf, size - 4)) { // reserve 4 to add .txt if needed rFname = buf; break; } else { printf ("\a\nCan't read the file name. Try again? y (yes) or n (no) "); if (!getY()) break; } } while (true); FILE *rfp = NULL; if (rFname != NULL) { char *s = buf; bool txt = false; while (*s++ != '\0'); while (--s != buf) if (*s == '.') { txt = (*++s == 't') && (*++s == 'x') && (*++s == 't') && (*++s == '\0'); break; } if (!txt) strcat_s(buf, size, ".txt"); // no .txt entered, add it if (fopen_s(&rfp, rFname, "r") != 0) { const int msgSize = bufSize + 50; char msg[msgSize]; sprintf_s(msg, msgSize, "\a\nCan't open for read %s", buf); perror(msg); } } return rfp; } // openInput //-------------------------------------------------------------------------- const int outSize = bufSize + 50; void stripName(char *inFname, char *obuf) // --------- { char *s = inFname; while (*s++ != '\0'); while (--s != inFname) if (*s == '.') *s = '\0'; // Remove .txt else if ((*s == '\\') || (*s == '/')) // Remove any directory path { ++s; break; } strcpy_s(obuf, outSize, s); } // stripName //-------------------------------------------------------------------------- bool openDir(char *dir) { // ------- char baseName[bufSize]; sprintf_s(baseName, bufSize, "Water%dx%d", R, C); strcpy_s(dir, bufSize, baseName); int fd = -1, sub = 0; do { if ( (fd = _mkdir(dir)) != -1) break; if (errno != EEXIST) { sprintf_s(baseName, bufSize, "\a\nCan't make folder %s", dir); perror(baseName); return false; } sprintf_s(dir, bufSize, "%s_%d", baseName, ++sub); } while (true); printf("Output file(s) are in folder %s\n", dir); return true; } // openDir //-------------------------------------------------------------------------- FILE *openOutput(char *dir, char* inFname) // ---------- { const int baseSize = bufSize + 25; char buf[outSize], baseName[baseSize]; sprintf_s(baseName, baseSize, "%s\\%s",dir, inFname); if (++outputFileNumber > 0) { sprintf_s(buf, baseSize, "_%d", outputFileNumber); strcat_s(baseName, baseSize, buf); } sprintf_s(buf, outSize, "%s.html", baseName); FILE *wfp = NULL; int sub = 0; do { if (_access_s(buf, 00) == ENOENT) { break; } else { sprintf_s(buf, outSize, "%s_%d.html", baseName, ++sub); } } while (true); if (fopen_s(&wfp, buf, "w") != 0) { sprintf_s(baseName, outSize, "\a\nCan't open for write %s", buf); perror(baseName); } return wfp; } // openOutput //-------------------------------------------------------------------------- bool checkSize() // --------- { if (RC > maxRC) { char msg[100]; sprintf_s(msg, 100, "Order limit RxC is set at %d", maxRC); reportError(msg); return false; } return true; } // checkSize //-------------------------------------------------------------------------- void reportElapsedTime(time_t startTime) // ----------------- { int et = (int)difftime(time(NULL), startTime); if (et > 0) printf("\nelapsed time %d:%02d:%02d\n", et/3600, et%3600/60, et%60); } // reportElapsedTime //-------------------------------------------------------------------------- bool doAnother(bool *inputOrder, bool writeError) // --------- { if (writeError) return false; printf("\nContinue? input y (yes) or n (no) or the order: "); if (getYorInts(&R, &C)) { *inputOrder = (R<0); return true; } else { freeStore(); return false; } } // doAnother //-------------------------------------------------------------------------- bool startOutputFile(char *dir, char *inFn, FILE **wfp, bool *writeError) // --------------- { if (*wfp != NULL) { writeFoot(*wfp, writeError); fclose(*wfp); *wfp = NULL; if (*writeError) return false; if (fileRectNumber!=0) fileRectNumber = 1; } if ((*wfp = openOutput(dir, inFn)) == NULL) { *writeError = true; return false; } if (!writeHead(*wfp)) { *writeError = true; return false; } return true; } // startOutputFile //-------------------------------------------------------------------------- int main() { // ---- outputLocalTime(); bool another = true, inputOrder = true; do { // for each input file bool writeError = false; if (inputOrder) { printf("\nOrder? "); if (!getInts(&R, &C, -1)) break;} if (checkSize()) { initGlobals(); char dir[bufSize]; if (openDir(dir)) { const int inSize = bufSize + 4; // +4 to add .txt if needed char ibuf[inSize]; FILE *rfp = openInput(ibuf, inSize); if (rfp != NULL) { printf("\nColor ponds by size, y (yes) or n (no)? "); multicolor=getY(); inputRectNumber = 0; fileRectNumber = 0; outputFileNumber = -1; FILE *wfp = NULL; char obuf[outSize]; stripName(ibuf, obuf); if (startOutputFile(dir, obuf, &wfp, &writeError)) { time_t startTime = time(NULL); while (inputRectangle(rfp)) { // for each rectangle in file if ((fileRectNumber > rectanglesPerFile) && !startOutputFile(dir, obuf, &wfp, &writeError)) break; if (!getWater(wfp, &writeError)) break; } if (wfp != NULL) { if (!writeError) writeFoot(wfp, &writeError); fclose(wfp); } reportElapsedTime(startTime); } fclose(rfp); } // (rfp != NULL } // if (openDir } // (checkSize another = doAnother(&inputOrder, writeError); } while (another); printf("\nPress a key to close the console"); while (!_kbhit()) Sleep(250); return 0; } // main