Hi all, and thanks in advance for your help.

I have a program which stores some large arrays of ints and reads and writes from text files. main() takes commands with cin and then runs various functions. One of these, generateSentence(), takes three ints and a char* as arguments, but a stack overflow exception is thrown when the function is called. No large variables exist in main(), and all my big arrays are allocated dynamically. Other functions, such as absorb(), run without any problem. In desperation, I changed the stack size in properties, which was mysteriously at 0, to 1,000,000, but to no avail.

(Sorry if this is a simple issue - I'm an experienced programmer but new to C++ and Visual Studio.)

Here's the code for main():

int main ()
{
	int mode = 0;
	int seedOffset = 0;
	int files = 0;

	int maxDepth = 0;

	string command;
	string dictName;
	char* fileName = "None";
	char* dictionaryName = "None";
	char* sequenceFileName;
	string lastFileName = "None";

	sequenceFileName = new (nothrow) char [30];

	sequenceFileName[0] = '\0';

	while (1) {

		cout << "Command or file to absorb: ";
		cin >> command;
		
		if (command == "q")
			return 1;

		else if (command == "c") {
			cout << "Links cleared." << endl;
			clearLinks();
		}

		else if (command == "g") {
			if (dictionaryName == "None") {
				cout << endl << "Dictionary file? ";
				cin >> dictName;
				dictionaryName = &dictName[0];
			}

			generateSentence(mode, seedOffset, dictionaryName, defMaxDepth);
			seedOffset++;
			cout << endl;
		}

		else if (command == "gdict") {
			cout << endl << "Dictionary file? ";
			cin >> dictName;
			dictionaryName = &dictName[0];
			generateSentence(mode, seedOffset, dictionaryName, defMaxDepth);
			seedOffset++;
			cout << endl;
		}
		else if (command == "gdepth") {
			if (dictionaryName == "None") {
				cout << endl << "Dictionary file? ";
				cin >> dictName;
				dictionaryName = &dictName[0];
			}
			cout << endl << "Maximum link depth? ";
			cin >> maxDepth;
			generateSentence(mode, seedOffset, dictionaryName, maxDepth + 1);
			seedOffset++;
			cout << endl;
		}

		else if (command == "gs") {
			if (dictionaryName == "None") {
				cout << endl << "Dictionary file? ";
				cin >> dictName;
				dictionaryName = &dictName[0];
			}
			for (int i = 0; i < 12; i++) {
				generateSentence(mode, seedOffset, dictionaryName, defMaxDepth);
				seedOffset++;
			}
			cout << endl;
		}

		else if (command == "d") {
			mode = DISPLAY;
			cout << "Display mode:" << endl;
		}

		else if (command == "n") {
			mode = NORMAL;
			cout << "Normal mode:" << endl;
		}

		else if (command == "adepth") {
			cout << endl << "File to absorb? ";
			cin >> command;
			fileName = &command[0];
			cout << endl << "Dictionary file? ";
			cin >> dictName;
			dictionaryName = &dictName[0];
			cout << endl << "Maximum link depth? ";
			cin >> maxDepth;
			if (dictName == "new") {
				FILE* outFile;
				fopen_s(&outFile, "dictionary.txt", "w");
				fclose(outFile);
				dictionaryName = "dictionary.txt";
			}
			cout << endl << "Absorbing " << fileName << " ..." << endl;
			absorb(fileName, dictionaryName, mode, maxDepth + 1);
		}

		else if (command == "asequence") {
			cout << endl << "Base file name to absorb? ";
			cin >> command;
			fileName = &command[0];
			cout << endl << "Dictionary file? ";
			cin >> dictName;
			dictionaryName = &dictName[0];
			cout << endl << "Maximum link depth? ";
			cin >> maxDepth;
			cout << endl << "Files in sequence? ";
			cin >> files;
			if (dictName == "new") {
				FILE* outFile;
				fopen_s(&outFile, "dictionary.txt", "w");
				fclose(outFile);
				dictionaryName = "dictionary.txt";
			}
			for (int i = 1; i <= files; i++) {
				sequenceFileName[0] = '\0';
				strcat(sequenceFileName, fileName);
				char num = i + '0';
				char numbox[2];
				numbox[0] = num;
				numbox[1] = '\0';
				strcat(sequenceFileName, numbox);
				cout << endl << "Absorbing " << sequenceFileName << " ..." << endl;
				absorb(sequenceFileName, dictionaryName, mode, maxDepth + 1);
			}
		}

		else {
			if (command == "s")
				fileName = &lastFileName[0];
			else fileName = &command[0];

			lastFileName = fileName;
			cout << endl << "Dictionary file? ";
			cin >> dictName;
			dictionaryName = &dictName[0];
			if (dictName == "new") {
				FILE* outFile;
				fopen_s(&outFile, "dictionary.txt", "w");
				fclose(outFile);
				dictionaryName = "dictionary.txt";
			}
			cout << endl << "Absorbing " << fileName << " ..." << endl;
			absorb(fileName, dictionaryName, mode, defMaxDepth);
		}

		
	}
	return 1;
}

The full file is attached.

Thanks for any and all help!

Edited 6 Years Ago by lukebradford: Additional information about functions in main()

Attachments
// Syntactica.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <sys/stat.h>
#include <windows.h>
#include <time.h>
#include <math.h>
#include "randomc.h"
using namespace std;

int absorb(char* fileName, char* dictionaryName, int mode, int maxDepth);
int absorbWord(int* word);
int absorbSentence(char* dictionaryName, int maxDepth);
int absorbLinks(int i, int si, int* text, int length, int maxDepth);
int isLetter(int c);
int isInWordSymbol(int c);
int charToIndex(int c);
int generateWord(int mode, int seedOffset);
int generateSentence(int mode, int seedOffset, char* dictionaryName, int maxDepth);
int valueToCharsAt(int value, int* text, int index, int digits);
int charsToValueAt(int* text, int index, int digits);
bool wordIsAt(int* word, int i, int* text);
bool depthMatch(int depth, int i, int* text);
int isAbbreviation(int i, int* text);
int incrementLink(int i, int* text);
int clearLinks();
int clearSentence();
int lowercase(int letter);
int uppercase(int letter);

const int kSentenceL = 100;
const int kWordL = 30;
const int kLinksL = 10000;
const int defMaxDepth = 4;
const int kLengthBuffer = 10000;
const bool kAlphaMode = true;

int links[30][30][30][30];

int sentence[kSentenceL][kWordL];

enum {NORMAL, DISPLAY};

#define dout if(mode==DISPLAY) cout

int main ()
{
	int mode = 0;
	int seedOffset = 0;
	int files = 0;

	int maxDepth = 0;

	string command;
	string dictName;
	char* fileName = "None";
	char* dictionaryName = "None";
	char* sequenceFileName;
	string lastFileName = "None";

	sequenceFileName = new (nothrow) char [30];

	sequenceFileName[0] = '\0';

	while (1) {

		cout << "Command or file to absorb: ";
		cin >> command;
		
		if (command == "q")
			return 1;

		else if (command == "c") {
			cout << "Links cleared." << endl;
			clearLinks();
		}

		else if (command == "g") {
			if (dictionaryName == "None") {
				cout << endl << "Dictionary file? ";
				cin >> dictName;
				dictionaryName = &dictName[0];
			}

			generateSentence(mode, seedOffset, dictionaryName, defMaxDepth);
			seedOffset++;
			cout << endl;
		}

		else if (command == "gdict") {
			cout << endl << "Dictionary file? ";
			cin >> dictName;
			dictionaryName = &dictName[0];
			generateSentence(mode, seedOffset, dictionaryName, defMaxDepth);
			seedOffset++;
			cout << endl;
		}
		else if (command == "gdepth") {
			if (dictionaryName == "None") {
				cout << endl << "Dictionary file? ";
				cin >> dictName;
				dictionaryName = &dictName[0];
			}
			cout << endl << "Maximum link depth? ";
			cin >> maxDepth;
			generateSentence(mode, seedOffset, dictionaryName, maxDepth + 1);
			seedOffset++;
			cout << endl;
		}

		else if (command == "gs") {
			if (dictionaryName == "None") {
				cout << endl << "Dictionary file? ";
				cin >> dictName;
				dictionaryName = &dictName[0];
			}
			for (int i = 0; i < 12; i++) {
				generateSentence(mode, seedOffset, dictionaryName, defMaxDepth);
				seedOffset++;
			}
			cout << endl;
		}

		else if (command == "d") {
			mode = DISPLAY;
			cout << "Display mode:" << endl;
		}

		else if (command == "n") {
			mode = NORMAL;
			cout << "Normal mode:" << endl;
		}

		else if (command == "adepth") {
			cout << endl << "File to absorb? ";
			cin >> command;
			fileName = &command[0];
			cout << endl << "Dictionary file? ";
			cin >> dictName;
			dictionaryName = &dictName[0];
			cout << endl << "Maximum link depth? ";
			cin >> maxDepth;
			if (dictName == "new") {
				FILE* outFile;
				fopen_s(&outFile, "dictionary.txt", "w");
				fclose(outFile);
				dictionaryName = "dictionary.txt";
			}
			cout << endl << "Absorbing " << fileName << " ..." << endl;
			absorb(fileName, dictionaryName, mode, maxDepth + 1);
		}

		else if (command == "asequence") {
			cout << endl << "Base file name to absorb? ";
			cin >> command;
			fileName = &command[0];
			cout << endl << "Dictionary file? ";
			cin >> dictName;
			dictionaryName = &dictName[0];
			cout << endl << "Maximum link depth? ";
			cin >> maxDepth;
			cout << endl << "Files in sequence? ";
			cin >> files;
			if (dictName == "new") {
				FILE* outFile;
				fopen_s(&outFile, "dictionary.txt", "w");
				fclose(outFile);
				dictionaryName = "dictionary.txt";
			}
			for (int i = 1; i <= files; i++) {
				sequenceFileName[0] = '\0';
				strcat(sequenceFileName, fileName);
				char num = i + '0';
				char numbox[2];
				numbox[0] = num;
				numbox[1] = '\0';
				strcat(sequenceFileName, numbox);
				cout << endl << "Absorbing " << sequenceFileName << " ..." << endl;
				absorb(sequenceFileName, dictionaryName, mode, maxDepth + 1);
			}
		}

		else {
			if (command == "s")
				fileName = &lastFileName[0];
			else fileName = &command[0];

			lastFileName = fileName;
			cout << endl << "Dictionary file? ";
			cin >> dictName;
			dictionaryName = &dictName[0];
			if (dictName == "new") {
				FILE* outFile;
				fopen_s(&outFile, "dictionary.txt", "w");
				fclose(outFile);
				dictionaryName = "dictionary.txt";
			}
			cout << endl << "Absorbing " << fileName << " ..." << endl;
			absorb(fileName, dictionaryName, mode, defMaxDepth);
		}

		
	}
	return 1;
}

int absorb(char* fileName, char* dictionaryName, int mode, int maxDepth)
{
	FILE* inFile;
	fopen_s(&inFile, fileName, "r");
	if (inFile == NULL) {
		strcat(fileName, ".txt");
		fopen_s(&inFile, fileName, "r");
	}
	if (inFile == NULL)
		cout << "Unable to open file \'" << fileName << "\'" << endl;
	else {
		struct stat st;
		stat(fileName, &st);
		int length = st.st_size;

		int* text = new (nothrow) int [length + 20000];
		if (text == 0) {
			cout << "Unable to allocate memory" << endl;
			return 0;
		}

		for (int i = 0; i < length; i++)
			text[i] = 0;
		
		int i = 0;
		int c = 0;
		int j;

		while (c != EOF) {
			c = getc(inFile);
			text[i] = c;
			i++;
		}

		i = 0;
		int wordi = 1;
		int currentWord[kWordL];
		for (int i = 0; i < kWordL; i++)
			currentWord[i] = 0;

		clearSentence();

		sentence[0][0] = '[';
		int si = 1;

		int chars = 0;
		int charsNoSpaces = 0;
		int words = 0;
		int sentences = 0;
		int lines = 1;
		bool inWord = false;
		bool inSentence = true;
		bool inQuote = false;

		while (text[i] != 0)
		{
			if (!inWord) {
				if (isLetter(text[i])) {
					words++; 
					inWord = true;
					currentWord[0] = text[i];					
				}
			}
			else {
				if (!isLetter(text[i]) && !isInWordSymbol(text[i])) {
					inWord = false;

					//cout << "Current word: " << si << endl;

					for (int i = 0; i < wordi; i++) {
						//cout << (char)currentWord[i];
						sentence[si][i] = currentWord[i];
					}
					sentence[si][wordi] = 0;

					//cout << endl;
					//for (int i = 0; i < 30; i++)
					//	cout << (char)sentence[i][0];

					si++;

					dout << endl;
					wordi = 1;
					for (int i = 0; i < kWordL; i++)
						currentWord[i] = 0;
				}
				else {
					if (wordi < kWordL - 1) {
						currentWord[wordi] = text[i];
						wordi++; }
				}
			}

			if (text[i] == ',' || text[i] == ';' || 
				text[i] == ':' || text[i] == '"' ||
				text[i] == '(' || text[i] == ')') {

				sentence[si][0] = text[i];
				sentence[si][1] = 0;
				si++;

			}

			if (text[i] == '-' && !inWord) {
				sentence[si][0] = text[i];
				sentence[si][1] = 0;
				si++;
			}

			if (text[i] == '.' || text[i] == '?' || text[i] == '!') {

				bool endOfSentence = true;

				sentence[si][0] = text[i];
				sentence[si][1] = 0;
								
				if (text[i + 1] == '.' && text[i + 2] == '.') {
					sentence[si][1] = '.';
					sentence[si][2] = '.';
					sentence[si][3] = 0;
					i += 2;
					for (j = i; text[j] != EOF && !isLetter(text[j]) && text[j] != '!' && text[j] != '?'; j++) {}
					if (isLetter(text[j]) == 1)
						endOfSentence = false;
					if (text[j] == '!' || text[j] == '?') {
						sentence[si+1][0] = text[j];
						sentence[si+1][1] = 0;
						si++;
						i++;
					}
				}

				
				if (text[i] == '.' && isAbbreviation(i, text))
					endOfSentence = false;

				if (text[i + 1] == '"') {
					sentence[si + 1][0] = text[i + 1];
					sentence[si + 1][1] = 0;
					si++;

					int j;
					if (text[i] == '?' || text[i] == '!') {
						for (j = i; text[j] != EOF && !isLetter(text[j]); j++) {}
						if (isLetter(text[j]) == 1)
							endOfSentence = false;
					}
					i++;
				}

				if (text[i + 1] == ')') {
					sentence[si + 1][0] = ')';
					sentence[si + 1][1] = 0;
					si++;
					i++;
				}

				if (endOfSentence) {
					sentence[1][0] = lowercase(sentence[1][0]);
					sentence[si + 1][0] = ']';
					sentence[si + 1][1] = 0;

					absorbSentence(dictionaryName, maxDepth);

					cout << "Absorbed sentence: ";

					for (int i = 0; sentence[i][0] != 0; i++) {
						for (int j = 0; sentence[i][j] != 0; j++)
							cout << (char)sentence[i][j];
						cout << " ";
					}
					cout << endl;
					//system("PAUSE");

					si = 0;
					sentences++;

					clearSentence();
					sentence[0][0] = '[';
				}

				si++;
			}

			if (text[i] == '\n')
				lines++;

			if (text[i] != 0 && text[i] != '\n') {
				chars++;
				if (text[i] != ' ') charsNoSpaces++;
			}
			i++;
		}

		dout << endl;
		cout << "Sentences:                   " << sentences << endl;
		cout << "Words:                       " << words << endl;
		cout << "Characters:                  " << chars << endl;
		cout << "Characters other than space: " << charsNoSpaces << endl;
		cout << "Lines:                       " << lines << endl;
		cout << endl;

		fclose (inFile);
	}
	return 1;
}

int isLetter(int c)
{
	if (c >= 'A' && c <= 'Z')
		return 2;
	if (c >= 'a' && c <= 'z')
		return 1;
	return 0;
}

int isInWordSymbol(int c)
{
	if (c >= '0' && c <= '9')
		return 1;
	if (c == '-' || c == '\'')
		return 1;
	//if (c >= 128 && c <= 154) // Accented letters, etc.
	//	return 1;
	//if (c >= 160 && c <= 165)

what version of vs are you using? I tried to compile that *.cpp file using VC++ 2008 Express and get lots of errors. There have been lots of changes between vc++ 6.0 and 2008, so you might want to compile it with 2008.

Also, please post randomc.h

Comments
Thanks for the help!

Here are randomc.h and mersenne.cpp, which are the only other code files that syntactica.cpp uses. I am using Visual C++ 2008 Express, and I don't get any errors when I compile. Could you tell me some of the errors you're having?

Thanks so much for your help.

what version of vs are you using? I tried to compile that *.cpp file using VC++ 2008 Express and get lots of errors. There have been lots of changes between vc++ 6.0 and 2008, so you might want to compile it with 2008.

Also, please post randomc.h

Attachments
/**************************   mersenne.cpp   **********************************
* Author:        Agner Fog
* Date created:  2001
* Last modified: 2008-11-16
* Project:       randomc.h
* Platform:      Any C++
* Description:
* Random Number generator of type 'Mersenne Twister'
*
* This random number generator is described in the article by
* M. Matsumoto & T. Nishimura, in:
* ACM Transactions on Modeling and Computer Simulation,
* vol. 8, no. 1, 1998, pp. 3-30.
* Details on the initialization scheme can be found at
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
*
* Further documentation:
* The file ran-instructions.pdf contains further documentation and 
* instructions.
*
* Copyright 2001-2008 by Agner Fog. 
* GNU General Public License http://www.gnu.org/licenses/gpl.html
*******************************************************************************/

#include "stdafx.h"
#include "randomc.h"

void CRandomMersenne::Init0(int seed) {
   // Seed generator
   const uint32_t factor = 1812433253UL;
   mt[0]= seed;
   for (mti=1; mti < MERS_N; mti++) {
      mt[mti] = (factor * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
   }
}

void CRandomMersenne::RandomInit(int seed) {
   // Initialize and seed
   Init0(seed);

   // Randomize some more
   for (int i = 0; i < 37; i++) BRandom();
}


void CRandomMersenne::RandomInitByArray(int const seeds[], int NumSeeds) {
   // Seed by more than 32 bits
   int i, j, k;

   // Initialize
   Init0(19650218);

   if (NumSeeds <= 0) return;

   // Randomize mt[] using whole seeds[] array
   i = 1;  j = 0;
   k = (MERS_N > NumSeeds ? MERS_N : NumSeeds);
   for (; k; k--) {
      mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) + (uint32_t)seeds[j] + j;
      i++; j++;
      if (i >= MERS_N) {mt[0] = mt[MERS_N-1]; i=1;}
      if (j >= NumSeeds) j=0;}
   for (k = MERS_N-1; k; k--) {
      mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - i;
      if (++i >= MERS_N) {mt[0] = mt[MERS_N-1]; i=1;}}
   mt[0] = 0x80000000UL;  // MSB is 1; assuring non-zero initial array

   // Randomize some more
   mti = 0;
   for (int i = 0; i <= MERS_N; i++) BRandom();
}


uint32_t CRandomMersenne::BRandom() {
   // Generate 32 random bits
   uint32_t y;

   if (mti >= MERS_N) {
      // Generate MERS_N words at one time
      const uint32_t LOWER_MASK = (1LU << MERS_R) - 1;       // Lower MERS_R bits
      const uint32_t UPPER_MASK = 0xFFFFFFFF << MERS_R;      // Upper (32 - MERS_R) bits
      static const uint32_t mag01[2] = {0, MERS_A};

      int kk;
      for (kk=0; kk < MERS_N-MERS_M; kk++) {    
         y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
         mt[kk] = mt[kk+MERS_M] ^ (y >> 1) ^ mag01[y & 1];}

      for (; kk < MERS_N-1; kk++) {    
         y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
         mt[kk] = mt[kk+(MERS_M-MERS_N)] ^ (y >> 1) ^ mag01[y & 1];}      

      y = (mt[MERS_N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
      mt[MERS_N-1] = mt[MERS_M-1] ^ (y >> 1) ^ mag01[y & 1];
      mti = 0;
   }
   y = mt[mti++];

   // Tempering (May be omitted):
   y ^=  y >> MERS_U;
   y ^= (y << MERS_S) & MERS_B;
   y ^= (y << MERS_T) & MERS_C;
   y ^=  y >> MERS_L;

   return y;
}


double CRandomMersenne::Random() {
   // Output random float number in the interval 0 <= x < 1
   // Multiply by 2^(-32)
   return (double)BRandom() * (1./(65536.*65536.));
}


int CRandomMersenne::IRandom(int min, int max) {
   // Output random integer in the interval min <= x <= max
   // Relative error on frequencies < 2^-32
   if (max <= min) {
      if (max == min) return min; else return 0x80000000;
   }
   // Multiply interval with random and truncate
   int r = int((double)(uint32_t)(max - min + 1) * Random() + min); 
   if (r > max) r = max;
   return r;
}


int CRandomMersenne::IRandomX(int min, int max) {
   // Output random integer in the interval min <= x <= max
   // Each output value has exactly the same probability.
   // This is obtained by rejecting certain bit values so that the number
   // of possible bit values is divisible by the interval length
   if (max <= min) {
      if (max == min) return min; else return 0x80000000;
   }
#ifdef  INT64_SUPPORTED
   // 64 bit integers available. Use multiply and shift method
   uint32_t interval;                    // Length of interval
   uint64_t longran;                     // Random bits * interval
   uint32_t iran;                        // Longran / 2^32
   uint32_t remainder;                   // Longran % 2^32

   interval = uint32_t(max - min + 1);
   if (interval != LastInterval) {
      // Interval length has changed. Must calculate rejection limit
      // Reject when remainder >= 2^32 / interval * interval
      // RLimit will be 0 if interval is a power of 2. No rejection then
      RLimit = uint32_t(((uint64_t)1 << 32) / interval) * interval - 1;
      LastInterval = interval;
   }
   do { // Rejection loop
      longran  = (uint64_t)BRandom() * interval;
      iran = (uint32_t)(longran >> 32);
      remainder = (uint32_t)longran;
   } while (remainder > RLimit);
   // Convert back to signed and return result
   return (int32_t)iran + min;

#else
   // 64 bit integers not available. Use modulo method
   uint32_t interval;                    // Length of interval
   uint32_t bran;                        // Random bits
   uint32_t iran;                        // bran / interval
   uint32_t remainder;                   // bran % interval

   interval = uint32_t(max - min + 1);
   if (interval != LastInterval) {
      // Interval length has changed. Must calculate rejection limit
      // Reject when iran = 2^32 / interval
      // We can't make 2^32 so we use 2^32-1 and correct afterwards
      RLimit = (uint32_t)0xFFFFFFFF / interval;
      if ((uint32_t)0xFFFFFFFF % interval == interval - 1) RLimit++;
   }
   do { // Rejection loop
      bran = BRandom();
      iran = bran / interval;
      remainder = bran % interval;
   } while (iran >= RLimit);
   // Convert back to signed and return result
   return (int32_t)remainder + min;

#endif
}
/*****************************   randomc.h   **********************************
* Author:        Agner Fog
* Date created:  1997
* Last modified: 2008-11-16
* Project:       randomc.h
* Source URL:    www.agner.org/random
*
* Description:
* This header file contains class declarations and other definitions for the 
* randomc class library of uniform random number generators in C++ language.
*
* Overview of classes:
* ====================
*
* class CRandomMersenne:
* Random number generator of type Mersenne twister.
* Source file mersenne.cpp
*
* class CRandomMother:
* Random number generator of type Mother-of-All (Multiply with carry).
* Source file mother.cpp
*
* class CRandomSFMT:
* Random number generator of type SIMD-oriented Fast Mersenne Twister.
* The class definition is not included here because it is not
* portable to all platforms. See sfmt.h and sfmt.cpp for details.
*
* Member functions (methods):
* ===========================
*
* All these classes have identical member functions:
*
* Constructor(int seed):
* The seed can be any integer. The time may be used as seed.
* Executing a program twice with the same seed will give the same sequence 
* of random numbers. A different seed will give a different sequence.
*
* void RandomInit(int seed);
* Re-initializes the random number generator with a new seed.
*
* void RandomInitByArray(int const seeds[], int NumSeeds);
* In CRandomMersenne and CRandomSFMT only: Use this function if you want 
* to initialize with a seed with more than 32 bits. All bits in the seeds[]
* array will influence the sequence of random numbers generated. NumSeeds 
* is the number of entries in the seeds[] array.
*
* double Random();
* Gives a floating point random number in the interval 0 <= x < 1.
* The resolution is 32 bits in CRandomMother and CRandomMersenne, and
* 52 bits in CRandomSFMT.
*
* int IRandom(int min, int max);
* Gives an integer random number in the interval min <= x <= max.
* (max-min < MAXINT).
* The precision is 2^-32 (defined as the difference in frequency between 
* possible output values). The frequencies are exact if max-min+1 is a
* power of 2.
*
* int IRandomX(int min, int max);
* Same as IRandom, but exact. In CRandomMersenne and CRandomSFMT only.
* The frequencies of all output values are exactly the same for an 
* infinitely long sequence. (Only relevant for extremely long sequences).
*
* uint32_t BRandom();
* Gives 32 random bits. 
*
*
* Example:
* ========
* The file EX-RAN.CPP contains an example of how to generate random numbers.
*
*
* Library version:
* ================
* Optimized versions of these random number generators are provided as function
* libraries in randoma.zip. These function libraries are coded in assembly
* language and support only x86 platforms, including 32-bit and 64-bit
* Windows, Linux, BSD, Mac OS-X (Intel based). Use randoma.h from randoma.zip
*
*
* Non-uniform random number generators:
* =====================================
* Random number generators with various non-uniform distributions are 
* available in stocc.zip (www.agner.org/random).
*
*
* Further documentation:
* ======================
* The file ran-instructions.pdf contains further documentation and 
* instructions for these random number generators.
*
* Copyright 1997-2008 by Agner Fog. 
* GNU General Public License http://www.gnu.org/licenses/gpl.html
*******************************************************************************/

#ifndef RANDOMC_H
#define RANDOMC_H

// Define integer types with known size: int32_t, uint32_t, int64_t, uint64_t.
// If this doesn't work then insert compiler-specific definitions here:
#if defined(__GNUC__)
  // Compilers supporting C99 or C++0x have inttypes.h defining these integer types
  #include <inttypes.h>
  #define INT64_SUPPORTED // Remove this if the compiler doesn't support 64-bit integers
#elif defined(_WIN16) || defined(__MSDOS__) || defined(_MSDOS) 
   // 16 bit systems use long int for 32 bit integer
  typedef   signed long int int32_t;
  typedef unsigned long int uint32_t;
#elif defined(_MSC_VER)
  // Microsoft have their own definition
  typedef   signed __int32  int32_t;
  typedef unsigned __int32 uint32_t;
  typedef   signed __int64  int64_t;
  typedef unsigned __int64 uint64_t;
  #define INT64_SUPPORTED // Remove this if the compiler doesn't support 64-bit integers
#else
  // This works with most compilers
  typedef signed int          int32_t;
  typedef unsigned int       uint32_t;
  typedef long long           int64_t;
  typedef unsigned long long uint64_t;
  #define INT64_SUPPORTED // Remove this if the compiler doesn't support 64-bit integers
#endif


/***********************************************************************
System-specific user interface functions
***********************************************************************/

void EndOfProgram(void);               // System-specific exit code (userintf.cpp)

void FatalError(const char *ErrorText);// System-specific error reporting (userintf.cpp)

#if defined(__cplusplus)               // class definitions only in C++
/***********************************************************************
Define random number generator classes
***********************************************************************/

class CRandomMersenne {                // Encapsulate random number generator
// Choose which version of Mersenne Twister you want:
#if 0 
// Define constants for type MT11213A:
#define MERS_N   351
#define MERS_M   175
#define MERS_R   19
#define MERS_U   11
#define MERS_S   7
#define MERS_T   15
#define MERS_L   17
#define MERS_A   0xE4BD75F5
#define MERS_B   0x655E5280
#define MERS_C   0xFFD58000
#else    
// or constants for type MT19937:
#define MERS_N   624
#define MERS_M   397
#define MERS_R   31
#define MERS_U   11
#define MERS_S   7
#define MERS_T   15
#define MERS_L   18
#define MERS_A   0x9908B0DF
#define MERS_B   0x9D2C5680
#define MERS_C   0xEFC60000
#endif

public:
   CRandomMersenne(int seed) {         // Constructor
      RandomInit(seed); LastInterval = 0;}
   void RandomInit(int seed);          // Re-seed
   void RandomInitByArray(int const seeds[], int NumSeeds); // Seed by more than 32 bits
   int IRandom (int min, int max);     // Output random integer
   int IRandomX(int min, int max);     // Output random integer, exact
   double Random();                    // Output random float
   uint32_t BRandom();                 // Output random bits
private:
   void Init0(int seed);               // Basic initialization procedure
   uint32_t mt[MERS_N];                // State vector
   int mti;                            // Index into mt
   uint32_t LastInterval;              // Last interval length for IRandomX
   uint32_t RLimit;                    // Rejection limit used by IRandomX
};    


class CRandomMother {                  // Encapsulate random number generator
public:
   void RandomInit(int seed);          // Initialization
   int IRandom(int min, int max);      // Get integer random number in desired interval
   double Random();                    // Get floating point random number
   uint32_t BRandom();                 // Output random bits
   CRandomMother(int seed) {           // Constructor
      RandomInit(seed);}
protected:
   uint32_t x[5];                      // History buffer
};

#endif // __cplusplus
#endif // RANDOMC_H

There are lots of these

1>c:\dvlp\test10\test10\test10.cpp(659) : warning C4258: 'i' : definition from the for loop is ignored; the definition from the enclosing scope is used
1> c:\dvlp\test10\test10\utils.cpp(646) : definition of 'i' ignored

Although they are warnings you need to correct the problems because they are actual errors. It is trying to tell you what you have attempted to use the value of a loop counter that was declared inside a for loop, which is not legal in c++.

for(int i = 0; <snipped> )

if( i == something) // illegal because i was declared above

Edited 6 Years Ago by Ancient Dragon: n/a

Cool, I can do that. Are these related to the stack overflow I'm getting, or is that a separate issue?

There are lots of these


Although they are warnings you need to correct the problems because they are actual errors.

Here it is, fixed. I only get four warnings, and they're from converting types. Hope this helps!

Don't know yet because I need a clean compile.

Attachments
// Syntactica.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <sys/stat.h>
#include <windows.h>
#include <time.h>
#include <math.h>
#include "randomc.h"
using namespace std;

int absorb(char* fileName, char* dictionaryName, int mode, int maxDepth);
int absorbWord(int* word);
int absorbSentence(char* dictionaryName, int maxDepth);
int absorbLinks(int i, int si, int* text, int length, int maxDepth);
int isLetter(int c);
int isInWordSymbol(int c);
int charToIndex(int c);
int generateWord(int mode, int seedOffset);
int generateSentence(int mode, int seedOffset, char* dictionaryName, int maxDepth);
int valueToCharsAt(int value, int* text, int index, int digits);
int charsToValueAt(int* text, int index, int digits);
bool wordIsAt(int* word, int i, int* text);
bool depthMatch(int depth, int i, int* text);
int isAbbreviation(int i, int* text);
int incrementLink(int i, int* text);
int clearLinks();
int clearSentence();
int lowercase(int letter);
int uppercase(int letter);

const int kSentenceL = 100;
const int kWordL = 30;
const int kLinksL = 10000;
const int defMaxDepth = 4;
const int kLengthBuffer = 10000;
const int kLinkDigits = 6;
const bool kAlphaMode = true;

int links[30][30][30][30];

int sentence[kSentenceL][kWordL];

enum {NORMAL, DISPLAY};

#define dout if(mode==DISPLAY) cout

int main ()
{
	int mode = 0;
	int seedOffset = 0;
	int files = 0;

	int maxDepth = 0;

	string command;
	string dictName;
	char* fileName = "None";
	char* dictionaryName = "None";
	char* sequenceFileName;
	string lastFileName = "None";

	sequenceFileName = new (nothrow) char [30];

	sequenceFileName[0] = '\0';

	while (1) {

		cout << "Command or file to absorb: ";
		cin >> command;
		
		if (command == "q")
			return 1;

		else if (command == "c") {
			cout << "Links cleared." << endl;
			clearLinks();
		}

		else if (command == "g") {
			if (dictionaryName == "None") {
				cout << endl << "Dictionary file? ";
				cin >> dictName;
				dictionaryName = &dictName[0];
			}

			generateSentence(mode, seedOffset, dictionaryName, defMaxDepth);
			seedOffset++;
			cout << endl;
		}

		else if (command == "gdict") {
			cout << endl << "Dictionary file? ";
			cin >> dictName;
			dictionaryName = &dictName[0];
			generateSentence(mode, seedOffset, dictionaryName, defMaxDepth);
			seedOffset++;
			cout << endl;
		}
		else if (command == "gdepth") {
			if (dictionaryName == "None") {
				cout << endl << "Dictionary file? ";
				cin >> dictName;
				dictionaryName = &dictName[0];
			}
			cout << endl << "Maximum link depth? ";
			cin >> maxDepth;
			generateSentence(mode, seedOffset, dictionaryName, maxDepth + 1);
			seedOffset++;
			cout << endl;
		}

		else if (command == "gs") {
			if (dictionaryName == "None") {
				cout << endl << "Dictionary file? ";
				cin >> dictName;
				dictionaryName = &dictName[0];
			}
			for (int i = 0; i < 12; i++) {
				generateSentence(mode, seedOffset, dictionaryName, defMaxDepth);
				seedOffset++;
			}
			cout << endl;
		}

		else if (command == "d") {
			mode = DISPLAY;
			cout << "Display mode:" << endl;
		}

		else if (command == "n") {
			mode = NORMAL;
			cout << "Normal mode:" << endl;
		}

		else if (command == "adepth") {
			cout << endl << "File to absorb? ";
			cin >> command;
			fileName = &command[0];
			cout << endl << "Dictionary file? ";
			cin >> dictName;
			dictionaryName = &dictName[0];
			cout << endl << "Maximum link depth? ";
			cin >> maxDepth;
			if (dictName == "new") {
				FILE* outFile;
				fopen_s(&outFile, "dictionary.txt", "w");
				fclose(outFile);
				dictionaryName = "dictionary.txt";
			}
			cout << endl << "Absorbing " << fileName << " ..." << endl;
			absorb(fileName, dictionaryName, mode, maxDepth + 1);
		}

		else if (command == "asequence") {
			cout << endl << "Base file name to absorb? ";
			cin >> command;
			fileName = &command[0];
			cout << endl << "Dictionary file? ";
			cin >> dictName;
			dictionaryName = &dictName[0];
			cout << endl << "Maximum link depth? ";
			cin >> maxDepth;
			cout << endl << "Files in sequence? ";
			cin >> files;
			if (dictName == "new") {
				FILE* outFile;
				fopen_s(&outFile, "dictionary.txt", "w");
				fclose(outFile);
				dictionaryName = "dictionary.txt";
			}
			for (int i = 1; i <= files; i++) {
				sequenceFileName[0] = '\0';
				strcat_s(sequenceFileName, 100, fileName);
				char num = i + '0';
				char numbox[2];
				numbox[0] = num;
				numbox[1] = '\0';
				strcat_s(sequenceFileName, 100, numbox);
				cout << endl << "Absorbing " << sequenceFileName << " ..." << endl;
				absorb(sequenceFileName, dictionaryName, mode, maxDepth + 1);
			}
		}

		else {
			if (command == "s")
				fileName = &lastFileName[0];
			else fileName = &command[0];

			lastFileName = fileName;
			cout << endl << "Dictionary file? ";
			cin >> dictName;
			dictionaryName = &dictName[0];
			if (dictName == "new") {
				FILE* outFile;
				fopen_s(&outFile, "dictionary.txt", "w");
				fclose(outFile);
				dictionaryName = "dictionary.txt";
			}
			cout << endl << "Absorbing " << fileName << " ..." << endl;
			absorb(fileName, dictionaryName, mode, defMaxDepth);
		}

		
	}
	return 1;
}

int absorb(char* fileName, char* dictionaryName, int mode, int maxDepth)
{
	FILE* inFile;
	fopen_s(&inFile, fileName, "r");
	if (inFile == NULL) {
		strcat_s(fileName, 100, ".txt");
		fopen_s(&inFile, fileName, "r");
	}
	if (inFile == NULL)
		cout << "Unable to open file \'" << fileName << "\'" << endl;
	else {
		struct stat st;
		stat(fileName, &st);
		int length = st.st_size;

		int* text = new (nothrow) int [length + 20000];
		if (text == 0) {
			cout << "Unable to allocate memory" << endl;
			return 0;
		}

		for (int i = 0; i < length; i++)
			text[i] = 0;
		
		int i = 0;
		int c = 0;
		int j;

		while (c != EOF) {
			c = getc(inFile);
			text[i] = c;
			i++;
		}

		i = 0;
		int wordi = 1;
		int currentWord[kWordL];
		for (int i = 0; i < kWordL; i++)
			currentWord[i] = 0;

		clearSentence();

		sentence[0][0] = '[';
		int si = 1;

		int chars = 0;
		int charsNoSpaces = 0;
		int words = 0;
		int sentences = 0;
		int lines = 1;
		bool inWord = false;
		bool inSentence = true;
		bool inQuote = false;

		while (text[i] != 0)
		{
			if (!inWord) {
				if (isLetter(text[i])) {
					words++; 
					inWord = true;
					currentWord[0] = text[i];					
				}
			}
			else {
				if (!isLetter(text[i]) && !isInWordSymbol(text[i])) {
					inWord = false;

					//cout << "Current word: " << si << endl;

					for (int i = 0; i < wordi; i++) {
						//cout << (char)currentWord[i];
						sentence[si][i] = currentWord[i];
					}
					sentence[si][wordi] = 0;

					//cout << endl;
					//for (int i = 0; i < 30; i++)
					//	cout << (char)sentence[i][0];

					si++;

					dout << endl;
					wordi = 1;
					for (int i = 0; i < kWordL; i++)
						currentWord[i] = 0;
				}
				else {
					if (wordi < kWordL - 1) {
						currentWord[wordi] = text[i];
						wordi++; }
				}
			}

			if (text[i] == ',' || text[i] == ';' || 
				text[i] == ':' || text[i] == '"' ||
				text[i] == '(' || text[i] == ')') {

				sentence[si][0] = text[i];
				sentence[si][1] = 0;
				si++;

			}

			if (text[i] == '-' && !inWord) {
				sentence[si][0] = text[i];
				sentence[si][1] = 0;
				si++;
			}

			if (text[i] == '.' || text[i] == '?' || text[i] == '!') {

				bool endOfSentence = true;

				sentence[si][0] = text[i];
				sentence[si][1] = 0;
								
				if (text[i + 1] == '.' && text[i + 2] == '.') {
					sentence[si][1] = '.';
					sentence[si][2] = '.';
					sentence[si][3] = 0;
					i += 2;
					for (j = i; text[j] != EOF && !isLetter(text[j]) && text[j] != '!' && text[j] != '?'; j++) {}
					if (isLetter(text[j]) == 1)
						endOfSentence = false;
					if (text[j] == '!' || text[j] == '?') {
						sentence[si+1][0] = text[j];
						sentence[si+1][1] = 0;
						si++;
						i++;
					}
				}

				
				if (text[i] == '.' && isAbbreviation(i, text))
					endOfSentence = false;

				if (text[i + 1] == '"') {
					sentence[si + 1][0] = text[i + 1];
					sentence[si + 1][1] = 0;
					si++;

					int j;
					if (text[i] == '?' || text[i] == '!') {
						for (j = i; text[j] != EOF && !isLetter(text[j]); j++) {}
						if (isLetter(text[j]) == 1)
							endOfSentence = false;
					}
					i++;
				}

				if (text[i + 1] == ')') {
					sentence[si + 1][0] = ')';
					sentence[si + 1][1] = 0;
					si++;
					i++;
				}

				if (endOfSentence) {
					sentence[1][0] = lowercase(sentence[1][0]);
					sentence[si + 1][0] = ']';
					sentence[si + 1][1] = 0;

					absorbSentence(dictionaryName, maxDepth);

					cout << "Absorbed sentence: ";

					for (int i = 0; sentence[i][0] != 0; i++) {
						for (int j = 0; sentence[i][j] != 0; j++)
							cout << (char)sentence[i][j];
						cout << " ";
					}
					cout << endl;
					//system("PAUSE");

					si = 0;
					sentences++;

					clearSentence();
					sentence[0][0] = '[';
				}

				si++;
			}

			if (text[i] == '\n')
				lines++;

			if (text[i] != 0 && text[i] != '\n') {
				chars++;
				if (text[i] != ' ') charsNoSpaces++;
			}
			i++;
		}

		dout << endl;
		cout << "Sentences:                   " << sentences << endl;
		cout << "Words:                       " << words << endl;
		cout << "Characters:                  " << chars << endl;
		cout << "Characters other than space: " << charsNoSpaces << endl;
		cout << "Lines:                       " << lines << endl;
		cout << endl;

		fclose (inFile);
	}
	return 1;
}

int isLetter(int c)
{
	if (c >= 'A' && c <= 'Z')
		return 2;
	if (c >= 'a' && c <= 'z')
		return 1;
	return 0;
}

int isInWordSymbol(int c)
{
	if (c >= '0' && c <= '9')
		return 1;
	if (c == '-' || c == '\'')
		return 1;
	//if (c >= 128 && c <= 154) // Accented letters, e

>> int goodLinks[kWordL + 1][kLinksL];

That's the culprit that is causing stack overflow. Make it a pointer and allocate the memory with new.

You are also going to have lots of problems with concantinating ".txt" to the pointers such as filename cause those pointers were never allocated enough space to hold the additional text. Suggest you replace all those pointers with std::string to avoid those problems. For example

std::string fileName = "None";
	std::string dictionaryName = "None";
	std::string sequenceFileName;
	string lastFileName = "None";

When you do that you will also have to change the function parameters to use std::string. Well, you really don't HAVE to do that but it would make your program a lot safer. Other changes will be needed too.

Edited 6 Years Ago by Ancient Dragon: n/a

This question has already been answered. Start a new discussion instead.