The title says it all. I am having trouble figuring out what that error could mean, as I've never heard of it prior to now.
string Cracker_Functions::Loop(string Password, char fullset[]) {
int x = 0;
char word[32] = "";
int Passwordlen = Password.length();
for (int a = 0; a < Passwordlen; a++) {
for (int b = 0; b < 92; b++) {
for (int c = 0; c < 92; c++) {
word[b] = fullset[c];
if (word == Password) {
return word;
}
}
word[b] = fullset[a];
continue;
}
word[a] = fullset[x];
x += 1;
}
return "";
}
The program throws an exception at:
word[a] = fullset[x];
Notes on the function:
All necessary files are included.
The function is predefined in another file.
The number 32 is the maximum size of password the computer will try to guess.
The number 92 is the total amount of characters that the computer can cycle through.
fullset is all the characters in one list.
word represents what the program is currently cycling through. For example the current combination of characters is "h#(u?"
x is the counter for when the first loop is done with the other 2, and needs to reassign a new letter to begin again with.
Related
Fairly new to coding. Trying some of the easy projects at LeetCode, and failing... Ha! I am trying to take an integer and convert it to a string so I can reverse it, then re-convert the reversed string back into a integer.
This code is throwing the "terminate after throwing and instance of 'std::invalid argument' what(): stoi" error. I've spent an hour searching google and other questions here on SO, but can't figure out why it's not working.
bool isPalindrome(int x) {
std::string backwards ="";
std::string NumString = std::to_string(x);
for (int i = NumString.size(); i >= 0 ; i--) {
backwards += NumString[i];
}
int check = std::stoi(backwards);
if (check == x) {
return true;
}
else {
return false;
}
}
EDIT: I think I figured it out. It was adding the null character to the end of the string upon first conversion, then adding it to the beginning of the string when I reversed it. Spaces can't be converted to integers.
So... I changed this line and it works:
for (int i = NumString.size() - 1; i >= 0 ; i--)
you can also reverse number without using string.
bool isPalindrome(int x) {
long long rev = 0;
int cur = x;
while( cur > 0) {
rev *= 10;
rev += cur % 10;
cur /=10;
}
return rev == x;
}
Its simpler than your answer that you edited in. YOu have
for (int i = NumString.size(); i >= 0 ; i--) {
backwards += NumString[i];
}
Imagine that Numstring has length 3 (no matter what spaces, digits,....)
So now you are efectively doing
for (int i = 3; i >= 0 ; i--) {
backwards += NumString[i];
}
So first loop goes
backwards += NumString[3];
well the indexes of things in an array of length 3 in c++ are 0,1,2. YOu are going one off the end
This is why you see loops doing
for(int i = 0; i < len; i++){}
Note the i < len not i <= len
I am trying to design a recursive solution to Lewis Carroll's 'Word Ladder' game
The game attempts to link a starting word, for example 'WET' to an ending word, e.g. 'DRY' using a chain of words where between any 2 words just 1 letter is different. There is a limit on how many words can be used to make the chain.
For example for WET - DRY the solution is WET - bet - bat - bay - day - DRY
I am using the below recursive C function
exit condition: word is 1 step away from the 'target word' - i.e. if it sees DAY (= 1 step away from DRY), it returns true
It finds the solution, however, the problem is: it does not pass the solution back to original function. With each return call, the chain shaves off one word - i.e. the function's innermost call correctly solves 'bet - bat - bay - day' and stores it in the answer_chain - however once calls unwind - this array somehow gets passed as 'bet - bat - bay' (=loses 1 word), and so on, and as a result the original outermost function call gets no information about the solution.
I've tried:
Copying 'by value' by creating a c-style string first, assigning it back later
Copying the array item-by-item only when the first return is reached, and just assigning one array to the other otherwise (answer_chain = answer_chain_temp)
I've unfortunately not been able to figure out what the issue actually is.
Any help would be greatly appreciated.
bool find_chain(const char* start_word, const char* target_word, const char* answer_chain[], int max_steps){
if (answer_chain[0] == NULL) {} // This is to zero out incoming answer_chain
else if (!valid_step(start_word,answer_chain[0])){
delete[] answer_chain;
for (unsigned int i = 0; i < sizeof(answer_chain)/sizeof(answer_chain[0]);++i){
answer_chain[i] = NULL;
}
}
int filled_words = find_sz_of_char_arrays(answer_chain); // Looks for null-terminator
string previous_word, try_new_word;
bool is_solved = false;
if (valid_chain(answer_chain) && valid_step(answer_chain[filled_words-1],target_word) ) {
is_solved = true;
}
if (is_solved) {return true;}
if (max_steps == 0 && !is_solved) {return false;}
if (filled_words > 0) { previous_word = answer_chain[filled_words-1];} else {previous_word = start_word;}
for (unsigned int j = 0; j < strlen(start_word); ++j){
try_new_word = previous_word;
for (unsigned int i = 0; i < 26; ++i){
char new_char = i + 'A';
if (try_new_word.at(j) != new_char) { // has to be different from character already in place
try_new_word.at(j) = new_char;
if (valid_step(previous_word.c_str(),try_new_word.c_str()) && !is_word_already_in_chain(try_new_word.c_str(),answer_chain) ) {
const char** answer_chain_temp = new const char*[15]; // append 'try' word to answer array
for (int k = 0; k < filled_words;++k){
answer_chain_temp[k] = answer_chain[k];}
answer_chain_temp[filled_words] = try_new_word.c_str();
answer_chain_temp[filled_words+1] = NULL;
if (find_chain(start_word,target_word,answer_chain_temp,max_steps-1)){
delete[] answer_chain;
answer_chain = new const char*[15];
for (int kk = 0; kk < 15;++kk) {
if (answer_chain_temp[kk]!=NULL){
answer_chain[kk] = answer_chain_temp[kk];
}
}
delete[] answer_chain_temp;
return true;
} // if successful - append the word
} // if valid step
} // if letter is differerent
} // for i
} // for j
return false;
}
EDIT:
I've now changed the middle part to copy the .s_str() by value, however the issue still seems to persist. I believe something is off with how I am copying and deleting after the solution has been found:
const char** answer_chain_temp = new const char*[15]; // append 'try' word to answer array
for (int k = 0; k < filled_words;++k){answer_chain_temp[k] = answer_chain[k];}
char * writable = new char[try_new_word.size() + 1];
std::copy(try_new_word.begin(), try_new_word.end(), writable);
writable[try_new_word.size()] = '\0';
answer_chain_temp[filled_words] = writable;
answer_chain_temp[filled_words+1] = NULL;
if (find_chain(start_word,target_word,answer_chain_temp,max_steps-1)){
delete[] answer_chain;
answer_chain = new const char*[15];
for (int kk = 0; kk < 15;++kk) {
if (answer_chain_temp[kk] != NULL){
answer_chain[kk] = answer_chain_temp[kk]; // <<<<<< I believe the problem is here
}
}
display_chain(answer_chain,cout); cout << endl;
delete[] answer_chain_temp;
return true;```
I wanted to create a function that will split a string by a delimiter.. I know there's already a function that does this thing but I wanted to make on my own.. But it doesn't work as it should.
char** Engine::splitString(const char* text, char delimiter)
{
char** splitted;
splitted = (char**)malloc(50 * sizeof(char*));
for (int y = 0; y < 50; y++)
splitted[y] = (char*)malloc((strlen(text) + 2) * sizeof(char));
int delimiterPosition[50];
int arrayLength = 0;
int f = 0;
int g = 0;
for (int x = 0; x < strlen(text); x++)
{
if (text[x] == delimiter)
{
delimiterPosition[f] = x;
f++;
}
}
for (int x = 0; x < 50; x++)
if (delimiterPosition[x] > 0 )
arrayLength++;
while (g < arrayLength) {
if (g == 0) {
for (int y = 0; y < delimiterPosition[0]; y++)
{
splitted[g][y] = text[y];
}
}
else if(g > 0)
{
for (int y = delimiterPosition[g - 1]; y < delimiterPosition[g] - delimiterPosition[g - 1]; y++)
{
splitted[g][y] = text[y];
}
}
g++;
}
return splitted;
}
First of all, I declared a two dimensional char array -> splitted. This was the variable that I should store my results into. Then I allocated a memory for it.. I wanted to have 50 words maximum. After that I created integer array.. this served as a storage for delimiters' positions. I also defined some variables below it for my code. Then I looped through the text to see if there's any delimiter.. if yes, I wanted to store it's position to a certain position in array, starting off from 0. I looped through delimiterPosition's array to how many positions I have stored. Then I made a simple loop using while to take all the characters up to the delimiter's position and store them to splitted[g][y] .. g represents the whole word.. y represents the character in that word. If g was greater than zero, I tok the previous position of a delimiter and then substracted the current from the previous.. and that gave me the distance between the first delimiter and the next..
The main problem here is that the first word is written correctly, the second one is not working, but it has some weird characters behind it when I try to call it.. is the text somehow leaking? the second one isn't being stored at all?:
char** strings = en.splitString("Hello;boy", ';');
printf("%s", strings[1]);
First word:
Second:
Any solutions, guys ? :) Thank you for any comment.
This does not initialize the memory:
int delimiterPosition[50];
So its content is potentially random (and its undefined to read from unless you initialize it first). So here:
if (delimiterPosition[x] > 0 ) // Is potentially invalid if x >= f
Easily solved with:
int delimiterPosition[50] = {0};
Potential for overflow here:
delimiterPosition[f] = x;
f++;
You don't validate that f remains in the correct range (less than 50). Another easy fix:
size_t stringLen = strlen(text); // Don't need to recalculate this each time!
for (int x = 0; f < 50 && x < stringLen; x++)
{
if (text[x] == delimiter)
{
delimiterPosition[f] = x;
f++;
}
}
Here is the problem you are complaining about:
for (int y = 0; y < delimiterPosition[0]; y++)
{
splitted[g][y] = text[y];
}
You copy the string.
But you don't add a terminator to the string. So when you try and print it you see all the extra characters on the end.
for (int y = 0; y < delimiterPosition[0]; y++)
{
splitted[g][y] = text[y];
}
splitted[g][y] = '\0'; // Add string terminator.
For the second a subsequent string you have the null terminator problem. But you also have the issue that you are copying the string to not the beginning.
// After the first string the value of y in an offset into text only
// So when used with `splitted[g]` you are offset from the beginning
// if the string.
splitted[g][y] = text[y];
Also your test for the end of the string is wrong:
Remember you start at:
int y = delimiterPosition[g - 1]
So y is an offset into the string. So as you increase it it will always be an offset not a length.
// So this test is wrong (you are using a length not an offset.
y < delimiterPosition[g] - delimiterPosition[g - 1]
Lets fix both at the same time:
int dstIndex = 0;
for (int y = delimiterPosition[g - 1]; y < delimiterPosition[g]; y++, dstIndex++)
{
splitted[g][dstIndex] = text[y];
}
splitted[g][dstIndex] = '\0';
I'm working on another school project, in part of which I need to take the data from a .txt file and convert it to a mixed type vector... that contains two integers and a string. I've tried various ways of doing it, and I have it down to where the .txt file is inputted, and hopefully sent to vectors. My difficulty comes in when I try to do stuff with the vectors. My code segment is as follows (I'll explain what things are for with comments):
bool ReadPeopleFromFile(int argc, char* argv[], vector<Person> &people) {
Person tmpPrsn;
int tmpAge;
string tmpGender;
int tmpAnualIncome;
ifstream PeopleFile("dev_people.txt"); // Try to open file
if (!PeopleFile.is_open()) {
cout << "Could not open file.\n";
return true; // indicates error
}
cout << "Starting" << endl;
while (!PeopleFile.eof()) {
PeopleFile >> tmpAge;
PeopleFile >> tmpGender;
PeopleFile >> tmpAnualIncome;
tmpPrsn.SetData(tmpAge, tmpGender, tmpAnualIncome);
tmpPrsn.Print();
people.push_back(tmpPrsn); // Need to look at this!!!
}
PeopleFile.close();
cout << "Finished reading file." << endl;
return false;
}
//I have a function that gets the user input... I took it out for this post.
vector<Person> ptntlCstmrs;
// Return people within the given age range.
vector<Person> GetPeopleWithQualifyingCharacteristics(vector<Person> ppl, int AgelowerRange, int AgeupperRange, string DesiredGender, int YIlowerRange, int YIupperRange) {
unsigned int i = 0;
unsigned int j = 0;
unsigned int k = 0;
vector<Person> pplInRange;
int age = 0;
string gender = "";
int yearlyIncome = 0;
for (i = 0; i < ppl.size(); ++i) {
for (j = 0; j < ppl.size(); ++j) {
for (k = 0; k < ppl.size(); ++k) {
age = ppl.at(i).GetAge();
gender = ppl.at(j).GetGender();
yearlyIncome = ppl.at(k).GetYearlyIncome();
if ((age >= AgelowerRange) && (age <= AgeupperRange) && (gender == DesiredGender || gender == "Any") && (yearlyIncome >= YIlowerRange) && (yearlyIncome <= YIupperRange)) {
ptntlCstmrs.push_back(ppl.at(i));
}
}
} // I know this section is messed up... I can't figure out how to get this part to work. What I'm trying to do is take the input, and filter it based on the user-inputted criteria. Nothing that I have done has worked.
}
return pplInRange;
}
int main(int argc, char* argv[]) {
vector<Person> ptntlCstmrs;
bool hadError = false;
int ageLowerRange = 0;
int ageUpperRange = 0;
string desiredGender = "";
int yearlyIncomeLowerRange = 0;
int yearlyIncomeUpperRange = 0;
hadError = ReadPeopleFromFile(argc, argv, ptntlCstmrs);
if (hadError) {
return 1; // indicates error
}
GetUserInput(ageLowerRange, ageUpperRange, desiredGender, yearlyIncomeLowerRange, yearlyIncomeUpperRange);
ptntlCstmrs = GetPeopleWithQualifyingCharacteristics(ptntlCstmrs, ageLowerRange, ageUpperRange, desiredGender, yearlyIncomeLowerRange, yearlyIncomeUpperRange);
cout << "\nNumber of potential customers = " << ptntlCstmrs.size() << endl;
}
I included a bunch of this stuff just in case some of my references are off, but I don't think so. It also tells you what I'm working with. I would like help figuring out how to get the criteria to actually sort the vectors, and then print out how many of those vectors are going to work with the user inputted data.
Thanks in advance!
The credit really goes to #PaulMcKenzie . The problem with the above code is in the following section:
Return people within the given age range.
vector<Person> GetPeopleWithQualifyingCharacteristics(vector<Person> ppl, int AgelowerRange, int AgeupperRange, string DesiredGender, int YIlowerRange, int YIupperRange) {
unsigned int i = 0;
unsigned int j = 0;
unsigned int k = 0;
vector<Person> pplInRange;
int age = 0;
string gender = "";
int yearlyIncome = 0;
for (i = 0; i < ppl.size(); ++i) {
for (j = 0; j < ppl.size(); ++j) {
for (k = 0; k < ppl.size(); ++k) {
age = ppl.at(i).GetAge();
gender = ppl.at(j).GetGender();
yearlyIncome = ppl.at(k).GetYearlyIncome();
if ((age >= AgelowerRange) && (age <= AgeupperRange) && (gender == DesiredGender || gender == "Any") && (yearlyIncome >= YIlowerRange) && (yearlyIncome <= YIupperRange)) {
ptntlCstmrs.push_back(ppl.at(i));
}
}
} // I know this section is messed up... I can't figure out how to get this part to work. What I'm trying to do is take the input, and filter it based on the user-inputted criteria. Nothing that I have done has worked.
}
return pplInRange;
which needs to be changed to the following:
vector<Person> GetPeopleWithQualifyingCharacteristics(vector<Person> ppl, int Agelow, int Ageup, string DesGen, int YIlow, int YIup) {
unsigned int i = 0;
int age = 0;
string gender = "";
int yearlyIncome = 0;
ifstream PeopleFile("dev_people.txt");
while (PeopleFile >> age >> gender >> yearlyIncome);
vector<Person> pplInRange;
for (i = 0; i < ppl.size(); ++i) {
age = ppl.at(i).GetAge();
gender = ppl.at(i).GetGender();
yearlyIncome = ppl.at(i).GetYearlyIncome();
if ((age >= Agelow) && (age <= Ageup) && (DesGen == gender || DesGen == "Any") && (yearlyIncome >= YIlow) && (yearlyIncome <= YIup)) {
pplInRange.push_back(ppl.at(i));
}
}
return pplInRange;
}
Now it works fine. Thanks Paul!
My initial thoughts are that you aren't collecting user input correctly. You send your variables that determine whether or not a Person object is a potential customer off into another function.
By default C++ passes parameters by value -- meaning that when a parameter is passed into a function, a copy of said parameter is made and used throughout that function. When the function comes to a close, the edited parameter is then disposed of and all changes / edits are lost. If you want to grab user input from another method, and have said input saved, make sure to pass your parameters by reference.
Passing by reference essentially tells the machine where that specific parameter is located in memory and allows the program to directly access that piece of memory as opposed to making a copy of the parameter when executing your function. This in turn makes any changes made to parameters permanent!
Hope this helps!
Given two strings, write a method to decide if one is an anagram/permutation of the other. This is my approach:
I wrote this function to check if 2 strings are anagrams (such as dog and god).
In ascii, a to z is 97 - 122.
Basically I have an array of bools that are all initially false. Everytime I encounter a char in string1, it marks it as true.
To check if its an anagram, I check if any chars of string2 are false (should be true if encountered in string1).
I'm not sure how but this works too: arr[num] = true; (shouldnt work because I dont take into account that ascii starts at 97 and thus goes out of bounds).
(Side note: is there a better approach than mine?)
EDIT: Thanks for all the responses! Will be carefully reading each one. By the way: not an assignment. This is a problem from a coding interview practice book
bool permutation(const string &str1, const string &str2)
{
// Cannot be anagrams if sizes are different
if (str1.size() != str2.size())
return false;
bool arr[25] = { false };
for (int i = 0; i < str1.size(); i++) // string 1
{
char ch = (char)tolower(str1[i]); // convert each char to lower
int num = ch; // get ascii
arr[num-97] = true;
}
for (int i = 0; i < str2.size(); i++) // string 2
{
char ch = (char)tolower(str2[i]); // convert char to lower
int num = ch; // get ascii
if (arr[num-97] == false)
return false;
}
return true;
}
There is nothing inherent in C++ arrays that prevents you from writing beyond the end of them. But, in doing so, you violate the contract you have with the compiler and it is therefore free to do what it wishes (undefined behaviour).
You can get bounds checking on "arrays" by using the vector class, if that's what you need.
As for a better approach, it's probably better if your array is big enough to cover every possible character (so you don't have to worry about bounds checking) and it shouldn't so much be a truth value as a count, so as to handle duplicate characters within the strings. If it's just a truth value, then here and her would be considered anagrams.
Even though you state it's not an assignment, you'll still learn more if you implement it yourself, so it's pseudo-code only from me. The basic idea would be:
def isAnagram (str1, str2):
# Different lengths means no anagram.
if len(str1) not equal to len(str2):
return false
# Initialise character counts to zero.
create array[0..255] (assumes 8-bit char)
for each index 0..255:
set count[index] to zero
# Add 1 for all characters in string 1.
for each char in string1:
increment array[char]
# Subtract 1 for all characters in string 2.
for each char in string2:
decrement array[char]
# Counts will be all zero for an anagram.
for each index 0..255:
if count[index] not equal to 0:
return false
return true
Working approach : with zero additional cost.
bool permutation(const std::string &str1, const std::string &str2)
{
// Cannot be anagrams if sizes are different
if (str1.size() != str2.size())
return false;
int arr[25] = {0 };
for (int i = 0; i < str1.size(); i++) // string 1
{
char ch = (char)tolower(str1[i]); // convert each char to lower
int num = ch; // get ascii
arr[num-97] = arr[num-97] + 1 ;
}
for (int i = 0; i < str2.size(); i++) // string 2
{
char ch = (char)tolower(str2[i]); // convert char to lower
int num = ch; // get ascii
arr[num-97] = arr[num-97] - 1 ;
}
for (int i =0; i< 25; i++) {
if (arr[i] != 0) {
return false;
}
}
return true;
}
Yes, C and C++ both doesn't carry out the index-out-of-bounds.
It is the duty of the programmer to make sure that the program logic doesn't cross the legitimate limits. It is the programmer who need to make checks for the violations.
Improved Code:
bool permutation(const string &str1, const string &str2)
{
// Cannot be anagrams if sizes are different
if (str1.size() != str2.size())
return false;
int arr[25] = { 0 }; //<-------- Changed
for (int i = 0; i < str1.size(); i++) // string 1
{
char ch = (char)tolower(str1[i]); // convert each char to lower
int num = ch; // get ascii
arr[num-97] += 1; //<-------- Changed
}
for (int i = 0; i < str2.size(); i++) // string 2
{
char ch = (char)tolower(str2[i]); // convert char to lower
int num = ch; // get ascii
arr[num-97] = arr[num-97] - 1 ; //<-------- Changed
}
for (int i =0; i< 25; i++) { //<-------- Changed
if (arr[i] != 0) { //<-------- Changed
return false; //<-------- Changed
}
}
return true;
}