Ok, I'm working on this code where I read in two lines from a text document, then store them in an array, write a binary code for each to indicate what words are in what array, and then compare the two arrays in a variety of ways. I got most of it to work. I create the binary code for the first line fine, and same for the second. Then, when I try to create the binary code for the array that shows what words are in both arrays, it messes up the binary code I made for the second line.

I know that probably doesn't make sense, so here's the example.
Line 1 = I eat green eggs and ham I eat
Line 2 = I don't like green eggs Sam I am

Words used in both lines (1U2) = I eat green eggs and ham don't like Sam am

Line 1 binary = 1 1 1 1 1 1 0 0 0 0
Line 2 binary = 1 0 1 1 0 0 1 1 1 1

1U2 binary = 1 1 1 1 1 1 1 1 1 1

After it creates 1U2, it changes the binary for Line 2 to
1 1 1 1 0 0 1 1 1 1


I've even tried switching their places in hope that that would help, but it seems that my binary for Line 2 and 1U2 always get messed up when I try to create their binary codes.

And also, when I change it back to my main function, somehow binary code for 1U2 gets messed up as well. I'm not entirely sure how, but it changes from all 1's to 2 0 and the rest 1's. If anyone sees why this is messing up, I would appreciate some help.

Here's the pieces of the code that are giving me an issue (if you want the rest, just ask and I can post it). The red sections are where to code goes wrong:

main ()
   {   int ALast, BLast, ABLast=1, x=0;
       string letter[5] = {"A", "B", "AUB", "A^B", "A-B"};
       int BitA[ABLast], BitB[ABLast], BitAUB[ABLast], BitAIB[ABLast];
       string A[10], B[10], AB[20], AIB[20], A_B[20];
       ifstream InData;


       getfile (InData);
       input (InData, ALast, A);  // Puts the lines into an array
       input (InData, BLast, B);  // Puts the lines into an array
       
       developArray (A, B, AB, ALast, BLast, ABLast, BitA, BitB, BitAUB);
       
[B]       set (BitAIB, ABLast);
       intersect (BitA, BitB, BitAIB, AIB, AB, ABLast); // BitAUB goes bad[/B]

       //print outputs
       write (ABLast, A, BitA, letter[0]);
       cout << endl;

       write (ABLast, B, BitB, letter[1]);
       cout << endl << endl << endl;

       write (ABLast, AB, BitAUB, letter[2]);
       write (ABLast, AIB, BitAIB, letter[3]);
       cout << endl;
       system ("pause");
       return 0;
   }

void developArray (string A[], string B[], string AB[], int ALast, int BLast, int& ABLast, int BitA[], int BitB[], int BitAB[])
// Stores all the functions used to create the arrays A, B, AB, BitA, BitB, Bit AB
     { 
       createArray (A, B, ALast, BLast, AB, ABLast);
       removeDup (A, ALast);
       removeDup (B, BLast);

       set (BitA, ABLast);              
       createBit (A, AB, ALast, ABLast, BitA); 
       
[B]       set (BitB, ABLast);       
       createBit (B, AB, BLast, ABLast, BitB); // B fine

       set (BitAB, ABLast);       
       createBit (AB, AB, ABLast, ABLast, BitAB);  // B goes bad[/B]
     }

void intersect (int BitA[], int BitB[], int BitAB[], string AIB[], string AB[], int ABLast)
// Show what two arrays have in common
     { int x = 0;
       for (int count = 0; count < ABLast; count++)
           { if ( BitA[count] == 1 )
                { if (BitB[count] == 1)
                     { BitAB[count] = 1; 
                       AIB[x] = AB[count];
                       x++;} 
      }     }     }    





// Used in developArray
void set (int Set[], int last)
// Sets all things in array equal to 0
     { for (int z = 0; z < last; z++)
           { Set[z] = 0; } }

void createBit (string A[], string AB[], int ALast, int ABLast, int BitA[]) 
// Compares AB to A and stores in BitA of length ABLast
     { for (int i = 0; i < ABLast; i++)
           { for (int x = 0; x < ALast; x++)
                 { if (AB[i] == A[x])
                      { BitA[i] = 1; 
                        break; }
     }    }     }

Recommended Answers

All 7 Replies

The cause of your problem is almost certainly code executed before your red lines are reached.

My guess - although you haven't shown them - is that the problems really occur in your input() function or, possibly in your createArray() or removeDup() functions.

I'd even guess further that - in writing those functions - you have assumed that an array size can magically change within those functions. If so, you are mistaken. So one of those functions is falling off the end of one of your arrays and corrupting random memory.

Also note that you are passing ALast - an uninitialised variable - to input(). If input() uses its original value you get undefined behaviour. If input() sets ALast to something more than 10, and then loops over the array (from 0 to ALast-1) it will fall off the end of the array. Similar comments for BLast.

A couple of general tips: when trying to find problems like this

1) Do not assume a problem occurs at the point it is detected. The cause is almost certainly code executed before the problem is detected.

2) Try to find a small but complete sample of code that illustrates your problem. In the process of getting to that small but complete sample you might identify the problem yourself. If not, you are not relying on people to work out what is happening in code you have not provided.

Well, I'm not sure if that is the case because I ran tests throughout my developArray function, after each individual thing, and it only changes once it hits the red sections.

It's fine before the red, but changes after if goes through the each createBit() line. The odd this is that BitAB and BitB are changed, but BitA has no issue what so ever.

Now, one thing I thought about is should I just get rid of createArray and put all those call functions back into the main() cause perhaps that would eliminate the issues but I don't see why that would change anything.

Well, I'm not sure if that is the case because I ran tests throughout my developArray function, after each individual thing, and it only changes once it hits the red sections.

No .... you mean your tests did not detect a problem. Your tests will only check things you think to test. If you didn't anticipate the particular problem that is occurring, a fault will get past your testing and cause chaos later.

In practice, at least 95% of problems with "variables changing in unexplained ways" result from some code that the programmer has previously tested and insists is unrelated to the problem. I believe that is happening for you.

It's fine before the red, but changes after if goes through the each createBit() line. The odd this is that BitAB and BitB are changed, but BitA has no issue what so ever.

Yep. That's the way it goes. Symptoms caused by malfunctioning code tend to manifest in odd ways .....

Now, one thing I thought about is should I just get rid of createArray and put all those call functions back into the main() cause perhaps that would eliminate the issues but I don't see why that would change anything.

That's because you are assuming the cause of the problem is the code where you see the problem. Whereas, code that is run previously is also a candidate as the cause.

Alright, so if you think the problem is happening in the rest of my code, then perhaps I need to show the rest of it so that someone can see the issue. Cause, as far as how I wrote it, it worked fine as I went along.

#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <sstream>

using namespace std;

void getfile (ifstream&);
void input (ifstream&, int&, string*);
void write (int, string*, int*, string);
void createArray (string*, string*, int, int, string*, int&);
void run (int, string*, string*, int, int&);
bool check (string*, string*, int);
bool check2 (string*, string*, int, int, int);
void set (int*, int);
void createBit (string*, string*, int, int, int*);
void removeDup (string*, int);
void developArray (string*, string*, string*, int, int, int&, int*, int*, int*);
void intersect (int*, int*, int*, string*, string*, int);

main ()
   {   int ALast, BLast, ABLast=1, x=0;
       string letter[5] = {"A", "B", "AUB", "A^B", "A-B"};
       int BitA[ABLast], BitB[ABLast], BitAUB[ABLast], BitAIB[ABLast];
       string A[10], B[10], AB[20], AIB[20], A_B[20];
       ifstream InData;


       getfile (InData);

       input (InData, ALast, A);  // Puts the lines into an array
       input (InData, BLast, B);  // Puts the lines into an array

       
       developArray (A, B, AB, ALast, BLast, ABLast, BitA, BitB, BitAUB);
       
       set (BitAIB, ABLast);
       intersect (BitA, BitB, BitAIB, AIB, AB, ABLast);

       //print outputs
       write (ABLast, A, BitA, letter[0]);
       cout << endl;
       write (ABLast, B, BitB, letter[1]);
       cout << endl << endl << endl;
       write (ABLast, AB, BitAUB, letter[2]);
       write (ABLast, AIB, BitAIB, letter[3]);
       
       cout << endl;
       system ("pause");
       return 0;
   }

void getfile (ifstream& InData)
// Gets the file from the user
     { string file;
       cout << "Enter the name of the file: ";
       cin >> file;
       InData.open (file.c_str());
       while(!InData)// Prompt for new file name if not able to open
         { cout << "Unable to open file. Enter a different name: ";
	       InData.clear();
           cin >> file;
	       InData.open(file.c_str()); 
         }
     }

void input (ifstream& file, int& end, string word[])
/* Takes one line from file and then breaks up 
 into words which are stored in an array */
     { int x=0, i=0;
       string line;
       getline(file, line);
       stringstream str(line);
       while (str >> word[x])
             { x++; }
       end = x;
     }
void developArray (string A[], string B[], string AB[], int ALast, int BLast, int& ABLast, int BitA[], int BitB[], int BitAB[])
// Stores all the functions used to create the arrays A, B, AB, BitA, BitB, Bit AB
     { 
       createArray (A, B, ALast, BLast, AB, ABLast);

       removeDup (A, ALast);
       removeDup (B, BLast);

       set (BitA, ABLast);
       set (BitB, ABLast);
       set (BitAB, ABLast);

       createBit (A, AB, ALast, ABLast, BitA); 
       createBit (B, AB, BLast, ABLast, BitB);
       createBit (AB, AB, ABLast, ABLast, BitAB);
     }

void write (int last, string array[], int list[], string letter)
// Writes to screen
     { int x=0;
       cout << letter << " = ";
       while (x < last)
             { cout << array[x] << " ";
               ++x; }
       cout << endl << letter << " = ";
       for (int n =0; n < last; n++)
           { cout << list[n] << " "; }
       cout << endl;
      }

void intersect (int BitA[], int BitB[], int BitAB[], string AIB[], string AB[], int ABLast)
// Show what two arrays have in common
     { int x = 0;
       for (int count = 0; count < ABLast; count++)
           { if ( BitA[count] == 1 )
                { if (BitB[count] == 1)
                     { BitAB[count] = 1; 
                       AIB[x] = AB[count];
                       x++;} 
           }   }    }    


// Used in developArray
void removeDup (string one[], int end)
/* Gets rid of any duplicated words in a 
line so it doesn't affect the bit string */
     { int x = 0;
       string two[end];
       for (int count = 0; count < end; count++)  //switch values
           { two[count] = one[count]; }
       for (int z = 0; z < end; z++) //set second array
              { one[z] = " "; }
       run (end, one, two, 0, x); // remove duplicates in two and restores one
     }

void createArray (string x[], string y[], int xlast, int ylast, string Bit[], int& i)
// Creates the union array in words
     { int f = 1;
       Bit[0] = x[0]; // assigns first
       run (xlast, Bit, x, f, i);
       f = 0;
       run (ylast, Bit, y, f, i);
}

void run (int last, string Bit[], string x[], int from, int& i)
// Prevents words from repeating in the union array
     { while (from < last)
        {  if (check (Bit, x, from) == true)
              { Bit[i] = x[from]; 
                ++i;
                ++from; } 
           else ++from; }
     }
bool check (string Bit[], string From[], int x)
// Checks to make sure nothing is repeated
     { int prev = 0;
       while (prev <= x)
          { if ( From[x] != Bit[prev] )
                { ++prev; } 
            else return false; }
       return true;
     }
     
void set (int Set[], int last)
// Sets all things in array equal to 0
     { for (int z = 0; z < last; z++)
           { Set[z] = 0; } }

void createBit (string A[], string AB[], int ALast, int ABLast, int BitA[]) 
// Compares AB to A and stores in BitA of length ABLast
     { for (int i = 0; i < ABLast; i++)
           { for (int x = 0; x < ALast; x++)
                 { if (AB[i] == A[x])
                      { BitA[i] = 1; 
                        break; }
     }    }     }

I had to edit what you posted... the indentation got to me--

#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <sstream>

using namespace std;

void getfile (ifstream&);
void input (ifstream&, int&, string*);
void write (int, string*, int*, string);
void createArray (string*, string*, int, int, string*, int&);
void run (int, string*, string*, int, int&);
bool check (string*, string*, int);
bool check2 (string*, string*, int, int, int);
void set (int*, int);
void createBit (string*, string*, int, int, int*);
void removeDup (string*, int);
void developArray (string*, string*, string*, int, int, int&, int*, int*, int*);
void intersect (int*, int*, int*, string*, string*, int);

main (){   

	int ALast, BLast, ABLast=1, x=0;
	string letter[5] = {"A", "B", "AUB", "A^B", "A-B"};
	int BitA[ABLast], BitB[ABLast], BitAUB[ABLast], BitAIB[ABLast];
	string A[10], B[10], AB[20], AIB[20], A_B[20];
	ifstream InData;

	getfile (InData);

	input (InData, ALast, A);  // Puts the lines into an array
	input (InData, BLast, B);  // Puts the lines into an array

	developArray (A, B, AB, ALast, BLast, ABLast, BitA, BitB, BitAUB);

	set (BitAIB, ABLast);
	intersect (BitA, BitB, BitAIB, AIB, AB, ABLast);

	//print outputs
	write (ABLast, A, BitA, letter[0]);
	cout << endl;
	write (ABLast, B, BitB, letter[1]);
	cout << endl << endl << endl;
	write (ABLast, AB, BitAUB, letter[2]);
	write (ABLast, AIB, BitAIB, letter[3]);

	cout << endl;
	system ("pause");
	return 0;
}

void getfile (ifstream& InData){// Gets the file from the user 

	string file;
	cout << "Enter the name of the file: ";
	cin >> file;
	InData.open (file.c_str());
	while(!InData){// Prompt for new file name if not able to open 
		cout << "Unable to open file. Enter a different name: ";
		InData.clear();
		cin >> file;
		InData.open(file.c_str()); 
	}
}

void input (ifstream& file, int& end, string word[]){
/* Takes one line from file and then breaks up 
into words which are stored in an array */

	int x=0, i=0;
	string line;
	getline(file, line);
	stringstream str(line);
	while (str >> word[x]){ 
		x++; 
	}
	end = x;
}

void developArray (string A[], string B[], string AB[], int ALast, int BLast, int& ABLast, int BitA[], int BitB[], int BitAB[]){
// Stores all the functions used to create the arrays A, B, AB, BitA, BitB, Bit AB

	createArray (A, B, ALast, BLast, AB, ABLast);
	removeDup (A, ALast);
	removeDup (B, BLast);

	set (BitA, ABLast);
	set (BitB, ABLast);
	set (BitAB, ABLast);

	createBit (A, AB, ALast, ABLast, BitA); 
	createBit (B, AB, BLast, ABLast, BitB);
	createBit (AB, AB, ABLast, ABLast, BitAB);
}

void write (int last, string array[], int list[], string letter){ // Writes to screen

	int x=0;
	cout << letter << " = ";
	while (x < last){ 
		cout << array[x] << " ";
		++x; 
	}
	
	cout << endl << letter << " = ";
	
	for (int n =0; n < last; n++){ 
		cout << list[n] << " "; 
	}
	
	cout << endl;
}

void intersect (int BitA[], int BitB[], int BitAB[], string AIB[], string AB[], int ABLast){
// Show what two arrays have in common

	int x = 0;
	for (int count = 0; count < ABLast; count++){ 
		if ( BitA[count] == 1 ){ 
			if (BitB[count] == 1){ 
				BitAB[count] = 1; 
				AIB[x] = AB[count];
				x++;
			} 
		}   
	}
}    


// Used in developArray
void removeDup (string one[], int end){
/* Gets rid of any duplicated words in a 
line so it doesn't affect the bit string */

	int x = 0;
	string two[end];
	for (int count = 0; count < end; count++){//switch values 
		two[count] = one[count]; 
	}
	
	for (int z = 0; z < end; z++){ //set second array
		one[z] = " "; 
	}
	run (end, one, two, 0, x); // remove duplicates in two and restores one
}

void createArray (string x[], string y[], int xlast, int ylast, string Bit[], int& i){
// Creates the union array in words

	int f = 1;
	Bit[0] = x[0]; // assigns first
	run (xlast, Bit, x, f, i);
	f = 0;
	run (ylast, Bit, y, f, i);
}

void run (int last, string Bit[], string x[], int from, int& i){ // Prevents words from repeating in the union array

	while (from < last){
		if (check (Bit, x, from) == true){ 
			Bit[i] = x[from]; 
			++i;
			++from; 
		} 
		else ++from; 
	}
}

bool check (string Bit[], string From[], int x){ // Checks to make sure nothing is repeated 

	int prev = 0;
	while (prev <= x){ 
		if ( From[x] != Bit[prev] ){ 
			++prev; 
		} 
		else return false; 
	}
	
	return true;
}

void set (int Set[], int last){ // Sets all things in array equal to 0

	for (int z = 0; z < last; z++){ 
		Set[z] = 0; 
	} 
}

void createBit (string A[], string AB[], int ALast, int ABLast, int BitA[]) {
// Compares AB to A and stores in BitA of length ABLast

	for (int i = 0; i < ABLast; i++){ 
		for (int x = 0; x < ALast; x++){ 
			if (AB[i] == A[x]){ 
				BitA[i] = 1; 
				break; 
			}
		}
	}
}

Alright. Did anything pop out at you when you went through it though Alex Edwards?

Cause, as far as I know, everything works fine up until that one point.

Unless I some how left something in the buffer that is meticulously placing itself in the second part of my second array instead of the first. But, it shouldn't have cause it produces the answer right according to the words. It's just messing up my 1's and 0's.

Well, I was right. The problem is in your createArray() function .... and in what it does with the arguments passed to it.

ABLast is 1 in main() so the various Bit... arrays in have one element. These are passed to developArray() and then to createArray() which passes them to run() (as the argument named i). run() - in a loop - increments i and sets the value of Bit. That therefore changes ABLast in main() and falls off the end of the Bit.... arrays.

You won't have seen it in your test cases, but input() will also merrily fall off the end of your arrays if handling files with more than 10 words on a line.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.