Thread: Unix/C++ problem

  1. #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.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981

    Re: Unix/C++ problem

    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

  3. #3
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    - 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

  4. #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

  5. #5
    Registered User
    Join Date
    Apr 2003
    Posts
    33
    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.

  6. #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

  7. #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;
    }

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    You are still using telling getline() that you have 50 chars, when you only have 45......bad.

    gg

  9. #9
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    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.

  10. #10
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    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?

  11. #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

  12. #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

  13. #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

  14. #14
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    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.

  15. #15
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    It's really annoying when people start multiple threads about a single issue.
    Answers are at your thread on the linux board:

    http://cboard.cprogramming.com/showt...threadid=37785

Popular pages Recent additions subscribe to a feed

Similar Threads

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