Conversion between numerical bases going wrong - c++

I don't have a clue on what is wrong with my program. I just went testing if this would be usable on at least a console application before adding this "experiment"to my project and as you can see I failed.
I made a library that converts a number between numerical bases (so far, only B16 or B2 to decimal). It's a big work-around since I couldn't understand very well how to manage modulus and divisions, but it seemingly worked until a point.
I gave it a 0xFF and it treated it as 0xFF0, the result being 4,080. I gave it a 0x16 and it treated it like a 0x160, the result being 352. It's obvious what is happening, but I don't know why it is. At least, so far, the problem is only being with B16, although B2 did gave me some weird errors as well.
Here is the code (Code::Blocks on GNU compiler):
int bin_to_int(char char_digit){
char_digit = toupper(char_digit);
if (char_digit == '0') {return 0;}
else if (char_digit == '1') {return 1;}
else {return 2;}
}
int hex_to_int(char char_digit){
char_digit = toupper(char_digit);
if (char_digit == '0') {return 0;}
else if (char_digit == '1') {return 1;}
else if (char_digit == '2') {return 2;}
else if (char_digit == '3') {return 3;}
else if (char_digit == '4') {return 4;}
else if (char_digit == '5') {return 5;}
else if (char_digit == '6') {return 6;}
else if (char_digit == '7') {return 7;}
else if (char_digit == '8') {return 8;}
else if (char_digit == '9') {return 9;}
else if (char_digit == 'A') {return 10;}
else if (char_digit == 'B') {return 11;}
else if (char_digit == 'C') {return 12;}
else if (char_digit == 'D') {return 13;}
else if (char_digit == 'E') {return 14;}
else if (char_digit == 'F') {return 15;}
else {return 16;}
}
void conv_todec(int mode_base){
if (mode_base == 16){std::cout << "\nHex to Dec function";}
if (mode_base == 2){std::cout << "\nBin to Dec function";}
if (mode_base == 16){std::cout << "\nEnter a hex number: ";}
if (mode_base == 2){std::cout << "\nEnter a bin number: ";}
std::string numb;
std::cin >> numb;
int str_leg = numb.length();
int total = 0;
for(int i(0);i<str_leg;i++){
if (mode_base == 16){
if (hex_to_int(numb[i]) == 16){func_erro();return;}}
if (mode_base == 2){
if (bin_to_int(numb[i]) == 2){func_erro();return;}}
}
int digits[str_leg] = {};
int j = str_leg;
for(int i(0);i<str_leg;i++){
if (mode_base == 16) {digits[i] = hex_to_int(numb.at(i));}
if (mode_base == 2) {digits[i] = bin_to_int(numb.at(i));}
if (mode_base == 16) {total += (digits[i] * power(mode_base,j--));}
//Somehow the number never had the first digit claiming it as
//either even or odd, so I tried pre-decrementing 'j' and it
//worked for some reason I don't know either.
if (mode_base == 2) {total += (digits[i] * power(mode_base,--j));}}
std::cout << "The result is: " << total << std::endl;
}

This line:
int j = str_leg;
means that for hex FF, j will be 2. This means that later on when you do power(mode_base,j--) to multiply with the first digit, you will be doing power(16, 2) (remember that j-- means take the value of j, then subtract one from j, but still use the original value). So you will be multiplying the first digit by 256, where you only wanted to be multiplying by 16.
The solution? Start j as one smaller.
int j = str_leg - 1;
Note, this is why your binary version works when you use --j as you are decrementing j before you use it. So either use --j and j = str_leg, or j-- and j = strleg - 1.
Also, work on the modulo parts - it will make your program a lot easier to write.

Related

Evaluate Infix expression without converting it into postfix [duplicate]

This question already has answers here:
How to evaluate an infix expression in just one scan using stacks?
(4 answers)
Closed 3 years ago.
I'm trying to evaluate an infix expression in 1 pass without converting it into postfix but it's not giving correct output for some expressions. For eg: 3-5*10/5+10 , (45+5)-5*(100/10)+5
Can someone provide a proper solution to this problem in cpp.
Link to the previous question asked: How to evaluate an infix expression in just one scan using stacks?
Please don't mark it as duplicate as I have tried the algorithm answered in the above given thread but to no avail.
#include<bits/stdc++.h>
int isoperand(char x)
{
if(x == '+' || x=='-'|| x=='*' || x=='/' || x==')' || x=='(')
return 0;
return 1;
}
int Pre(char x)
{
if(x == '+' || x == '-')
return 1;
if(x == '*' || x == '/')
return 3;
return 0;
}
int infixevaluation(std::string exp)
{
std::stack<int> s1; //Operand Stack
std::stack<char> s2; //Operator Stack
int i,x,y,z,key;
i=0;
while(exp[i]!='\0')
{
if(isoperand(exp[i]))
{
key = exp[i]-'0';
s1.push(key);
i++;
}
else if(!isoperand(exp[i]) && s2.empty())
s2.push(exp[i++]);
else if(!isoperand(exp[i]) && !s2.empty())
{
if(Pre(exp[i])>Pre(s2.top()) && exp[i]!=')')
s2.push(exp[i++]);
else if(exp[i]==')' && s2.top() == '(')
{
s2.pop();
i++;
}
else if(exp[i]=='(')
s2.push(exp[i++]);
else
{
x = s1.top();
s1.pop();
y = s2.top();
s2.pop();
z = s1.top();
s1.pop();
if(y == '+')
s1.push(z+x);
else if(y == '-')
s1.push(z-x);
else if(y == '*')
s1.push(x*z);
else if(y == '/')
s1.push(z/x);
}
}
}
while(!s2.empty())
{
x = s1.top();
s1.pop();
y = s2.top();
s2.pop();
z = s1.top();
s1.pop();
if(y == '+')
s1.push(x+z);
else if(y == '-')
s1.push(z-x);
else if(y == '*')
s1.push(x*z);
else if(y == '/')
s1.push(z/x);
}
return s1.top();
}
int main(int argc, char const *argv[])
{
std::string s;
getline(std::cin,s);
std::cout<<infixevaluation(s)<<std::endl;
return 0;
}
Your code can only deal with single-digit operands -- and it has no checks for malformed input, so when you have a multi-digit operand, it runs off the rails.
The easiest fix for the former is just to scan digits when you see a digit -- change the if (isoperand(exp[i]) clause to:
if (isdigit(exp[i])) {
int value = 0;
while (isdigit(exp[i]))
value = value * 10 + exp[i++] - '0';
s1.push(value);
} else ...
For error checking, you should do things like
check for spaces and other invalid characters and reject or skip them
keep track of whether the last token matched was an operand or an operator, and give errors for two consecutive operands, or two consecutive operators other than ( and )

My 2D maze solver recurses infinitely and I get a stack overflow - why?

The Problem :-
I am trying to solve a 2d maze navigation problem in C++ using 2-dimensional array. To give a concise idea about the problem itself, I intend to navigate from node 'S' in the array to node 'G' by walking through free spaces denoted by '.' The nodes '#' are obstacles. One is not allowed to move on spaces denoted as obstacles. Care must also be taken to make all moves as legal moves (within configuration space). I denote the valid move with a '+' after replacement of the '.' If you like to know more about this problem (not necessary) then please refer this link.
What is the issue ?
I coded a recursive algorithm for this problem where we receive an array and a start node position, and then try to navigate to the goal node using recursion. However, I am getting a stack overflow error. It seems like my recursion never stops. I strongly believe there is some problem in my play() function or my check() function. I am not sure what actually is the problem.
What did I try ?
I am reproducing my code below :
void spawn(std::string (&board)[6]) {
for (int i = 0; i <= 6; i++) {
std::cout << board[i] << std::endl;
}
}
bool check(size_t a, size_t b, const std::string (&board)[6]) {
if (a < board[1].size() && a >= 0 && b < board[1].size() && b >= 0) {
if (board[a][b] == '#' || board[a][b] == '+')
return false;
else if (board[a][b] == '.')
return true;
}
return false;
}
void play(std::string (&board)[6], size_t a, size_t b) {
auto status = check(a, b, board);
if (board[a][b] == 'G' || board[a][b] == 'g') {
spawn(board);
return;
}
if (status) {
board[a][b] = '+';
play(board, ++a, b);
play(board, --a, b);
play(board, a, ++b);
play(board, a, --b);
}
}
int main() {
std::string grid[6] = {{"S#####"},
{".....#"},
{"#.####"},
{"#.####"},
{"...#.G"},
{"##...#"}};
play(grid, 0, 0);
return 0;
}
The check function prevents recursion because it sees the 'S' in the grid at the starting location. Changing:
else if (board[a][b] == '.')
to
else if (board[a][b] == '.' || board[a][b] == 'S')
got it to work for me.
Thanks for the insights Perette and Retired Ninja. I refactored the play() and check() functions in light of your suggestions and also some more ideas by myself.
I figured out that the main issue with the segmentation fault error was not providing accommodation for the '\0' character at the end of array of strings grid. I overlooked it because I considered array of strings to function in a different way than array of chars (since they are not the same species). Now I realize that the '\0' is necessary even for an array of strings !
I am reproducing the refactored functions for the purpose of completeness of this post :
void spawn(std::string board[6]) {
for (int i = 0; i <= 6; i++) {
std::cout << board[i] << std::endl;
}
}
bool check(int a, int b, const std::string board[6]) {
if (a < board[1].size() && a >= 0 && b <
board[1].size() && b >= 0) {
if (board[a][b] == '#' || board[a][b] == '+') {
return false;
} else if (board[a][b] == '.' ||
board[a][b] == 'S' ||
board[a][b] == 'G') {
return true;
}
}
return false;
}
void play(std::string board[6], int a, int b) {
if (board[a][b] == 'G' || board[a][b] == 'g') {
board[0][0] = 'S';
spawn(board);
return;
}
if (board[a][b] == '.' || board[a][b] == 'S')
board[a][b] = '+';
if (check(a + 1, b, board)) play(board, a + 1, b);
if (check(a - 1, b, board)) play(board, a - 1, b);
if (check(a, b + 1, board)) play(board, a, b + 1);
if (check(a, b - 1, board)) play(board, a, b - 1);
if (board[a][b] == '+') board[a][b] = '.';
}
int main() {
std::string grid[7] = {{"S#####"},
{".....#"},
{"#.####"},
{"#.####"},
{"...#.G"},
{"##...#"}};
play(grid, 0, 0);
return 0;
}

convert any base to base 10 in C++

I have this code:
#include <stdio.h>
#include <ctype.h>
int validnumber(int b, char* p);
unsigned long base2dec(int b,char *p);
void dec2base (int b,unsigned long x);
char *number;
main() {
int base,temp=0,count;
unsigned long Decimal_number;
do {
printf ("Give the base of the number you want to tranform:");
scanf ("%d", &base);
if (base<2 || base>16)
printf("Not acceptable base number, numbers should be in range from 2 to 16\n\n");
} while (base<2 || base>16);
printf ("Give the number you want to tranform:");
scanf("%s", number);
for (count=0;count<32;count++) {
number [count]= toupper(number[count]);
}
temp=validnumber(base, number);
if (temp==0)
printf ("O arithmpos pou eisagatai periexei MH egkira symbola\n");
else
if (temp==1)
printf ("O arithmpos pou eisagatai periexei egkira symbola\n");
if (temp==1) {
Decimal_number = base2dec( base , number);
}
int validnumber(int b, char *p){
int count, a[32];
for (count=0;count<32;count++)
a[count]=p[count];
if (b>=2 && b<=10) {
for (count=0;count<32;count++) {
if (a[count]<48 || a[count]>48+b)
return 0;
break;
}
}
if (b>=11 && b<=16) {
for (count=0;count<32;count++) {
if ((a[count]>=48 && a[count]<=57) || (a[count]>=65 && a[count]<=70)) {
return 1;
}
}
}
}
From this point the main program must call the function:
unsigned long base2dec (int b, char * p)
which accepts as arguments the base b and a pointer p in character table that
corresponds to the imported string s and returns the number representing the s expressed in the decimal system.
Also, it should call the function:
void dec2base (int b, unsigned long x)
which accepts as arguments the base b and the value of the number x in the decimal system and displays the base value and the representation of the number x in this base. The main program calls this function for all of the base values from 2 to 16.
Are there any ideas on how to begin? Any guidance will be appreciated.
In your base2dec, you will simply call this method and pass in 'b' as it is and x which should be the converted string.
Here is an implementation of dec2base. It is implemented recursively.
void dec2base(int b, unsigned long x){
if (x == 0)
return;
int y = x % b;
x /= b;
if (y < 0)
x += 1;
dec2base(b, x);
//converted digits to hex after realizing this solution doesn't work
//for bases greater than 10. Credits to Trevor pointing this out.
cout<< hex << y < 0 ? y + (b * -1) : y;
return;
}
First of all please have a look at your formatting because the way your code is written makes it harder than it needs to be to follow.
Here is what I would do:
#include <stdexcept>
#include <iostream>
void dec2base(int b, long x)
{
// Quick check for zero
if (x == 0)
{
std::cout << '0';
return;
}
// Print the negative sign if present, also negate
if (x < 0)
{
std::cout << '-';
x = -x;
}
char buf[12];
int i = 0;
// Convert to a backwards BCD
do {
buf[i++] = static_cast<char>(x % b);
} while (x /= b);
// Print it starting from the last digit (really the first)
do {
if (buf[--i] <= 9) std::cout << static_cast<char>(buf[i] + '0');
else std::cout << static_cast<char>(buf[i] + ('a' - 10));
} while (i);
}
long base2dec(int b, char * p)
{
long digit; // Current digit
long mul = 1; // Current multiplier
char *pos = p; // Current position
bool neg = false; // Sign
long ret = 0; // The return value
// Find the last digit
while (*pos) pos++;
// Continue until the start of the string is reached
while (pos-- != p)
{
if (*pos < '0')
{
if (*pos == '-')
{
// Sign reached, save it an break out
neg = true;
break;
}
else // Shouldn't happen
{
throw std::invalid_argument("Not a number");
}
}
if (*pos > 'f')
throw std::invalid_argument("Not a number");
// Get a digit
if (*pos <= '9') digit = *pos - '0';
else if (*pos >= 'a') digit = *pos - ('a' - 10);
else if (*pos >= 'A' && *pos <= 'F')
digit = *pos - ('A' - 10);
else
throw std::invalid_argument("Not a number");
// Make sure it is not larger than or equal to the base
if (digit >= b)
throw std::invalid_argument("Not a number");
// Add the digit
ret += digit * mul;
// Increase the multiplier
mul *= b;
}
return neg ? -ret : ret;
}
int main()
{
long val = base2dec(16, "123f");
dec2base(16, val);
return 0;
}
I realize you didn't ask for a signed version but as it is very easy to implement I have done it. If you really don't need to deal with signed values it is simple to drop the relevant parts from the functions.
This is a very quick and dirty go at this and this could no doubt be improved both for readability and performance but is, I think, a good starting point.
Here is a slightly improved version of base2dec():
long base2dec(int b, char * p)
{
long digit; // Current digit
bool neg = false; // Sign
long ret = 0; // The return value
// Check for negative number
if (*p == '-')
{
neg = true;
p++;
}
// Continue until the end of the string is reached
for (; *p != 0; p++)
{
// Rough range check
if (*p < '0' || *p > 'f')
throw std::invalid_argument("Not a number");
// Get a digit
if (*p <= '9') digit = *p - '0';
else if (*p >= 'a') digit = *p - ('a' - 10);
else if (*p >= 'A' && *p <= 'F')
digit = *p - ('A' - 10);
else
throw std::invalid_argument("Not a number");
// Make sure it is not larger than or equal to the base
if (digit >= b)
throw std::invalid_argument("Not a number");
// Add the digit
ret = ret * b + digit;
}
return neg ? -ret : ret;
}
Regarding the validnumber() function. This check is best performed during the conversion both to avoid having to read the entire string twice and because base2dec() really ought to check for valid input anyway. If you still need a separate check then you need to fix validnumber(). There is no need to copy the string to an array and it is also better to use the same code for all bases. Here is a suggestion:
bool validnumber(int b, char *p)
{
// Check for valid base
if (b < 2 || b > 16) return false;
// Extract numeric and alpha parts of the base
int b_numeric = b <= 10 ? b : 10;
int b_alpha = b - 11;
// Ignore any sign
if (*p == '-') p++;
// Continue until the end of the string
for (; *p != 0; p++)
{
// Digits < 0 are always bad
if (*p < '0') return false;
// Check for valid numeric digits
if (*p > ('0' + b_numeric))
{
// Check for valid alpha digits
if (b <= 10) return false;
if (*p < 'A' || *p > ('a' + b_alpha)) return false;
if (*p > ('A' + b_alpha) && *p < 'a') return false;
}
}
return true;
}

Converting a string to roman numerals in C++ [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to convert integer value to Roman numeral string?
first time asking a question here. I have a project on the horizon I've been working a bit on, and can't seem to find anything like it asked here or elsewhere. The goal is to accept an integer with no upper constraint, and convert that into a roman numeral. Since integers do in fact have an upper boundary, I have to convert it into a string before parsing it, using apostrophes to denote each set of three characters placed into a sub-string. I'm having trouble conceptualizing the loops that a)assign roman numerals to what they see based on their location b)count each set of three by displaying apostrophes.
So far I have:
for(int i=0;i<(int)input.length()/3;i++){
temp=input.substr(i,3);
for(int j = 0; j < (int)temp.length(); j++){
if(j == 0){
if(temp[j] == '9') cout<<"CM";
else if(temp[j] >= '8') cout<<"DCCC";
else if(temp[j] >= '7') cout<<"DCC";
else if(temp[j] >= '6') cout<<"DC";
else if(temp[j] >= '5') cout<<"D";
else if(temp[j] == '4') cout<<"CD";
else if(temp[j] == '3') cout<<"CCC";
else if(temp[j] == '2') cout<<"CC";
else if(temp[j] == '1') cout<<"C";
}
else if(j == 1){
if(temp[j] == '9') cout<<"XC";
else if(temp[j] >= '8') cout<<"LXXX";
else if(temp[j] >= '7') cout<<"LXX";
else if(temp[j] >= '6') cout<<"LX";
else if(temp[j] >= '5') cout<<"L";
else if(temp[j] == '4') cout<<"XL";
else if(temp[j] == '3') cout<<"XXX";
else if(temp[j] == '2') cout<<"XX";
else if(temp[j] == '1') cout<<"X";
}
else if(j ==2){
if(temp[j] == '9') cout<<"IX";
else if(temp[j] == '8') cout<<"VIII";
else if(temp[j] == '7') cout<<"VII";
else if(temp[j] == '6') cout<<"VI";
else if(temp[j] >= '5') cout<<"V";
else if(temp[j] == '4') cout<<"IV";
else if(temp[j] == '3') cout<<"III";
else if(temp[j] == '2') cout<<"II";
else if(temp[j] == '1') cout<<"I";
}
}
}
The numerals display well enough on their own, but I'm having trouble figuring out how to tell the loop to start on the right, and work it's way left by threes, maintaining the actual place of the number in the input (e.g. 1234 should display 1 as I, not C. I also need to figure out the loop to write in the apostrophes.
Simplest way i can think of to convert to roman numerals, is to check starting from the largest possible digit/combo and work down. Include combos, and check them from largest to smallest, so that say "XC" always gets checked before "L" and you don't have to worry about "LXXXX" and "LXL" and such.
// This code requires C++11 support. Namely, initializer lists and type inference.
// If your compiler sucks, there's equivalents for the important stuff. What really
// really matters is the order of the value=>digits mappings, and the iteration over
// them in the for loop.
#include <vector>
#include <string>
#include <utility>
std::string romanNumeralFor(int n, int markCount = 0) {
typedef std::pair<int, std::string> valueMapping;
static std::vector<valueMapping> importantNumbers = {
{1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"},
{100, "C"}, { 90, "XC"}, { 50, "L"}, { 40, "XL"},
{10, "X"}, { 9, "IX"}, { 5, "V"}, { 4, "IV"},
{1, "I"},
};
std::string result;
bool needMark = false;
std::string marks(markCount, '\'');
for (auto mapping : importantNumbers) {
int value = mapping.first;
std::string &digits = mapping.second;
while (n >= value) {
result += digits;
n -= value;
needMark = true;
}
if ((value == 1000 || value == 100 || value == 10 || value == 1) && needMark) {
result += marks;
needMark = false;
}
}
return result;
}
As for converting a string to a number:
// in C++11
int n = std::stoi(str);
// in C++03
std::istringstream iss(str);
int n;
iss >> n;
So, split your string up into three-digit chunks (starting from the end!), and pass them in with appropriate mark counts.
Not the best solution but it works.
#include <iostream>
#include <map>
#include <algorithm>
#include <string>
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
if(from.empty())
return;
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
}
int romanNumeralToInt(std::string s) {
std::map<char,int> romanNum = {
{'I',1}, {'V',5}, {'X',10}, {'L',50}, {'C',100},
{'D',500}, {'M',1000}
};
//{"IIIII",5}, {"VV",10}, {"XXXXX",50}, {"LL",100}, {"CCCCC",500}, {"DD",1000}
int g = 0;
std::sort(s.begin(),s.end());
if(s.find("IIIII") != std::string::npos)
replaceAll(s,"IIIII","V");
if(s.find("VV") != std::string::npos)
replaceAll(s,"VV","X");
if(s.find("XXXXX") != std::string::npos)
replaceAll(s,"XXXXX","L");
if(s.find("LL") != std::string::npos)
replaceAll(s,"LL","C");
for(auto& i : s) {
if(romanNum[i] != 0)
g += romanNum[i];
}
return g;
}
int main() {
std::string st = "XXXXXIIIIIVVVXLLD";
int a = romanNumeralToInt(st);
std::cout << a;
}
Prints out 680.

C++ function not found during compilation

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