Yesterday I started developing a encrypting machine, that works like a Caesar cipher. You put a message (e.g., HELLO), choose a key value (e.g., 3) and the result is KHOOR (3 letters forward).
The problem is that, if I use "cin >> msg;" I can only codify one word. If I use "getline (cin, msg);", the code doesn't work. Maybe it's a simple problem, but I can't solve it... :(
string msg;
int a, b, i, key_value;
char c;
cout << "WRITE YOUR MESSAGE:" << endl;
cin >> msg; //HERE IS THE PROBLEM!!!
system ("cls");
cout << "PUT A KEY VALUE:" << endl;
cin >> key_value;
system ("cls");
cout << "THE CODIFIED MESSAGE IS:" << endl;
for (i=0; i < msg.length(); i++) {
if (msg[i] == 'A') a = 1;
if (msg[i] == 'B') a = 2;
if (msg[i] == 'C') a = 3;
if (msg[i] == 'D') a = 4;
if (msg[i] == 'E') a = 5;
if (msg[i] == 'F') a = 6;
if (msg[i] == 'G') a = 7;
if (msg[i] == 'H') a = 8;
if (msg[i] == 'I') a = 9;
if (msg[i] == 'J') a = 10;
if (msg[i] == 'K') a = 11;
if (msg[i] == 'L') a = 12;
if (msg[i] == 'M') a = 13;
if (msg[i] == 'N') a = 14;
if (msg[i] == 'O') a = 15;
if (msg[i] == 'P') a = 16;
if (msg[i] == 'Q') a = 17;
if (msg[i] == 'R') a = 18;
if (msg[i] == 'S') a = 19;
if (msg[i] == 'T') a = 20;
if (msg[i] == 'U') a = 21;
if (msg[i] == 'V') a = 22;
if (msg[i] == 'W') a = 23;
if (msg[i] == 'X') a = 24;
if (msg[i] == 'Y') a = 25;
if (msg[i] == 'Z') a = 26;
b = a + key_value;
if (b > 26) b -= 26;
if (b == 1) c = 'A';
if (b == 2) c = 'B';
if (b == 3) c = 'C';
if (b == 4) c = 'D';
if (b == 5) c = 'E';
if (b == 6) c = 'F';
if (b == 7) c = 'G';
if (b == 8) c = 'H';
if (b == 9) c = 'I';
if (b == 10) c = 'J';
if (b == 11) c = 'K';
if (b == 12) c = 'L';
if (b == 13) c = 'M';
if (b == 14) c = 'N';
if (b == 15) c = 'O';
if (b == 16) c = 'P';
if (b == 17) c = 'Q';
if (b == 18) c = 'R';
if (b == 19) c = 'S';
if (b == 20) c = 'T';
if (b == 21) c = 'U';
if (b == 22) c = 'V';
if (b == 23) c = 'W';
if (b == 24) c = 'X';
if (b == 25) c = 'Y';
if (b == 26) c = 'Z';
cout << c;
}
So your code works fine: http://ideone.com/lBhD78
If you're trying to accept more than 1 word the simple extraction operator will not work however. Which is probably what you're asking about. In this case you will want to use getline. Like this for instance:
getline(cin, msg, '\n');
So I'm not certain what you're complaining about, however this could be much improved by:
Being case-insensitive
Only modifying alpha-characters
You could accomplish this by doing something like:
transform(cbegin(msg), cend(msg), ostream_iterator<char>(cout), [&](unsigned char i){
if(isalpha(i)) {
const auto a = islower(i) ? 'a' : 'A';
i = (i - a + key_value) % 26 + a;
}
return i; });
I've written a Live Example complete with getline.
You have to be carefull to write questions.
BUT, without being clear what you mean, the answer is:
When you read cin>>s, by default, you are considering the data are separated by "white spaces". So, it skips spaces and read the string until a new space or end of input.
If you have problems with getline, probably the problem is before the code you are shown. If you read a value with, for example, cin>>integer, you push newline key at the end of the input, but this character is still in the stream. If the following line in your code es getline, probably you will read an empty line.
In the first item you find why you current code works, in the second one, why your getline-version doesn't.
Related
#include <iostream>
using namespace std;
int main()
{
int tablica[9];
string inputromanum;
cout << "ROMAN: ";
cin >> inputromanum;
int maxindeks;
bool disablenextcomp = false;
int readysolution = 0;
maxindeks = inputromanum.length() - 1;{}{}
for (int i = 0; i <= maxindeks; i++)
{
if (inputromanum[i] == 'M' || inputromanum[i] == 'm')
{
tablica[i] = 1000;
}
if (inputromanum[i] == 'D' || inputromanum[i] == 'd')
{
tablica[i] = 500;
}
if (inputromanum[i] == 'C'|| inputromanum[i] == 'c')
{
tablica[i] = 100;
}
if (inputromanum[i] == 'L' || inputromanum[i] == 'l')
{
tablica[i] = 50;
}
if (inputromanum[i] == 'X' || inputromanum[i] == 'x')
{
tablica[i] = 10;
}
if (inputromanum[i] == 'V' || inputromanum[i] == 'v')
{
tablica[i] = 5;
}
if (inputromanum[i] == 'I' || inputromanum[i] == 'i')
{
tablica[i] = 1;
}
}
cout<<endl;
for(int i4 = 0; i4 <= maxindeks; i4++)
{
cout<<"tablica["<<i4<<"] = "<<tablica[i4]<<endl;
}
for (int i2 = 0; i2 <= maxindeks; i2++)
{
int i5 = i2 + 1;
if (i5 <= maxindeks)
{
//cout<<endl<<"tablica[i2 + 1] = "<<tablica[i2 + 1];
//cout<<endl<<"tablica[i2] = "<<tablica[i2];
//cout<<endl<<"tablica[i2 + 1] - tablica[i2] = "<<tablica[i2 + 1] - tablica[i2];
if (tablica[i2 + 1] - tablica[i2] > 0 && disablenextcomp == false)
{
//cout<<endl<<"readysolution + (tablica[i2 + 1] - tablica[i2]) = "<<readysolution + (tablica[i2 + 1] - tablica[i2])<<endl;
readysolution = readysolution + (tablica[i2 + 1] - tablica[i2]);
disablenextcomp = true;
}
else
{
if(disablenextcomp == false)
{
//cout<<endl<<"readysolution + tablica[i2] = "<<readysolution + tablica[i2]<<endl;
readysolution = readysolution + tablica[i2];
}
else
{
disablenextcomp = false;
}
}
}
else
{
if(disablenextcomp == false)
{
//cout<<endl<<endl<<"OSTATNI INDEKS";
//cout<<endl<<"tablica[i2] = "<<tablica[i2];
//cout<<endl<<"readysolution + tablica[i2] = "<<readysolution + tablica[i2];
readysolution = readysolution + tablica[i2];
}
}
i5++;
}
cout << endl << readysolution;
}
This is my program. made for decoding roman numerals into arabic ones. It works as intended in most cases, however, one of my colleagues found it to produce this error while inputting MMMCMXCVIII into the program:
*** stack smashing detected ***: terminated
It would refuse to work afterwards.
I wasn't able to find different numbers that would cause this error except MMMMMMMMMMM.
It seems to fail when the index of tablica array exceeds 10. I don't know why it does so, as i am a novice in c++. It should've outputted 3999 instead of the error appearing. The numbers it should process successfully should range from 1 to 5000.
Thanks to folks in the comments, I've found the cause.
The tablica[9] array is supposed to store 9 or less characters.
The length of the input (MMMCMXCVIII in this case) has more characters, therefore it makes the for loop responsible for storing values for each character to cause mentioned above error, as there are no remaining units to store the values in.
I've expanded the storage of tablica to 25 characters.
In modern C++ it is considered bad practice to use C-style arrays and index loops whenever you can avoid this. So, fo example you can rewrite first loop like this:
std::vector<int> tablica;
tablica.reserve(inputromanum.size()); // This line is not necessary, but it can help optimize memory allocations
for (char c : inputromanum)
{
if (c == 'M' || c == 'm')
{
tablica.push_back(1000);
}
if (c == 'D' || c == 'd')
{
tablica.push_back(500);
}
if (c == 'C'|| c == 'c')
{
tablica.push_back(100);
}
if (c == 'L' || c == 'l')
{
tablica.push_back(50);
}
if (c == 'X' || c == 'x')
{
tablica.push_back(10);
}
if (c == 'V' || c == 'v')
{
tablica.push_back(5);
}
if (c == 'I' || c == 'i')
{
tablica.push_back(1);
}
}
And you will avoid your issue completly. Something similar can be done with other loops too. This approach also has benefit of (somewhat) properly handling situations when input line has other symbols, which is not roman number. Try it on your version and you will see what I mean.
One more point. When you need to do something different depending of value of one variable, like you did with all those ifs. There is special statement in C/C++ for this: switch. So instead of those ifs you can do this:
std::vector<int> tablica;
tablica.reserve(inputromanum.size()); // This line is not necessary, but it can help optimize memory allocations
for (char c : inputromanum)
{
switch(c)
{
case 'M':
case 'm':
tablica.push_back(1000);
break;
case 'D':
case 'd':
tablica.push_back(500);
break;
case 'C':
case 'c':
tablica.push_back(100);
break;
case 'L':
case 'l':
tablica.push_back(50);
break;
case 'X':
case 'x':
tablica.push_back(10);
break;
case 'V':
case 'v':
tablica.push_back(5);
break;
case 'I':
case 'i':
tablica.push_back(1);
break;
}
}
Can anyone please explain me how this wrapping of chars between a-to-z and A-to-Z happening in Caesar shift code?
k %= 26;
for(int i = 0; i < n; i++){
int c = s[i];
if(c >= 'a' && c <= 'z'){
c += k;
if( c > 'z'){
c = 96 + (c % 122); // wrapping from z to a?
}
}
else if(c >= 'A' && c <= 'Z'){
c += k;
if(c > 'Z'){
c = 64 + (c % 90);
}
}
cout << (char)c;
}
K is amount of shift and c is a char of string s.
Is there any better way to do the same?
Lets make a couple changes to the code and it is easier to see what is going on
for(int i = 0; i < n; i++){
int c = s[i];
if(c >= 'a' && c <= 'z'){
c += k;
if( c > 'z'){
c = 'a' + (c % 'z') - 1; // wrapping from z to a?
}
}
else if(c >= 'A' && c <= 'Z'){
c += k;
if(c > 'Z'){
c = 'A' + (c % 'Z') - 1;
}
}
cout << (char)c;
}
So in c = 'a' + (c % 'z') - 1; if c is larger than z then we mod c by z(122) to get how many characters from a we need to go. The same thing is going on with the upper case letters. I am subtracting one here as we are starting at a instead of the character before a like you original code does.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
So, I have been fiddling around with a code for a ctf competition. However, every time I run the actual console application, it keeps crashing. Could someone please explain to me why. Thank you so much in advance.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int lowerConvert(char x)
{
int y;
if (x == 'a')
y = 1;
if (x == 'b')
y = 2;
if (x == 'c')
y = 3;
if (x == 'd')
y = 4;
if (x == 'e')
y = 5;
if (x == 'f')
y = 6;
if (x == 'g')
y = 7;
if (x == 'h')
y = 8;
if (x == 'i')
y = 9;
if (x == 'j')
y = 10;
if (x =='k')
y = 11;
if (x == 'l')
y = 12;
if (x == 'm')
y = 13;
if (x == 'n')
y = 14;
if (x == 'o')
y = 15;
if (x == 'p')
y = 16;
if (x == 'q')
y = 17;
if (x == 'r')
y = 18;
if (x == 's')
y = 19;
if (x == 't')
y = 20;
if (x == 'u')
y = 21;
if (x == 'v')
y = 22;
if (x == 'w')
y = 23;
if (x == 'x')
y = 24;
if (x == 'y')
y = 25;
if (x == 'z')
y = 26;
return y;
}
int upperConvert(char x)
{
int y;
if (x == 'A')
y = 27;
if (x == 'B')
y = 28;
if (x == 'C')
y = 29;
if (x == 'D')
y = 30;
if (x == 'E')
y = 31;
if (x == 'F')
y = 32;
if (x == 'G')
y = 33;
if (x == 'H')
y = 34;
if (x == 'I')
y = 35;
if (x == 'J')
y = 36;
if (x == 'K')
y = 37;
if (x == 'L')
y = 38;
if (x == 'M')
y = 39;
if (x == 'N')
y = 40;
if (x == 'O')
y = 41;
if (x == 'P')
y = 42;
if (x == 'Q')
y = 43;
if (x == 'R')
y = 44;
if (x == 'S')
y = 45;
if (x == 'T')
y = 46;
if (x == 'U')
y = 47;
if (x == 'V')
y = 48;
if (x == 'W')
y = 49;
if (x == 'X')
y = 50;
if (x == 'Y')
y = 51;
if (x == 'Z')
y = 52;
return y;
}
char lowerBack(int x)
{
char y;
if (x == 1)
y = 'a';
else if (x == 2)
y = 'b';
else if (x == 3)
y = 'c';
else if (x == 4)
y = 'd';
else if (x == 5)
y = 'e';
else if (x == 6)
y = 'f';
else if (x == 7)
y = 'g';
else if (x == 8)
y = 'h';
else if (x == 9)
y = 'i';
else if (x == 10)
y = 'j';
else if (x == 11)
y = 'k';
else if (x == 12)
y = 'l';
else if (x == 13)
y = 'm';
else if (x == 14)
y = 'n';
else if (x == 15)
y = 'o';
else if (x == 16)
y = 'p';
else if (x == 17)
y = 'q';
else if (x == 18)
y = 'r';
else if (x == 19)
y = 's';
else if (x == 20)
y = 't';
else if (x == 21)
y = 'u';
else if (x == 22)
y = 'v';
else if (x == 23)
y = 'w';
else if (x == 24)
y = 'x';
else if (x == 25)
y = 'y';
else if (x == 26)
y = 'z';
return y;
}
char upperBack(int x)
{
char y;
if (x == 27)
y = 'A';
if (x == 28)
y = 'B';
if (x == 29)
y = 'C';
if (x == 30)
y = 'D';
if (x == 31)
y = 'E';
if (x == 32)
y = 'F';
if (x == 33)
y = 'G';
if (x == 34)
y = 'H';
if (x == 35)
y = 'I';
if (x == 36)
y = 'J';
if (x == 37)
y = 'K';
if (x == 38)
y = 'L';
if (x == 39)
y = 'M';
if (x == 40)
y = 'N';
if (x == 41)
y = 'O';
if (x == 42)
y = 'P';
if (x == 43)
y = 'Q';
if (x == 44)
y = 'R';
if (x == 45)
y = 'S';
if (x == 46)
y = 'T';
if (x == 47)
y = 'U';
if (x == 48)
y = 'V';
if (x == 49)
y = 'W';
if (x == 50)
y = 'X';
if (x == 51)
y = 'Y';
if (x == 52)
y = 'Z';
return y;
}
void primaryRot13()
{
cout << "Please enter name of file to be decrypted: ";
string name;
getline(cin, name);
name += ".txt";
ifstream file;
ofstream write;
file.open(name);
string message;
file >> message;
int converted[9999999];
char reconvert[9999999];
for (int i = 0; i < message.length();++i)
{
if (message[i] == 0 || 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9)
message[i] += 53;
if (message[i] == 'a' || 'b' || 'c' || 'd' || 'e' || 'f' || 'g' || 'h' || 'i' || 'j' || 'k' || 'l' || 'm' || 'n' || 'o' || 'p' || 'q' || 'r' || 's' || 't' || 'u' || 'v' || 'w' || 'x' || 'y' || 'z')
converted[i] = lowerConvert(message[i]);
converted[i] += 13;
if (converted[i] > 26)
converted[i] -= 26;
if (message[i] == 'A' || 'B' || 'C' || 'D' || 'E' || 'F' || 'G' || 'H' || 'I' || 'J' || 'K' || 'L' || 'M' || 'N' || 'O' || 'P' || 'Q' || 'R' || 'S' || 'T' || 'U' || 'V' || 'W' || 'X' || 'Y' || 'Z')
converted[i] = upperConvert(message[i]);
converted[i] += 13;
if (converted[i] > 52)
converted[i] -= 26;
}
for (int i = 0; i < message.length(); ++i)
{
if (converted[i] == 52 || 53 || 54 || 55 || 56 || 57 || 58 || 59 || 60 || 61){
reconvert[i] = converted[i] - 53;
continue;
}
if (converted[i] < 27){
reconvert[i] = lowerBack(converted[i]);
continue;
}
if (converted[i] < 51){
reconvert[i] = upperBack(converted[i]);
continue;
}
write.open("decode");
write << reconvert[i];
}
}
EDIT AND FINAL SOLUTION
Several years later, I am here to repost. What I ended up doing was simply adding the desired amount to the character code, then if it is greater than the upper limit for that set, I subtracted 26 in order to reset. I also ended up using the vector instead, which did solve my issue of crashing. Now I can happily rot13 all day long :) All without the myriad of if statements.
Table Lookup
First, an introduction to table or array look ups.
Given a character array:
static const char letters[] = "abcdefghijklmnopqrstuvwxyz";
The index of 'a' is 0, 'b' is 1, ..., 'z' is 25.
The array can be searched for a letter. The index of the letter can be it's number. In your case, it would be the index + 1.
Example:
static const unsigned int letter_quantity = sizeof(letters) / sizeof(letters[0]);
unsigned int index = 0;
for (index = 0; index < letter_quantity; ++i)
{
if (letters[i] == x)
{
break;
}
}
At the end of the loop statement, the index variable will be the position of the character in x or the length of the array (if not found).
Modulo Arithmetic
Modulo arithmetic, using the % operator, returns the remainder. It has the behavior of wrapping around. This can be used with the array.
unsigned int new_char_index = index + 13; // We may have gone past the array.
new_char_index = new_char_index % letter_quantity; // Wrap around.
The New ROT13 Character
The converted character can be found by using the new_char_index as the index into the array.
char rot13 = letters[new_char_index];
Covering all the characters
The remaining uppercase characters can be added to the array to account for all the letters. Other symbols can be added also.
All this without any if statements.
You're allocating two static arrays of 9999999 elements on the stack.
If an int is 32 bits and a char is 8 bits on your system, then that's 48MB of memory. That's simply too much for the stack.
Try allocating your arrays dynamically instead, i.e. using std::vector:
std::vector<int> converted(9999999);
std::vector<char> reconvert(9999999);
So, I am trying to make a ROT13decoder, and this is what I have so far. Only some of the letters change though and I am not sure why. I'm very new to programming. I am just trying to figure out how to read in files, and write to files. So far that part works, but yeah it doesn't change all the letters in the original file, just some of them. I would really appreciate any feedback.
#include <iostream>
#include <fstream>
//the letters in the secretMessage file are "Lbh unir gb fgnl va funcr. Zl tenaqzbgure, fur fgnegrq jnyxvat svir zvyrf n qnl jura fur jnf 60. Fur’f 97 gbqnl naq jr qba’g xabj jurer gur uryy fur vf
//
//
//and this is what it outputs to the decodedMessage file "Lbh haie gb fgal ia fhace. Ml geaadmbghee, fhe fgaeged jalkiag fiie milef a dal jhea fhe jaf 60. Fhe’f 97 gbdal aad je dba’g kabj jheee ghe hell fhe if.
using namespace std;
int main(){
ofstream fout;
ifstream fin;
fin.open("secretMessage.txt");
fout.open("decodedMessage.txt");
char c = 0;
while (!fin.eof()){
c = fin.get();
if (c == 'a')c = 'n';
if (c == 'b')c = 'o';
if (c == 'c')c = 'p';
if (c == 'd')c = 'q';
if (c == 'e')c = 'r';
if (c == 'f')c = 's';
if (c == 'g')c = 't';
if (c == 'h')c = 'u';
if (c == 'i')c = 'v';
if (c == 'j')c = 'w';
if (c == 'k')c = 'x';
if (c == 'l')c = 'y';
if (c == 'm')c = 'z';
if (c == 'n')c = 'a';
if (c == 'o')c = 'b';
if (c == 'p')c = 'c';
if (c == 'q')c = 'd';
if (c == 'r')c = 'e';
if (c == 's')c = 'f';
if (c == 't')c = 'g';
if (c == 'u')c = 'h';
if (c == 'v')c = 'i';
if (c == 'w')c = 'j';
if (c == 'x')c = 'k';
if (c == 'y')c = 'l';
if (c == 'z')c = 'm';
if (c == 'A')c = 'N';
if (c == 'B')c = 'O';
if (c == 'C')c = 'P';
if (c == 'D')c = 'Q';
if (c == 'E')c = 'R';
if (c == 'F')c = 'S';
if (c == 'G')c = 'T';
if (c == 'H')c = 'U';
if (c == 'I')c = 'V';
if (c == 'J')c = 'W';
if (c == 'K')c = 'X';
if (c == 'L')c = 'Y';
if (c == 'M')c = 'Z';
if (c == 'N')c = 'A';
if (c == 'O')c = 'B';
if (c == 'P')c = 'C';
if (c == 'Q')c = 'D';
if (c == 'R')c = 'E';
if (c == 'S')c = 'F';
if (c == 'T')c = 'G';
if (c == 'U')c = 'H';
if (c == 'V')c = 'I';
if (c == 'W')c = 'J';
if (c == 'X')c = 'K';
if (c == 'Y')c = 'L';
if (c == 'Z')c = 'M';
cout << c;
if (!fin.eof())fout << c;
}
fin.close();
fout.close();
return 0;
}
Most letters in your example will be flipped twice. You either need to add a whole lot of 'else' commands or use a switch statement.
if (c == 'a')c = 'n';
else if (c == 'b')c = 'o';
There is a better, mathematical method; but I'll leave that as an exercise to the reader.
You have a logic error. If you start with "a" the first IF turns it into "n" and a later IF turns it back into "a".
Have a look at the switch statement.
you should not use if conditions everywhere as each of them will be checked as you have a new row. Suppose your character is l then your if statement changes the letter to y but the condition for y is also checked so the character is changed back to l. So in fact your code is not not changing some of the letters, it is changing them twice.
You should be able to cure this using else if for the subsequent entries so that when one is true the other ones don't get checked, or you could use a switch case.
Take a single letter encoded in ROT13. If you encode it twice, you end up with the original letter again, which makes encoding and decoding ROT13 practically the same.
Now take for example the letter 'a'. What you are doing above in your code is
if (c == 'a') c = 'n';
...
if (c == 'n') c = 'a';
So for the first half of the letters above (a to m), you're encoding twice, getting the same letter again. Only for the lower half of the letters the encoding is only done once.
One solution to this would be to change your statements to something like
if (c == 'a') { c = 'n'; continue; }
This would skip the rest of the code in case of a match and continue with the next loop iteration.
For a homework assignment: I'm supposed to create randomized alphabetial keys, print them to a file, and then hash each of them into a hash table using the function "goodHash", found in my below code.
When I try to run the below code, it says my "goodHash" "identifier isn't found". What's wrong with my code?
#include <iostream>
#include <vector>
#include <cstdlib>
#include "math.h"
#include <fstream>
#include <time.h>
using namespace std;
// "makeKey" function to create an alphabetical key
// based on 8 randomized numbers 0 - 25.
string makeKey() {
int k;
string key = "";
for (k = 0; k < 8; k++) {
int keyNumber = (rand() % 25);
if (keyNumber == 0)
key.append("A");
if (keyNumber == 1)
key.append("B");
if (keyNumber == 2)
key.append("C");
if (keyNumber == 3)
key.append("D");
if (keyNumber == 4)
key.append("E");
if (keyNumber == 5)
key.append("F");
if (keyNumber == 6)
key.append("G");
if (keyNumber == 7)
key.append("H");
if (keyNumber == 8)
key.append("I");
if (keyNumber == 9)
key.append("J");
if (keyNumber == 10)
key.append("K");
if (keyNumber == 11)
key.append("L");
if (keyNumber == 12)
key.append("M");
if (keyNumber == 13)
key.append("N");
if (keyNumber == 14)
key.append("O");
if (keyNumber == 15)
key.append("P");
if (keyNumber == 16)
key.append("Q");
if (keyNumber == 17)
key.append("R");
if (keyNumber == 18)
key.append("S");
if (keyNumber == 19)
key.append("T");
if (keyNumber == 20)
key.append("U");
if (keyNumber == 21)
key.append("V");
if (keyNumber == 22)
key.append("W");
if (keyNumber == 23)
key.append("X");
if (keyNumber == 24)
key.append("Y");
if (keyNumber == 25)
key.append("Z");
}
return key;
}
// "makeFile" function to produce the desired text file.
// Note this only works as intended if you include the ".txt" extension,
// and that a file of the same name doesn't already exist.
void makeFile(string fileName, int n) {
ofstream ourFile;
ourFile.open(fileName);
int k; // For use in below loop to compare with n.
int l; // For use in the loop inside the below loop.
string keyToPassTogoodHash = "";
for (k = 1; k <= n; k++) {
for (l = 0; l < 8; l++) { // For-loop to write to the file ONE key
ourFile << makeKey()[l];
keyToPassTogoodHash += (makeKey()[l]);
}
ourFile << " " << k << "\n";// Writes two spaces and the data value
goodHash(keyToPassTogoodHash); // I think this has to do with the problem
makeKey(); // Call again to make a new key.
}
}
// Primary function to create our desired file!
void mainFunction(string fileName, int n) {
makeKey();
makeFile(fileName, n);
}
// Hash Table for Part 2
struct Node {
int key;
string value;
Node* next;
};
const int hashTableSize = 10;
Node* hashTable[hashTableSize];
// "goodHash" function for Part 2
void goodHash(string key) {
int x = 0;
int y;
int keyConvertedToNumber = 0;
// For-loop to produce a numeric value based on the alphabetic key,
// which is then hashed into hashTable using the hash function
// declared below the loop (hashFunction).
for (y = 0; y < 8; y++) {
if (key[y] == 'A' || 'B' || 'C')
x = 0;
if (key[y] == 'D' || 'E' || 'F')
x = 1;
if (key[y] == 'G' || 'H' || 'I')
x = 2;
if (key[y] == 'J' || 'K' || 'L')
x = 3;
if (key[y] == 'M' || 'N' || 'O')
x = 4;
if (key[y] == 'P' || 'Q' || 'R')
x = 5;
if (key[y] == 'S' || 'T')
x = 6;
if (key[y] == 'U' || 'V')
x = 7;
if (key[y] == 'W' || 'X')
x = 8;
if (key[y] == 'Y' || 'Z')
x = 9;
keyConvertedToNumber = x + keyConvertedToNumber;
}
int hashFunction = keyConvertedToNumber % hashTableSize;
Node *temp;
temp = new Node;
temp->value = key;
temp->next = hashTable[hashFunction];
hashTable[hashFunction] = temp;
}
// First two lines are for Part 1, to call the functions key to Part 1.
int main() {
srand ( time(NULL) ); // To make sure our randomization works.
mainFunction("sandwich.txt", 5); // To test program
cin.get();
return 0;
}
I realize my code is cumbersome in some sections, but I'm a noob at C++ and don't know much to do it better.
I'm guessing another way I could do it is to AFTER writing the alphabetical keys to the file, read them from the file and hash each key as I do that, but I wouldn't know how to go about coding that.
C++ expected everything to be declared in order, so that nothing's used before it's declared.
If you need to refer to a function higher in the file than where it's defined, you need to have a function prototype near the top of the file that declares the function. (Writing prototypes for all functions is a standard practice as a result of this.)
Near the top of the file (after the #includes) simply add
void goodHash(string key);
Definitions
Function declaration: something that declares the name of the function and the types the function takes.
Function definition: something that specifies the actual code of the function.
if you insert
void goodHash(string key);
in the line under "using namespace..." it will work
The issue is that you have to forward declare goodHash or define goodHash before makeFile if you want to use goodHash in makeFile. Otherwise, when the compile is in makeFile, it sees the token goodHash and hasn't found out what it means, which is why you are getting the compile-time error.
EDIT: Here is a good resource on forward declarations
you forgot the function prototype just add this in the top:
void goodHash(string key);
and btw your makeKey() is too long
you can try this instead:
string makeKey() {
int k;
string key = "";
for (k = 0; k < 8; k++) {
int keyNumber = (rand() % 25);
char app[2];
app[0] = keyNumber + 'A';
app[1] = 0;
key.append(app);
}
return key;
}