Caesar Cipher program finished, but need help with bugs.

Pages: 12
Reads in text file. Ex- >2D or >23D or <-2D or >2D+4G. The > and < move the shift value up depending on the follow letter. The +/- add or subtract the following number to the shift value. The goal is to from
<25CNM'S OZX ZMX ZSSDMSHNM SN SGD LZM ADGHMC SGD BTQSZHM.#

To

DON'T PAY ANY ATTENTION TO THE MAN BEHIND THE CURTAIN.

Current Goal: See last post.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <iostream>
#include <cctype>
#include <string>
#include <fstream>
using namespace std;



void openFile(ifstream& ins);
void toupperByReference(char& c);

int main ()
{
	int shiftvalue = 0;
	char c; 
	ifstream ins; 
	openFile(ins); //Opens file and prints out error if file doesn't exist.
	cout << endl;
	while (ins>>c) //Will continue to run code until end of file.
	{
		toupperByReference(c);
		if(isspace(c))
		{
			cout << c;
		}
		if(ispunct(c)) //Checks if character is punct.
		{
			if(c == '.' || c == ','|| c == ':' || c == '!' || c == '\'') //If c is something normal, it just prints it out. 
			{
				cout << c;
			}
			if(c == '>' || c == '<') //If this triggers it will change the shift value
			{
				if (c == '>')
				{
					shiftvalue = 0;
					int shiftvaluetens;
					ins>>shiftvaluetens;
					if(!ins.good())
					{
						cout << endl;
						cout << "*** ERROR: No shift value as expected ***" << endl
							 << "Special character: \" > \" requires a numeric following it.";
						ins.clear();
						while((c = ins.get()) != '#')
						{
							/* MT */
						}

					}
					shiftvalue += shiftvaluetens; 
				}
				if (c == '<')
				{
					shiftvalue = 0;
					int shiftvaluetens;
					ins>>shiftvaluetens;
						if(!ins.good())
						{
							cout << endl;
							cout << "*** ERROR: No shift value as expected ***" << endl
								 << "Special character: \" < \" requires a numeric following it.";
						    ins.clear();
						while((c = ins.get()) != '#') 
						{
							/* MT */
						}

					}
					shiftvalue -= shiftvaluetens; 
				}
			}
			if (c == '#') //If this triggers will clear shift and get ready for next chunk.
			{
				cout << endl;
				shiftvalue = 0;
			}
			if(c == '+' || c == '-') //If this triggers will add or subtract appropriate amount to shiftvalue
			{
				int shiftvalueplusminus;
				ins >> shiftvalueplusminus;
				if (c=='+')
				{
					if(!ins.good())
					{
						cout << endl;
						cout << "*** ERROR: No shift value as expected ***" << endl
							 << "Special character: \" + \" requires a numeric following it.";
						ins.clear();
						while((c = ins.get()) != '#')
						{
							/* MT */
						}

					}
					shiftvalue += shiftvalueplusminus;
				}
				if (c=='-')
				{
					if(!ins.good())
					{
						cout << endl;
						cout << "*** ERROR: No shift value as expected ***" << endl
							 << "Special character: \" - \" requires a numeric following it.";
						ins.clear();
						while((c = ins.get()) != '#')
						{
							/* MT */
						}

					}
					shiftvalue -= shiftvalueplusminus;
				}

			}
		}
		if (isdigit(c))
		{
			cout << c;
		}

		if (isalpha(c)) //Checks if character is an alpha. 
		{
			c += shiftvalue;
			if (c<'A')
			{
				c += 26;
				cout << c;
			}
			else if (c>'Z')
			{
				c -= 26;
				cout << c;
			}
			else cout << c;
		}
	}
	
	return 0;

}


void toupperByReference(char& c)
{
	c = toupper(c);
}

void openFile(ifstream& ins)
{
string fileName;
cout << "Enter filename: ";
cin >> fileName;
ins.open(fileName.c_str());
while (!ins) 
	{
	ins.clear();
	cout << "*** ERROR: Error in opening file ***" 
		<< endl << "You entered an invalid file name. Please try again." << endl <<endl;
	cout << "Enter filename : ";
	cin >> fileName;
	ins.open(fileName.c_str());
	}
ins.unsetf(ios_base::skipws);
}
Last edited on
Why do you have a different function just to open a file? There's a good question. Why are you not just doing everything in the program in the main function?
It was give to me in the project specs already. From our last project.
I actually got it to "work now"

It just does nothing though.

Enter file name:
test1.txt, is what i type

Just blinks the cursor after that. test1.txt had >2C So an A should have printed. Ugh
what does the error say?
No error. It just blinks after I enter it. I have a breakpoint at return 0. I am currently updating some of the loops, give me a few minutes to enter the new code above.
Your code works. You just don't know it. You have no way of knowing where you are in your code. When you go to enter something. You just don't know what you're entering. When you enter a value, have a message saying something like.

cout << "Enter a punctuation mark: "
I am a bit confused as to what you mean. The test1.txt contains ">2C" and it should cout "E" to the screen.

I get what you mean until you say "You just don't know what you're...". I should only have to enter the text files name and the code should just run from there. Where did you envision me having the cout << "enter a "

@Yezman

Your program has one small problem. The reason the cursor is blinking, is because it's waiting for an input.
1
2
3
4
while (!ins.eof()) //Will continue to run code until end of file.
	{
		cin >> c;
		if(ispunct(c)) //Checks if character is punct. 


It should be..
1
2
3
4
while (!ins.eof()) //Will continue to run code until end of file.
	{
		ins >> c; // c takes the input from the opened file
		if(ispunct(c)) //Checks if character is punct. 

After I made this change, the text file was printed out, but with no changes to the input. I did get a diiferent output when I changed ch + shiftvalue; to this.. ch += shiftvalue;
@Whitenite1. Thanks.

The cin >> c is what I get for programming at 4am I guess.

I did also change the + to a +=, and it did change the output. I am a little confused as to why though. If c = 'A' and shiftvalue = 2 //for example shouldn't it just print C, or am I overlooking something?

Also, now with those changes it works for > or < followed by a single number. However, it always double outputs the last digit. I had a question like this with a 1 2 3 4 in a text file and know that that I got it wrong. It was 14, I put 10. It has something to do with reading the end of the file twice. Can anyone lead me in the right direction to fix that?
I did also change the + to a +=, and it did change the output. I am a little confused as to why though. If c = 'A' and shiftvalue = 2 //for example shouldn't it just print C, or am I overlooking something?


I think what you're missing, is the fact that ch doesn't get changed, up or down in value, with just a + or - number. It would have to be ch = ch (+ or -) a variable.

I am not understanding the beginning of your text input file. <25CNM'S... . It seems you want the value of the letters reduced by 25, but the characters need a plus one, to get it to print out the target sentence. I changed the text read file to >1CNM'S... and the sentence printed properly, without spaces though. Had to add to the ispunct(c) check section with
1
2
if(c=='_')
  cout << " ";
to properly cout the spaces. Changed the spaces in the input text to the '_' character.
The ch = ch +/- makes sense.

My program is going to be tested against text files that do have <25, but I have a few lines of code that can fix the letters if they go out of range on the ascii table.

My current issue is that the program is outputing the last character of the text file twice. Ex- if it should output BCD, it will output BCDD.

About the spaces. I currently have >2C C in my text file. I hadn't even thought about the spaces yet. But, the text files I am tested against will be exactly like the OP. So I am going to try get it so that my program will cout << E EE when >2C C is entered now.
For the spaces, I added
1
2
3
4
if(isspace(c))
{
	cout << " ";
}


Now when I have >2C C in my text file, I feel like this code should make it at least cout E EE. But it still only cout's EEE..... Ugh
Last edited on
@Yezman

Try using this,
1
2
3
while (ins >> c) //Will continue to run code until end of file.
	{
		if(ispace(c))


in place of this.
1
2
3
4
while (!ins.eof()) //Will continue to run code until end of file.
	{
		ins >> c;
		if(isspace(c))


I think you'll like the results a lot more..
Your thinking is correct, I do like the results much more.

For future reference. Why does this work (only print it once) as compared to !ins.eof()? I just re read through http://www.cplusplus.com/doc/tutorial/files/ and didn't see anything about this topic, so is there a short explanation you or anyone else can give me?
With (!ins.eof), the program tries to read the next character, fails, then prints out with the cout, the character still being held, so you'll get a double output of the last character or word, read. The while(ins >> c) closes the file as soon as it comes to the end, and nothing will be printed, because the while, ended..
Ah wasn't aware of that, thanks. Note to self, use ins>> not !ins.eof() in the future.

Now my issue is getting spaces. Ex- >2C C. I am trying to use the isspace() function (http://www.cplusplus.com/reference/clibrary/cctype/isspace/)

In the example in that link, they use an array. c=int(str[i]) then isspace(c). Does that imply that this should really only be used with arrays, so I should try a different approach? What I have in the OP still isn't working. I also have tried if(c== ' ').

------------
Fixed it. Put
ins.unsetf(ios_base::skipws);
in my openFile

Now give me like 15 minutes to break it again, attempt to fix it and fail.
Last edited on
I couldn't spaces to work, either, so I replaced the spaces in the saved text, with _'s. Then, in the program, I used,
1
2
if(c == '_')
		cout << " ";


Also, I added
1
2
3
4
5
6
7
8
if (c == '#')// Used as NEWLINE
{
	cout << endl;
}
if (c == '~') // Used as TAB
{
	cout << "\t";
}
Worked great.
@whitenite1

I got the spaces to work. I haven't tackled the # yet, but I had the same idea. For the '~' is that something I should learn to recognize meaning tab?


----------------
Score! I got it to solve the example in the OP. Now I need to make it solve

>7IETR BM LTF. HY TEE MAX ZBG CHBGML BG TEE MAX IETVXL BG TEE
MAX PHKEW, LAX ATW MH PTED >14UZFA YUZQ. IQ'XX MXIMKE TMHQ BMDUE.
>23URXQG XS WKH XVXDO VXVSHFWV.

to

PLAY IT SAM. OF ALL THE GIN JOINTS IN ALL THE PLACES IN ALL
THE WORLD, SHE HAD TO WALK INTO MINE. WE'LL ALWAYS HAVE PARIS.
ROUND UP THE USUAL SUSPECTS.

Right now my output is Enter filename: test1.txt
PLAY IT SAM. OF ALL THE GIN JOINTS IN ALL THE PLACES IN ALL THE WORLD, SHE HAD T
O WALK PUAV TPUL. DL'SS HSDHFZ OHCL WHYPZ. ¢d₧cY ₧e ¥]Z ₧£₧Va £₧£eZX¥£.

So now I am going to figure out why it goes crazy. My guess is that I something is wrong with my

1
2
3
4
5
6
7
8
9
10
11
12
	
if (ch<'A')
{
        ch += 26;
	cout << ch;
}
else if (ch>'Z')
{
	ch -= 26;
	cout << ch;
}
else cout << ch;


I think I just got lucky with my first example. Now the shift values are really big so +- 26 isn't going to work. I have a feeling I have to use my arch-nemesis the %. (This has screwed me over so many times ==)
Last edited on
@Yezman

Concerning the '~'. I just used a character that probably would not be in a normal sentence, and had the program recognize it as a tab. A normal tab in a cout statement is '\t'.

The program does not look for digits higher than 9. You'll have to do some checking for the next character after a digit, to see if it's another digit. Then take digit one, multiply by 10, then add the value of digit 2. So when it reads >23, the 2 would be multiplied by 10, making twenty, then the 3 is added, making 23. Otherwise, shiftvalue is only being increased or decreased by the value of the first digit, giving false results in your output
Pages: 12