C++ Anagram Maker Error - c++

I have been trying to make an anagram maker, using a textBox (encryption_text) for input, which the text is "Hello World", and the output textBox (encrypted_text) which receives the text:
"ellllloooo
WWWWWWooooooorrrrrrrrllllllllldddddddddd".
I also have a textBox called 'anag_used', which should record the used number/location in the string to encrypt.
Have I over complicated it, or is there an error?
Thanks :)
Here is my code:
void anagram()
{
string toanagram = marshal_as<string>(encryption_text->Text);
string out;
int k;
System::String^ rndstr;
System::String^ ktostr;
ostringstream kstr;
anag_used->Clear();
for (int i = 0; i < toanagram.size(); ++i)
{
anag_used->Text += "\n";
int rnd = 0 + rand() % toanagram.size();
ostringstream rndtostr;
rndtostr << rnd;
rndstr = gcnew System::String(rndtostr.str().c_str());
for (int l = 0; l < i; ++l)
{
if (anag_used->Lines[l] == rndstr)
{
k = rnd;
kstr << k;
ktostr = gcnew System::String(kstr.str().c_str());
for (System::String^ j = anag_used->Lines[l]; j == ktostr; k = 0 + rand() % toanagram.size())
{
kstr << k;
ktostr = gcnew System::String(kstr.str().c_str());
if (anag_used->Lines[l] == ktostr)
{
//Do someting if you want
}
else
{
out += toanagram[k];
anag_used->Lines[l] = ktostr;
}
}
}
else
{
out += toanagram[i];
anag_used->Lines[i] = rndstr;
}
}
}
encrypted_text->Text = marshal_as<System::String^>(out);
}
EDIT: FOUND A MUCH SIMPLER WORKING CODE
#include <algorithm>
.
string toanagram = marshal_as<string>(encryption_text->Text);
sort(toanagram.begin(), toanagram.end());
encrypted_text->Text = marshal_as<System::String^>(toanagram);

This works for console, but you could implement it in C++/CLI quite easily
#include <iostream>
#include <sstream>
#include <vector>
#include <ctime>
void str_vect(std::vector<const char>* v, std::string& s)
{
for (int i = 0; i < s.length(); ++i)
{
v->push_back(s[i]);
}
}
int main()
{
for (;;)
{
std::cout << "Please enter the word / phrase\n";
std::string word;
std::getline(std::cin, word);
std::vector<const char> word_split;
str_vect(&word_split, word);
int sz = word_split.size();
std::string anagram;
for (int i = 0; i < sz; ++i)
{
srand(time(NULL));
int r = (rand() % (word_split.size() - 0)) + 0;
anagram += word_split[r];
word_split.erase((word_split.begin()) + r);
}
system("cls");
std::cout << "Please guess the anagrammed phrase / word - '" << anagram << "'\n";
int max_tries = 3;
int tries = max_tries;
for (int i = 0; i <= max_tries; ++i)
{
std::string guess;
std::getline(std::cin, guess);
if (guess != word)
{
tries--;
if (tries == 0)
{
std::cout << "You have ran out of tries. The answer was: " << word << "\n";
break;
}
std::cout << tries << ((tries == 1) ? " try" : " tries") << " left\n";
}
else
{
std::cout << "Correct!\n";
break;
}
}
}
}

#include <algorithm>
.
string toanagram = marshal_as<string>(encryption_text->Text);
sort(toanagram.begin(), toanagram.end());
encrypted_text->Text = marshal_as<System::String^>(toanagram);

Related

Reference to a vector element become invalid after n iterations

Program stop occur in this line
guess = secret;
From that, I guess that reference is broken, because if I change reference to simple value
const string secret = word_list[idx_word];
the program finishes correctly. So, my question is why this happen. The word_list is not changed/resided in loop.
Erorr occur on 392 iteration.
#include <QCoreApplication>
#include <QFile>
#include <QDir>
#include <QVector>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <thread>
#include <mutex>
#include <iomanip>
#include <string>
using namespace std;
bool debug = true;
const int COUNT = 5;
string MASK_FULL_MATCH(COUNT, 'o');
const string getMask(const string& word, const string& answer) {
if (word.size() != COUNT || answer.size() != COUNT) {
cout << word.size() << " " << answer.size() << endl;
}
char mask[5];
bool visited[5];
for (int i = 0; i < COUNT; i++) {
mask[i] = 'x';
visited[i] = false;
}
// find correct letters
for(int i = 0; i < COUNT; i++){
if (word[i] == answer[i]){
mask[i] = 'o';
visited[i] = true;
}
}
// find present letters
for (int i = 0; i < COUNT; i++){
if (mask[i] != 'o'){
for (int j = 0; j < COUNT; j++) {
if (answer[j] == word[i] && !visited[j]) {
mask[i] = '-';
visited[j] = true;
break;
}
}
}
}
return string(mask, COUNT);
}
int main(int argc, char *argv[])
{
QString pathToFile = QString("C:/Users/Ivan/Desktop/w_assets/w") + QString::number(COUNT) + QString("_entropy.txt");
QFile file(pathToFile);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return -2;
QTextStream in(&file);
QVector<string> word_list;
while (!in.atEnd()) {
QString line = in.readLine();
word_list.append(line.split(QChar(' '))[0].toStdString());
}
file.close();
for (int idx_word = 0; idx_word < word_list.size(); idx_word++) {
const string &secret = word_list[idx_word];
cout << secret << '\t';
}
int total = 0;
for (int idx_word = 0; idx_word < word_list.size(); idx_word++) {
const string &secret = word_list[idx_word];
cout << "NEW SECRET " << secret << endl;
QVector<string> possible_answers = word_list;
for (int row = 0; row < 6; row++) {
string guess;
if (row == 0) {
guess = word_list[0];
}
else {
cout << "before broken secret\n";
guess = secret;
cout << "after broken secret\n";
cout << "row " << row << "; GUESS " << guess << endl;
}
debug = true;
string mask = getMask(guess, secret);
debug = false;
cout << "MASK: " << mask << endl;
if (mask == MASK_FULL_MATCH) {
break;
}
QVector<string> new_possible_answers;
for (const auto& pa : possible_answers) {
if (getMask(guess, pa) == mask) {
new_possible_answers.append(pa);
}
}
possible_answers = new_possible_answers;
cout << "NEW POSSIBLE WORDS SIZE " << possible_answers.size() << endl;
}
}
return 0;
}
word_list[0]; - this is a non-const operation in a QVector (see documentation, there is even a note about the possible detach) and since the reference count of your word_list is two due to the copy to possible_answers some lines above, the container has to do a detach and therefore your reference goes out of scope.
If you work with references on Qt containers you have to make sure to either have a reference count of 1 or only use const-access to the container (e.g. by creating a const ref to the container -> const auto &const_word_list = word_list; guess = const_word_list [0])

pHash returning different hash lenght

I have the following code:
fingerprint.cpp:
#include <iostream>
#include <filesystem>
#include "ImageHash.h"
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include <opencv2/imgcodecs.hpp>
using namespace std;
void usage (char** argv) noexcept {
cout << "Usage: " << argv[0] << " <image or dir>" << endl << "Example: " << argv[0] << " template.png" << endl;
}
int main(int argc, char** argv) {
if (argc != 2) {
usage(argv);
return 1;
}
auto imgHash = ImageHash();
if (std::filesystem::is_directory(argv[1])) {
for (const auto& dirEntry : std::filesystem::recursive_directory_iterator(argv[1])) {
auto filePath = dirEntry.path();
std::string fileName = dirEntry.path().filename().string();
cv::Mat img = cv::imread(filePath.string(), cv::IMREAD_GRAYSCALE);
img.resize(8*8);
/*cv::imshow("img", img);
cv::waitKey();*/
cout << fileName << "\t\t" << imgHash.getHashString(img) << endl;
}
}
else if (std::filesystem::is_regular_file(argv[1])){
cv::Mat img = cv::imread(argv[1], cv::IMREAD_GRAYSCALE);
cout << std::filesystem::path(argv[1]).filename().string() << "\t\t" << imgHash.getHashString(img) << endl;
}
else {
usage(argv);
}
return 0;
}
ImageHash.cpp:
#include "ImageHash.h"
#include <iomanip>
using namespace std;
ImageHash::ImageHash()
{
pHash = cv::img_hash::PHash::create();
}
std::string ImageHash::convertHashToString(vector<bool> hash) {
std::string ret = "";
double h = 0;
for (unsigned int i = 0; i < hash.size(); i++) {
if (hash[i]) {
h += pow(2, (i % 8));
}
if (i % 8 == 7) {
std::stringstream buffer;
buffer << std::hex << std::setfill('0') << std::setw(2) << h;
ret += buffer.str();
h = 0;
}
}
return ret;
}
std::vector<bool> ImageHash::hex_str_to_hash(std::string inputString) {
std::vector<bool> hash;
size_t size = inputString.size() / 2;
for (int i = 0; i < size; i++) {
std::string str2 = inputString.substr(i * 2, 2);
if (str2.empty()) {
continue;
}
unsigned int value = 0;
std::stringstream SS(str2);
SS >> std::hex >> value;
for (int j = 0; j < 8; j++) {
bool check = !!((value >> j) & 1);
hash.push_back(check);
}
}
return hash;
}
std::vector<bool> ImageHash::matHashToBoolArr(cv::Mat const inHash) {
const unsigned char* data = inHash.data;
std::vector<bool> v;
for (int i = 0; i < 8; i++) {
unsigned char c = data[i];
for (int j = 0; j < 8; j++) {
int shift = (8 - j) - 1;
bool val = ((c >> shift) & 1);
v.push_back(val);
}
}
return v;
}
std::vector<bool> ImageHash::computeHash(cv::Mat const input) {
cv::Mat inHash;
pHash->compute(input, inHash);
return matHashToBoolArr(inHash);
}
std::string ImageHash::getHashString(cv::Mat const input) {
return convertHashToString(computeHash(input));
}
//returns hamming distance
int ImageHash::getHashDistance(std::vector<bool>& hash1, std::vector<bool>& hash2) {
//assert(hash1.size() == hash2.size());
/* ToDo: I don't know why the size is not the same but if if is lets add padding to the smaller one
This does not seem to make it work*/
if (hash1.size() != hash2.size()) {
auto smaller = hash1.size() < hash2.size() ? &hash1 : &hash2;
auto larger = hash1.size() < hash2.size() ? hash2 : hash1;
smaller->resize(larger.size());
std::fill(begin(*smaller) + larger.size(), end(*smaller), 0);
}
int dist = 0;
for (unsigned int i = 0; i < hash1.size(); i++) {
dist += (hash1[i] != hash2[i]);
}
return dist;
}
For some reason the hashes returned have different size depending on the input image. I tried to add some padding at getHashDistance() but I don't think I should do that since now when I calculate the distance between two similar images I get a large distance as if they were not similar.
Do you know why that is? I'm resizing the images to 8*8 img.resize(8*8); which I though it would make the trick but it does not work.
Thanks
Thanks
auto imgHash = ImageHash();
Could it be that the auto keyword here is causing the runtime to draw different inferences of the returned type (and therefore the size of the returned type)?
Type Inference in C++ (auto and decltype)

add space after space in char array

So, i need to insert space after space in char string, for example:
we have string: hello world, and function should be return hello world
hello world something else => hello world something else
hello world => hello world (4 spaces) (not necessarily, but preferably)
how?? (definitely need to be used char string)
my solution (it does not work correctly because it insert only 1 space)
from hello world something it returns hello world something:
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
char* addSpaces(char* str) {
char* p = strchr(str, ' ');
if (p) {
p++;
int n = strlen(p);
p[n + 1] = 0;
while (n) {
p[n] = p[n - 1];
n--;
}
*p = ' ';
}
return str;
}
int main(void) {
const int stringCount = 1;
const int c = 500;
char cstring[stringCount][c];
string str[stringCount];
for (int i = 0; i < stringCount; i++) {
cout << "Enter " << i + 1 << ". line: ";
cin.getline(cstring[i], c);
str[i] = cstring[i];
}
for (int i = 0; i < stringCount; i++) {
cout << "First function result with char in parameter: ";
char* result = addSpaces(cstring[i]);
cout << result << endl;
}
}
Using Dynamic Array:
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
char *add(char *arr, int lastIndex, char key)
{
int len = sizeof(&arr);
if (len == 0 || arr[len - 1] != '\0')
{
char newArr[len + 100];
newArr[len + 100 - 1] = '\0';
strncpy(newArr, arr, len);
*arr = *newArr;
}
arr[lastIndex] = key;
return arr;
}
int main(void)
{
std::string line;
const int stringCount = 1;
const int c = 500;
cout << "Enter line: ";
std::getline(std::cin, line);
int spaceCount = 0;
char cstring[0];
int lastUpdated = 0;
for (int i = 0; i < sizeof(line); i++)
{
add(cstring, lastUpdated++, line[i]);
if (line[i] == ' ')
{
add(cstring, lastUpdated++, ' ');
}
}
cout << cstring << endl;
}
OR
Check for space first and start char str with len+spaces. and add extra space on each iterate. Else error out of index bound can come.
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main(void)
{
std::string line;
const int stringCount = 1;
const int c = 500;
cout << "Enter line: ";
std::getline(std::cin, line);
cout << line << endl;
int spaceCount = 0;
for (int i = 0; i < sizeof(line); i++)
{
if (line[i] == ' ')
{
spaceCount += 1;
}
}
char cstring[stringCount + spaceCount];
int j = 0;
for (int i = 0; i < sizeof(line); i++)
{
if (line[i] == ' ')
{
cstring[j++] = ' ';
cstring[j++] = ' ';
}
else
{
cstring[j++] = line[i];
}
}
cout << cstring << endl;
}
Modify the main() function according to your needs:
#include <iostream>
#include <cstring>
#include <cstdlib>
#define MAXLEN 500
void add_space(char* str, size_t index, size_t n) {
if (n >= MAXLEN) {
std::cerr << "Cannot further expand the array!" << std::endl;
abort();
}
for (auto i = n; i >= index; --i)
str[i] = str[i - 1];
str[index] = ' ';
}
char* double_spaces(char* str, size_t n) {
for (size_t i = 0; i < n; ++i)
if (str[i] == ' ')
add_space(str, i++, n++);
return str;
}
int main() {
char str[MAXLEN] = "hello world";
std::cout << double_spaces(str, std::strlen(str)) << std::endl;
return 0;
}
Sample Output:
For str[] = "hello world" function returns "hello world"
For str[] = "hello world something else" function returns "hello world something else"
For str[] = "hello world" function returns "hello world"
PS: Better algorithms are possible but they mostly require use of advanced data structures so sticking to the asker's demand of using simple cstrings I have provided one of the simplest and easy to understand solution.
Analysis: The insertion operation requires O(n-index) time which can be reduced by using something similar to ArrayLists.

How to get a substring by deleting minimum number of characters?

In this question, we take 2 strings as input say s1 and s2.
Now, first we need to check if s2 is a subsequence of s1. If not, print no.
But if it is, we need to print the minimum number of characters to be deleted from s1 to get s2.
Eg- thistext text
Here, text can be directly found without deleting any characters so the answer is 0.
Eg- cutefriendship crisp
In this case, the answer is 9.
What I've done so far,
#include <bits/stdc++.h>
using namespace std;
int checkIfSub(string s1, string s2, int m, int n)
{
int j = 0;
for(int i = 0; i < m && j < n; i++)
if(s1[i] == s2[j])
j++;
if(j == n)
return 0;
else
return 1;
}
int check(string s1, string s2)
{
int count = 0; string s3;
if(checkIfSub(s1, s2, s1.length(), s2.length()) == 1 || s2.length() > s1.length())
{
cout << "NO\n"; return 0;
}
int j = 0;
for(int i = 0; i < s1.length(); i++)
{
if(s1[i] == s2[j])
{
s3[j] = s1[j];
j++; continue;
}
count++;
}
cout << "YES " << count << "\n";
return 0;
}
int main() {
string s1, s2;
cin >> s1 >> s2;
check(s1, s2);
return 0;
}
My code works well for the second example, but fails the first case.
(This was a question asked in some interview I read online.)
Try something like this:
#include <iostream>
#include <string>
using namespace std;
bool check(const string &s1, const string &s2, int &minToDelete)
{
minToDelete = 0;
bool anySubSeqFound = false;
if (s2.empty())
return false;
string::size_type first = 0;
while ((first = s1.find(s2[0], first)) != string::npos)
{
int numDeleted = 0;
bool isSubSeq = true;
string::size_type next = first + 1;
for(string::size_type j = 1; j < s2.size(); ++j)
{
string::size_type found = s1.find(s2[j], next);
if (found == string::npos)
{
isSubSeq = false;
break;
}
numDeleted += (found - next);
next = found + 1;
}
if (isSubSeq)
{
if (anySubSeqFound)
{
if (numDeleted < minToDelete)
minToDelete = numDeleted;
}
else
{
anySubSeqFound = true;
minToDelete = numDeleted;
}
}
++first;
}
return anySubSeqFound;
}
int main()
{
int minToDelete;
if (check("thistext", "text", minToDelete))
cout << "yes, delete " << minToDelete << endl;
else
cout << "no" << endl;
if (check("cutefriendship", "crisp", minToDelete))
cout << "yes, delete " << minToDelete << endl;
else
cout << "no" << endl;
}
Live Demo

c++ out of range at memory location error

Here is the code I have for a programing assignment I have. Im getting this error when I run the program
"Unhandled exception at at 0x772BC41F in STRUCT2.EXE: Microsoft C++ exception: std::out_of_range at memory location 0x0043ED04." If I understand this right, the error means my array has exceeded the allotted memory space. is that correct? and if this is correct, what am I doing wrong? My input file has less than 30 elements in it.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cmath>
#include <sstream>
#include <cctype>
using namespace std;
struct Element
{
string Name;
char eN1;
char eN2;
float Weight;
};
struct Formula
{
char Element1;
char ElementA;
int Atom;
};
void ELEMENTS(Element ElmAry[30]);
float Str2Float(string Weight);
void FORMULAS(Formula FormAry[30]);
float CalculateMoleculeWeight(Element ElmAry[30], Formula FormAry[30]);
int main()
{
ifstream inputFile1;
ifstream inputFile2;
ofstream outputFile;
inputFile1.open("Element.txt");
inputFile2.open("Formula.txt");
outputFile.open("Molecular Weight.txt");
Element ElmAry[30];
Formula FormAry[30];
char inputCh;
int i = 0;
string String1;
string mFor;
string ABRV;
int ElmDigit = 0;
float StringWeight = 0;
string Name;
string Weight;
int LENGTH = 0;
float MOLEWT;
if(!inputFile1)
{
cout << "Couldn't find the Element.txt file." << endl;
return 0;
}
if(!inputFile2)
{
cout << "Couldn't find the Formula.txt file." << endl;
return 0;
}
ELEMENTS(ElmAry);
while(inputFile1)
{
Name = String1.substr(0,2);
ElmAry[i].Name = Name;
Weight = String1.substr(3,10);
String1.clear();
StringWeight = Str2Float(Weight);
ElmAry[i].Weight = StringWeight;
i++;
}
i--;
FORMULAS(FormAry);
while (inputFile2)
{
getline(inputFile2,String1);
LENGTH = String1.length();
int j = 0;
int n = 0;
while( j < LENGTH)
{
int pos = 0;
pos = String1.find(')');
while(n < LENGTH)
{
inputCh = String1.at(n);
if(isalpha(inputCh) && isupper(inputCh))
{
FormAry[j].Element1 = String1.at(n);
n++;
inputCh = String1.at(n);
}
if(isalpha(inputCh) && islower(inputCh))
{
FormAry[j].ElementA = String1.at(n);
n++;
inputCh = String1.at(n);
}
if(ispunct(inputCh))
{
n++;
inputCh = String1.at(n);
ElmDigit = (inputCh-'0');
}
if(isdigit(inputCh))
{
FormAry[j].Atom = ElmDigit;
n++;
}
inputCh = String1.at(n);
j++;
if(iscntrl(inputCh))
{
n++;
inputCh = String1.at(n);
j++;
}
n++;
}
}
}
MOLEWT = CalculateMoleculeWeight(ElmAry, FormAry);
cout << "\t\t MOLECULAR WEIGHT CHART \t\t\n" << endl;
cout << "\n| FORMULA |\t " << "\t| ATOM.WT |" << endl;
cout << "_______________________________";
outputFile << "\t\t MOLECULAR WEIGHT CHART \t\t\n" << endl;
outputFile << "\n| FORMULA |\t " << "\t| ATOM.WT |" << endl;
outputFile << "_______________________________";
for (int a = 0; a < 30; a++)
{
cout << MOLEWT << endl;
outputFile << MOLEWT << endl;
}
inputFile1.close();
inputFile2.close();
outputFile.close();
cin.get();
cin.get();
return 0;
}
void ELEMENTS(Element ElmAry[30])
{
for(int i = 0; i < 30; i++)
{
ElmAry[i].Weight = 0;
}
}
void FORMULAS(Formula FormAry[30])
{
for(int x = 0; x < 30; x++)
{
for(int x = 0; x < 9; x++)
{
FormAry[x].Atom = 1;
}
}
}
float Str2Float (string x)
{
stringstream ss(x);
float StringWeight;
ss >> StringWeight;
return StringWeight;
}
float CalculateMoleculeWeight(Element ElmAry[30], Formula FormAry[30])
{
int i;
int j=0;
float MoleWT = 0;
float MoleSum = 0;
char e1;
char e2;
char f1;
char f2;
for(i = 0; i < 30; i++)
{
f1 = FormAry[j].Element1;
f2 = FormAry[j].ElementA;
e1 = ElmAry[i].eN1;
e2 = ElmAry[i].eN1;
if
(e1 == f1 && e2 == f2)
{
MoleWT = ElmAry[i].Weight * FormAry[j].Atom;
MoleSum = MoleSum + MoleWT;
j++;
}
}
return MoleSum;
}
when I get to
while(inputFile1)
{
Name = String1.substr(0,2);
ElmAry[i].Name = Name;
Weight = String1.substr(3,10);//invalid string position
String1.clear();
StringWeight = Str2Float(Weight);
ElmAry[i].Weight = StringWeight;
i++;
}
i--;
Weight = String1.substr(3,10); gives me an invalid string position
std::out_of_range is an exception you get when you attempt to access memory outside the space you've allocated (in an STL container). In this particular case, you are accessing areas of a std::string that has not been allocated:
Weight = String1.substr(3,10); // empty string or string.length() < 4 throws here
std::string::substr takes index parameters that must be within the bounds of the array encapsulated by std::string. If the string is only 2 characters long, and you attempt to get characters starting at the 4th position, you will see the std::out_of_range exception. You should check the length prior to doing this kind of operation.
Additionally, you are declaring your arrays:
Element ElmAry[30];
Formula FormAry[30];
But you are looping through an entire file (which potentially has more than 30 elements). Thus, when i >= 30, you are out of bounds (and behavior will be undefined).
You can fix that by using std::vector, which will allow the array to be dynamically sized, or another collection (e.g. std::list, std::deque).