Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

JohnMC

macrumors 6502
Original poster
May 5, 2006
386
1
Duluth, MN
Hi all,

I am trying to sort out a problem with my code. This is a school homework assignment so if you don't want to give me the answer in understand. My program works fine until it gets to the scanf under the decrypt data section. At the console for scanf, you can enter integer after integer and nothing happens.
What am I doing wrong? Code below.

Code:
#include <iostream>
#include <fstream>
#include "stdio.h"
#include "string.h"

#define STRING_LENGTH 120
#define MAX_SIZE 4096

using namespace::std;


extern void encript(char *UnEncriptArray, char EncriptArray[], int Key, int stringLength); 
extern void decript(char *EncriptArray, char UnEncriptArray[], int Key, int stringLength);


int main (int argc, char * const argv[]) {
	char inFileName[STRING_LENGTH];
	char outFileName[STRING_LENGTH];
	char arrayIn[MAX_SIZE];
	char arrayOut[MAX_SIZE];
		
	int Key;
	
	
	cout << "Welcome to <Encrypt/Decrypt>!!! \n" << endl;
	
	// DECODE FUNCTION
    
    cout << "You are in Decrypt Mode. \n" << endl;
	
	//asks user for file names
	cout << "Please enter the name of the file to get text from:" << endl;
	cin >> inFileName;
	cout << "Please enter the name of the file to save text to:" << endl;
	cin >> outFileName;
	
	//creates file streams from file names given above
	ifstream dataIn(inFileName, ios::in);
	ofstream dataOut(outFileName, ios::out);
	
		//FOR TESTING ONLY
	//prints status of file streams
	cout << "In File: " << inFileName << dataIn.is_open() << endl;
	cout << "Out File: " << outFileName << dataOut.is_open() << endl;
	
	//loads data from input location into data array
	int positionIn = 0; 
	char positionChar;
	while (!dataIn.eof()) {
		dataIn >> positionChar;
		positionChar = toupper(positionChar);
		arrayIn[positionIn] = positionChar;
		positionIn++;
	}
	arrayIn[strlen(arrayIn)-1] = 0; //removes the "extra" char
	
	//decrypt data
	cout << "Please enter the key value <int>: ";
	scanf("%d", &Key);
	decript(arrayIn, arrayOut, Key, strlen(arrayIn));
	cout << "The key decrypted the text as: " << endl;
	cout << arrayOut << endl;
	
	//output data
	dataOut << "Output from Encrypt/Decrypt." << endl;
	dataOut << "Decryption Key Used: ";
	dataOut << Key << endl;
	dataOut << "The decrypted text is: ";
	dataOut << arrayOut << endl;
	
	cout << "Thank You for using Encrypt/Decrypt. Your data has been saved to your output file.";
	return 0;
}

Decrypt Function:
Code:
void decript(char *EncriptArray, char UnEncriptArray[], int Key, int stringLength) {
	int decodeWorking;
	int wrapValue;
	
	for (int i = 0; i < stringLength; i++) {
		decodeWorking = (int)EncriptArray[i] - Key;
		if (decodeWorking < 64) {
			wrapValue = 64 - decodeWorking;
			decodeWorking = 90 - wrapValue;
		}
		
		UnEncriptArray[i] = (char)decodeWorking;
		
	}
	
}

Any advice would be great.

JohnMC
 

chown33

Moderator
Staff member
Aug 9, 2009
10,747
8,420
A sea of green

JohnMC

macrumors 6502
Original poster
May 5, 2006
386
1
Duluth, MN
I am using Xcode 3.2.1 on Snow Leopard. Thanks for the links, I will go through them and see what I can figure out.
 

JohnMC

macrumors 6502
Original poster
May 5, 2006
386
1
Duluth, MN
Lee - If I replace the scanf with cin I still have the same problem. So either I am doing something wrong entirely or I have a problem with Xcode.

John
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
I didn't mean to insinuate that cin would help with this XCode bug (see chown33's first link, you should be able to remedy this in ~30 seconds), I was just asking because it seemed odd that you'd use scanf to read a single integer value when you could use cin.

-Lee
 

JohnMC

macrumors 6502
Original poster
May 5, 2006
386
1
Duluth, MN
I read through the threads posted above and made the changes to my Xcode project, but I still can't get past my cin/scanf problem. Here is a copy/paste from the console:

Code:
Welcome to <Encrypt/Decrypt>!!! 

You are in Decrypt Mode. 

Please enter the name of the file to get text from:
InFile.txt
Please enter the name of the file to save text to:
OutFile.txt
In File: InFile.txt1
Out File: OutFile.txt1
Please enter the key value <int>: 5
222
sfwef


$

rsgesrges


df
32356
-892

Anyone have any pointers for me?

John

Edit: Lee - I did not mean any offense with my comment. Sorry. I am just getting frustrated with Xcode right now.
 

lloyddean

macrumors 65816
May 10, 2009
1,047
19
Des Moines, WA
Have you tried running the code from the debugger to verify that the input file was opened successfully?

Would also be helpful if you posted the entire compilable project.

A common problem is the current working directory is NOT what you think it is so check this.
 

chown33

Moderator
Staff member
Aug 9, 2009
10,747
8,420
A sea of green
How large is the input file being tested?

As posted, the code will overrun its input buffer if the file is longer than the array. There's no predicting what will happen after that. That's not the only bug, though.

When I paste the two code fragments together into a single source file, it does compile and run at the command-line. I gave it an input file with the letters a-p in it, with a single newline.

The error-handling is essentially non-existent, because it crashes if the input file doesn't exist, or filenames are too long, or the input-file is too long, or the output can't be created. Nevertheless, given safe inputs, it does run to termination. I have no idea what it's doing in decript(), and there isn't an encript() to even be called, but basically it's doing something.

EDIT:
This statement seems to be unpredictably fatal:
Code:
	arrayIn[strlen(arrayIn)-1] = 0; //removes the "extra" char

First, I have no idea what "extra" char the comment is referring to.

Second, the loop that read the data did not put a null byte into the array, so there is a random chance that strlen() will return something bogus. If it does return something bogus, then storing a 0 there could do anything.

Third, positionIn holds a count of the bytes read into the array, but this is ignored. As a result, who knows what unpredictable things will happen when decript() is called, because strlen() is used again, even though there's no predictable null byte at the end of the data.
 

JohnMC

macrumors 6502
Original poster
May 5, 2006
386
1
Duluth, MN
Okay -- I think I fixed the null byte issue by using the positionIn count to add a null byte after the loop. After making the changes I put in some known strings and it got the sizes right with strlen(). I know my program has no error correction, I want to get the basics of my program running first.

However, if either of the scanf or cin is being used to get the Key value, the program never moves past that spot. If I comment out those two lines and simply set the Key to a value, the code runs fine and outputs to file.

I attached my entire code file and the input file and resulting output file (provided that the Key is set, no cin or scanf). The Key value for the input file is 17. It will return a paragraph about the US constitution.

Program Code:
Code:
#include <iostream>
#include <fstream>
#include "stdio.h"
#include "string.h"

#define STRING_LENGTH 120
#define MAX_SIZE 4096

using namespace::std;


void encript(char *UnEncriptArray, char EncriptArray[], int Key, int stringLength); 
void decript(char *EncriptArray, char UnEncriptArray[], int Key, int stringLength);


int main (int argc, char * const argv[]) {
	char inFileName[STRING_LENGTH];
	char outFileName[STRING_LENGTH];
	char arrayIn[MAX_SIZE];
	char arrayOut[MAX_SIZE];
		
	int Key = 17;
	
	
	cout << "Welcome to <Encrypt/Decrypt>!!! \n" << endl;
	
	// DECODE FUNCTION
    
    cout << "You are in Decrypt Mode. \n" << endl;
	
	//asks user for file names
	cout << "Please enter the name of the file to get text from:" << endl;
	cin >> inFileName;
	cout << "Please enter the name of the file to save text to:" << endl;
	cin >> outFileName;
	
	//creates file streams from file names given above
	ifstream dataIn(inFileName, ios::in);
	ofstream dataOut(outFileName, ios::out);
	
		//FOR TESTING ONLY
	//prints status of file streams
	cout << "In File: " << inFileName << dataIn.is_open() << endl;
	cout << "Out File: " << outFileName << dataOut.is_open() << endl;
	
	//loads data from input location into data array
	int positionIn = 0; 
	char positionChar;
	while (!dataIn.eof()) {
		dataIn >> positionChar;
		positionChar = toupper(positionChar);
		arrayIn[positionIn] = positionChar;
		positionIn++;
	}
	arrayIn[positionIn - 1] = 0;
	
	//decrypt data
	cout << "Please enter the key value <int>: " << endl;
		//scanf("%d", &Key);
		//cin >> Key;
	decript(arrayIn, arrayOut, Key, strlen(arrayIn));
	cout << "The key decrypted the text as: " << endl;
	cout << arrayOut << endl;
	
	//output data
	dataOut << "Output from Encrypt/Decrypt." << endl;
	dataOut << "Decryption Key Used: ";
	dataOut << Key << endl;
	dataOut << "The decrypted text is: ";
	dataOut << arrayOut << endl;
	
	
	//close file i/o and exit program
	cout << "Thank You for using Encrypt/Decrypt. Your data has been saved to your output file.";
	
	dataIn.close();
	dataOut.close();
	
	return 0;

}



void encript(char *UnEncriptArray, char EncriptArray[], int Key, int stringLength) {
	int encodeWorking;
	int wrapValue;
	
	for (int i = 0; i < stringLength; i++) {
		encodeWorking = (int)UnEncriptArray[i] + Key;
		if (encodeWorking > 90) {
			wrapValue = encodeWorking - 90;
			encodeWorking = 64 + wrapValue;
		}
		
		EncriptArray[i] = (char)encodeWorking;
		
	}
	
}

void decript(char *EncriptArray, char UnEncriptArray[], int Key, int stringLength) {
	int decodeWorking;
	int wrapValue;
	
	for (int i = 0; i < stringLength; i++) {
		decodeWorking = (int)EncriptArray[i] - Key;
		if (decodeWorking < 64) {
			wrapValue = 64 - decodeWorking;
			decodeWorking = 90 - wrapValue;
		}
		
		UnEncriptArray[i] = (char)decodeWorking;
		
	}
	
}


/* NOT USED IN PROGRAM
int done(int userInput) {
	if ((userInput == 89) || (userInput == 121)) {
		return 1;
	}
	else {
		return 0;
	}
	
}
*/

Also files are attached. I am still completely lost on the cin/scanf problem under //decrypt data.

John
 

Attachments

  • InFile.txt
    283 bytes · Views: 67
  • OutFile.txt
    355 bytes · Views: 65
  • main copy.txt
    2.9 KB · Views: 75

lloyddean

macrumors 65816
May 10, 2009
1,047
19
Des Moines, WA
With working directory adjustment outputs:


Output from Encrypt/Decrypt.
Decryption Key Used: 17
The decrypted text is: WETHEPEOPLEOFTHEUNITEDSTATES@INORDERTOFORMAMOREPERFECTUNION@ESTABLISHJUSTICE@INSUREDOMESTICTRANQUILITY@PROVIDEFORTHECOMMONDEFENCE@PROMOTETHEGENERALWELFARE@ANDSECURETHEBLESSINGSOFLIBERTYTOOURSELVESANDOURPOSTERITY@DOORDAINANDESTABLISHTHISCONSTITUTIONFORTHEUNITEDSTATESOFAMERICA@
 

JohnMC

macrumors 6502
Original poster
May 5, 2006
386
1
Duluth, MN
I was able to get my program working on Xcode. Thanks everyone for your help. Now I just have to port it to Visual Studio.

John
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.