C Board  

Go Back   C Board > Platform Specific Boards > Linux Programming

Closed Thread
 
LinkBack Thread Tools Display Modes
Old 04-11-2003, 02:58 PM   #1
Registered User
 
Join Date: Apr 2003
Posts: 33
Unix/C++ problem

Hey guys heard of your site through a friend and i decided to give you guys a shot at this problem. I have written a simple code for searching a text file and outputting the number of occurences a certain word appears and the line number to the screen. It works fine in Visual C++ 6.0 but when i load it into Unix it links compiles and everything but outputs the wrong number of occurences. I get no errors or warnings in either one(C++ or Unix). Here is the code:
Code:
//*********************************************************************************************
//
// This program finds a word or phrase input by the user in a file and outputs the lines of
// the file and the number of occurances.
//
//*********************************************************************************************

#include <iostream.h>
#include <fstream.h>

typedef char characterString[45];

char SENTINAL = '*';

int compairText(characterString input, int x, characterString target, int y, int numberOfCharacters);
void convertText(characterString input);

int main()
{
	characterString input;			//input string
	characterString target;			//target string

	int numberOfCharacters = -1;	//number of characters in the target string
	int lineNumber = 1;				//number of lines
	int numberOfMatches = 0;		//keeps the number of matches found
	
	ifstream infile;				//input file
	ofstream outfile;				//output file

	infile.open("hw02.dat");
	outfile.open("Output.dat");

	for(int i = 0; i < 45; i++)
		target[i] = SENTINAL;		//initilizes the target string to *

	cout << "Enter the word to search for: " << endl;
	cin >> target;

	convertText(target);

	for(int j = 0; j < 45; j++)		//finds the number of characters in the target string
	{
		if(target[j] != SENTINAL)
			numberOfCharacters++;
	}

	cout << "Line Number \t Number of Matches" << endl;

	while(infile.peek() != EOF)
	{
		infile.getline(input, 50, '\n');

		convertText(input);

		for(int k = 0; k < 45; k++)	//traverses the input string
		{
			if(target[0] == input[k])
				if(compairText(input, k, target, 0, numberOfCharacters))
				{
					numberOfMatches++;
					k += numberOfCharacters;
				}
		}

		cout << lineNumber <<  "\t\t\t" << numberOfMatches << endl;
		outfile << lineNumber <<  "\t\t\t" << numberOfMatches << endl;

		lineNumber++;
		numberOfMatches = 0;
	}

	infile.close();
	outfile.close();

	return 0;
}

//*********************************************************************************************

int compairText(characterString input, int x, characterString target, int y, int z)
{
	if(z == 0)
		return 1;

	else
	{
		if(input[x] != target[y])
			return 0;

		if(input[x] == target[y])
			if(compairText(input, (x+1), target, (y+1), (z-1)))
				return 1;
	}

}

//*********************************************************************************************

void convertText(characterString x)
{
	for(int i = 0; i < 45; i++)
		if(x[i] >= 65 && x[i] <= 90)
			x[i] += 32;
}
I hope you guys can find out what's wrong with it, and if you need to know anything like why something is delcared or what just ask and I will respond with whatever you need. Thanks a million guys.

-Bill

P.S. sorry about the tags haven't learned how to use them yet, yes i know i know i'm a n00b

Last edited by Maverik; 04-11-2003 at 03:03 PM.
Maverik is offline  
Old 04-11-2003, 08:30 PM   #2
Registered User
 
Codeplug's Avatar
 
Join Date: Mar 2003
Posts: 3,898
Re: Unix/C++ problem

Quote:
Originally posted by Maverik
...but when i load it into Unix it links compiles and everything but outputs the wrong number of occurences.
Like off by one or what? Is it consistently off by the same amount? etc..

gg
Codeplug is offline  
Old 04-11-2003, 09:23 PM   #3
Registered User
 
Codeplug's Avatar
 
Join Date: Mar 2003
Posts: 3,898
- compairText() should have a "return 0;" at the end
- getline() could cause a buffer overrun since your characterString has only 45 chars and you are asking for up to 50
- your code won't work if you process a file that has >45 chars in a single line
- your code has a bug where the following file isn't processed correctly when looking for "hello" (I'll let you figure it out):
- you don't need any of that SENTINAL stuff since strings are already terminated with '\0' (not a bug though)
Code:
hello

world
HELLO

world
Fix all those and see if you still have a problem.

gg
Codeplug is offline  
Old 04-12-2003, 02:19 PM   #4
Registered User
 
Join Date: Apr 2003
Posts: 33
It's not consistanely off by one number or a number, it finds the correct number of occurences if the word does occur but it gives like the nujber 3, 4 or 2 if there aren't anything on the lines. However i am going to try what you posted about the second time and hopefully that will fix it. Thanks for the insite.

-Bill
Maverik is offline  
Old 04-12-2003, 02:51 PM   #5
Registered User
 
Join Date: Apr 2003
Posts: 33
Quote:
Originally posted by Codeplug
- compairText() should have a "return 0;" at the end
- getline() could cause a buffer overrun since your characterString has only 45 chars and you are asking for up to 50
- your code won't work if you process a file that has >45 chars in a single line
- your code has a bug where the following file isn't processed correctly when looking for "hello" (I'll let you figure it out):
- you don't need any of that SENTINAL stuff since strings are already terminated with '\0' (not a bug though)
gg
Ok i've tried all of these and i now have the problem that the program stops looking through the infile after the first or second line. I've tried all of the various things to read infile with a loop such as:
Code:
while(infile).....;
while(infile.peek() != EOF)......;
while(!EOF)......;
and even 
do
while(infile)..........;
I don't know if it's not reading the infile or what's going on. Also i've heard that if you save a file through DOS and send it to unix, DOS puts 2 extra caracters on the end of the line and when saved with ASCII , ASCII only puts one. Right now i have the text file saved as an ASCII and that is suppossed to be compatible with the unix system. Hopefully you can shine through once again. Thanks

-Bill

Last edited by Maverik; 04-12-2003 at 04:20 PM.
Maverik is offline  
Old 04-12-2003, 04:18 PM   #6
Registered User
 
Join Date: Apr 2003
Posts: 33
ok i got it working now. I think the problem was with the getline function. It would read up to 50 characters or to a newline which ever was first. And since the file is fixed so that each line in the file has no more than 45 characters. I should have told you guys that before hand and that would have made it all the difference. But thanks for the help.

-Bill
Maverik is offline  
Old 04-12-2003, 04:20 PM   #7
Registered User
 
Join Date: Apr 2003
Posts: 33
And here is the code if you want it
Code:
#include <iostream.h>
#include <fstream.h>
#include <cstring>

typedef char characterString[45];

int compairText(characterString input, int x, characterString target, int y, int numberOfCharacters);
void convertText(characterString input);

int main()
{
	characterString input;			//input string
	characterString target;			//target string

	int numberOfCharacters = -1;	//number of characters in the target string
	int lineNumber = 1;				//number of lines
	int numberOfMatches = 0;		//keeps the number of matches found
	
	ifstream infile;				//input file
	ofstream outfile;				//output file

	infile.open("hw02.dat");
	outfile.open("Output.dat");

	cout << "Enter the word to search for: " << endl;
	cin >> target;

	convertText(target);

	numberOfCharacters = strlen(target);

	cout << "Line Number \t Number of Matches" << endl;

	while(infile.peek() != EOF)
	{
		infile.getline(input, 50, '\n');

		convertText(input);

		for(int k = 0; k < 45; k++)	//traverses the input string
		{
			if(target[0] == input[k])
				if(compairText(input, k, target, 0, numberOfCharacters))
				{
					numberOfMatches++;
					k =  k + numberOfCharacters - 1;
				}
		}

		cout << lineNumber <<  "\t\t\t" << numberOfMatches << endl;
		outfile << lineNumber <<  "\t\t\t" << numberOfMatches << endl;

		lineNumber++;
		numberOfMatches = 0;
	}

	infile.close();
	outfile.close();

	return 0;
}

//*********************************************************************************************

int compairText(characterString input, int x, characterString target, int y, int z)
{
	if(z == 0)
		return 1;

	else
	{
		if(input[x] != target[y])
			return 0;

		else if(input[x] == target[y])
			if(compairText(input, (x+1), target, (y+1), (z-1)))
				return 1;
	}

return 0;

}

//*********************************************************************************************

void convertText(characterString x)
{
	for(int i = 0; i < 45; i++)
		if(x[i] >= 65 && x[i] <= 90)
			x[i] += 32;
}
Maverik is offline  
Old 04-12-2003, 09:53 PM   #8
Registered User
 
Codeplug's Avatar
 
Join Date: Mar 2003
Posts: 3,898
You are still using telling getline() that you have 50 chars, when you only have 45......bad.

gg
Codeplug is offline  
Old 04-13-2003, 04:02 PM   #9
Registered User
 
Join Date: Feb 2003
Posts: 490
Are you aware that your program (even after your changes) still doesn't work correctly? It runs, and it gives output, but that output is wrong. It is reporting occurrences of the target string on lines where it does not exist.

First, as codeplug pointed out, you have an inconsistency between the defined length of your characterString variable and the length of the input lines you are reading in. This is definitely a problem. And, as a matter of good form, you should avoid having these "magic numbers" floating around in your code -- makes it hard to debug and hard to modify later on should that become necessary. Instead, define a constant and use that constant in the body of the program to define array sizes, limits for "while" statements, etc. As an example, I defined a constant MAXSTRING in the code posted below.

Second, while debugging, you should learn to use extra print statements to help figure out where the program is going wrong.
Below is a modified version of your code which STILL doesn't work correctly, but if you study its screen output you should be able to figure out what's going wrong.

Maybe you have been testing with a file that makes it appear that the program works. Just in case, I'm also attaching the file I have been using to test your program. Use it, and search for the word "release" & you will see that your code reports occurrences EVEN ON BLANK LINES.

Anyway, check the output of this version. There is still one error remaining that can cause the output to be completely inaccurate(as it does with my input file). Using the step by step output you should be able to find it.

Code:
#include <iostream.h>
#include <fstream.h>
#include <cstring>
#include <stdio.h>	//for getchar() (to pause while debugging)
#define MAXSTRING 50  // constant to define maximum input string length throughout the program

typedef char characterString[MAXSTRING+1];  //allowing space for null byte

int compairText(characterString input, int x, characterString target, int y, int numberOfCharacters);
void convertText(characterString input);

int main()
{
	characterString input;			//input string
	characterString target;			//target string

	int numberOfCharacters = -1;	//number of characters in the target string
	int lineNumber = 1;				//number of lines
	int numberOfMatches = 0;		//keeps the number of matches found
	
	ifstream infile;				//input file
	ofstream outfile;				//output file

	infile.open("hw02.dat");
	outfile.open("Output.dat");

	cout << "Enter the word to search for: " << endl;
	cin >> target;

	convertText(target);

	numberOfCharacters = strlen(target);

	cout << "Line Number \t Number of Matches" << endl;

	while(infile.peek() != EOF)
	{
		cout << "entering while loop; numberOfMatches = " << numberOfMatches << endl;
		infile.getline(input, MAXSTRING+1, '\n');
		cout << input << endl;						//debug
		convertText(input);
		cout << input << endl;						//debug

		// in the next line I reduced the upper limit of the search - no point checking the
		// last few letters if there are fewer than numberOfCharacters remaining in the string
		for(int k = 0; k < MAXSTRING-numberOfCharacters+1; k++)	//traverses the input string
		{
			cout << "now testing input[" << k << "]: contents = " << input[k] << endl; // debug
			if(target[0] == input[k])
			{	cout << "entered first \"if\", numberOfMatches =" << numberOfMatches << endl;//debug
				if(compairText(input, k, target, 0, numberOfCharacters))
				{
					cout << "after successful compairText, numberOfMatches ="
							<< numberOfMatches << endl;		//debug
					numberOfMatches++;
					cout << "incremented numberOfMatches to " << numberOfMatches << endl;//debug
					k =  k + numberOfCharacters - 1;
				}
			}
		}
		cout << "finished traversing the string" << endl;
		cout << lineNumber <<  "\t\t\t" << numberOfMatches << endl;
		outfile << lineNumber <<  "\t\t\t" << numberOfMatches << endl;

		lineNumber++;
		numberOfMatches = 0;
		cout << "numberOfMatches reset to " << numberOfMatches << endl;		//debug
		cout << "press <enter> to continue" << endl;				//debug
		getchar();							//debug
	}

	infile.close();
	outfile.close();

	return 0;
}

// ****************************************************

int compairText(characterString input, int x, characterString target, int y, int z)
{
	if(z == 0)
		return 1;

	else
	{
		if(input[x] != target[y])
			return 0;

		else if(input[x] == target[y])
			if(compairText(input, (x+1), target, (y+1), (z-1)))
				return 1;
	}

return 0;

}

// ****************************************************

void convertText(characterString x)
{
	for(int i = 0; i < MAXSTRING; i++)
		if(x[i] >= 65 && x[i] <= 90)
			x[i] += 32;
}
Here is the test input file I used (lines truncated to 50 chars):
1-2-3 Release 5 for Windows Product Updates (READM
**CONTENTS**
Updating Release 4 Worksheet Files to Release 5

Install
Information for Upgraders
Installing on Computers with Multiple Configuratio
Server and Distribution Install
3. Windows and Available Memory
4. Charting Information for Upgraders
5. Printing Performance Information
Printer Drivers and Devices
Print Resolution
6. DataLens and ODBC Drivers
ODBC Drivers
Environment Variables
7. Version Manager
8. Solver
9. Command-Line Parameters
10. Corrections to the Documentation
Macros Help
Help for 1-2-3 Messages
The Guided Tour
11. Font Usage
Font Mapping
Font Performance Tips
Removing ATM
12. Map Performance Information
Finding the Correct Map Type
Map Resolution
Map Macros
Maps and Lotus Approach
13. Compatibility
Working with .WK1 Files
Working with Excel Files
Working with dBASE Files
14. Using 1-2-3 with OS/2


**1. UPDATING RELEASE 4 WORKSHEET FILES TO RELEASE

Last edited by R.Stiltskin; 04-13-2003 at 04:08 PM.
R.Stiltskin is offline  
Old 04-13-2003, 04:44 PM   #10
Registered User
 
Join Date: Feb 2003
Posts: 490
By the way, I don't know why, but when I compile this code in Unix using the CC compiler, it compiles OK but when it runs it only processes the first line of input and then exits the program.

But when I compile it with the g++ compiler, it behaves the same as it does with MSVC++ 6.0 -- output is still wrong because of the remaining logic error, but it does process the entire file.

Anybody know the reason for this discrepancy? Another getline problem maybe?
R.Stiltskin is offline  
Old 04-13-2003, 09:49 PM   #11
Registered User
 
Join Date: Apr 2003
Posts: 33
C++ logic error

ok this is the same program as before. It searches a file for a word and find the number of occurences in each line. I got rid of the recursion. No i am having problems with the Function that finds the numbner of occurences. When the file finds 2 occurences it outputs 2 however in the next line when there are no occurences it outputs 1. here is the code:

Code:
#include <iostream.h>
#include <fstream.h>
#include <cstring>


const int MAXSTRING = 45;  // constant to define maximum input string length throughout the program
typedef char characterString[MAXSTRING];  //allowing space for null byte

int compairText(characterString target, characterString input, int lineNumber, int numberOfCharacters);
void convertText(characterString input);

int main()
{
	characterString input;			//input string
	characterString target;			//target string

	int numberOfCharacters = 0;			//number of characters in the target string
	int lineNumber = 1;				//number of lines
	int numberOfMatches = 0;		//keeps the number of matches found
	
	ifstream infile;				//input file
	ofstream outfile;				//output file

	infile.open("hw02.dat");
	outfile.open("Output.dat");

	cout << "Enter the word to search for: " << endl;
	cin >> target;

	convertText(target);

	numberOfCharacters = strlen(target);
	cout << numberOfCharacters << endl;

	cout << "Line Number \t Number of Matches" << endl;

	while(infile.peek() != EOF)
	{
		infile.getline(input, MAXSTRING, '\n');
		convertText(input);

		numberOfMatches = compairText(target, input, numberOfMatches, numberOfCharacters);
	
		cout << lineNumber <<  "\t\t\t" << numberOfMatches << endl;
		outfile << lineNumber <<  "\t\t\t" << numberOfMatches << endl;

		lineNumber++;
		numberOfMatches = 0;
	}

	infile.close();
	outfile.close();

	return 0;
}


//****************************************************

void convertText(characterString x)
{
	for(int i = 0; i < MAXSTRING; i++)
		if(x[i] >= 65 && x[i] <= 90)
			x[i] += 32;
}

//****************************************************

int compairText(characterString target, characterString input, int numberOfMatches, int numberOfCharacters)
{
	int targetPosition = 0;

	for(int inputPosition = 0; inputPosition < MAXSTRING; inputPosition++)
	{	
		if(input[inputPosition] == target[targetPosition])
		{
			targetPosition++;
			
			if(targetPosition == numberOfCharacters)
			{	
				targetPosition = 0;
				numberOfMatches++;
			}
		}
		
		else
		{
			targetPosition = 0;
			
			if(input[inputPosition] == target[targetPosition])
				targetPosition++;
		}
	}
 
	return numberOfMatches;
}
Thanks for trhe help guys.

-Bill
Maverik is offline  
Old 04-13-2003, 09:49 PM   #12
Registered User
 
Join Date: Apr 2003
Posts: 33
ohh and here is the file i used to search, the word i was looking for is "release".

reaadfna
release
adgadgrereleaseadgadg
adfad
adgadg
release adfad release
afdadf
adfadf
adfadf
release
Maverik is offline  
Old 04-13-2003, 10:06 PM   #13
Registered User
 
Join Date: Apr 2003
Posts: 33
ok i think i got it but i still don't understand why it wouldn't work.
What I changed is in bold

here is the compair text function:
Code:
int compairText(characterString target, characterString input, int numberOfMatches, int numberOfCharacters)
{
	int targetPosition = 0;
	int length = strlen(input);

	for(int inputPosition = 0; inputPosition < length; inputPosition++)
	{	
		if(input[inputPosition] == target[targetPosition])
		{
			targetPosition++;
			
			if(targetPosition == numberOfCharacters)
			{	
				targetPosition = 0;
				numberOfMatches++;
			}
		}
		
		else
		{
			targetPosition = 0;
			
			if(input[inputPosition] == target[targetPosition])
				targetPosition++;
		}
	}
 
	return numberOfMatches;
}
If someone can tell me why this makes that much of a difference i would greatly appreciate it.

-Bill
Maverik is offline  
Old 04-14-2003, 07:01 AM   #14
Registered User
 
Join Date: Feb 2003
Posts: 490
Here's the correction I made:

following is the error: traversing the MAXIMUM LENGTH OF THE CHAR ARRAY
beyond the end of the latest string
Code:
for(int k = 0; k < MAXSTRING-numberOfCharacters+1; k++)   //traverses the input string plus
                                      // everything left over from the PREVIOUS input string
here's the corrected version; it traverses only the current input string
actually I reduced the upper limit of the search still further - no point checking the
last few letters if there are fewer than numberOfCharacters remaining in the string

Code:
for(int k = 0; k < (int)strlen(input)-numberOfCharacters+1; k++)   //traverses only the new input string
but I still don't know why the CC compiler doesn't handle it correctly.
R.Stiltskin is offline  
Old 04-14-2003, 07:07 AM   #15
Registered User
 
Join Date: Feb 2003
Posts: 490
It's really annoying when people start multiple threads about a single issue.
Answers are at your thread on the linux board:

Unix/C++ problem
R.Stiltskin is offline  
Closed Thread

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Need help understanding a problem dnguyen1022 C++ Programming 2 04-29-2009 04:21 PM
Memory problem with Borland C 3.1 AZ1699 C Programming 16 11-16-2007 11:22 AM
Someone having same problem with Code Block? ofayto C++ Programming 1 07-12-2007 08:38 AM
A question related to strcmp meili100 C++ Programming 6 07-07-2007 02:51 PM
WS_POPUP, continuation of old problem blurrymadness Windows Programming 1 04-20-2007 06:54 PM


All times are GMT -6. The time now is 06:16 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22