Your program shows this result, because the std::string
find function will only look for an exact match of a substring.
What you want is to calculate the distance of 2 strings and then show those with a distance of 1.
For calculating the distance, generally the well known Levensthein algorithm is used.
I showed an implementation already in my answers here and here.
With that, your solution can be modified to
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <numeric>
using namespace std;
// Distance between 2 strings
size_t levensthein(const std::string& string1, const std::string& string2)
{
// First get the string lengths
const size_t lengthString1{ string1.size() };
const size_t lengthString2{ string2.size() };
// If one of the string length is 0, then return the length of the other
// This results in 0, if both lengths are 0
if (lengthString1 == 0) return lengthString2;
if (lengthString2 == 0) return lengthString1;
// Initialize substitition cost vector
std::vector<size_t> substitutionCost(lengthString2 + 1);
std::iota(substitutionCost.begin(), substitutionCost.end(), 0);
// Calculate substitution cost
for (size_t indexString1{}; indexString1 < lengthString1; ++indexString1) {
substitutionCost[0] = indexString1 + 1;
size_t corner{ indexString1 };
for (size_t indexString2{}; indexString2 < lengthString2; ++indexString2) {
size_t upper{ substitutionCost[indexString2 + 1] };
if (string1[indexString1] == string2[indexString2]) {
substitutionCost[indexString2 + 1] = corner;
}
else {
const size_t temp = std::min(upper, corner);
substitutionCost[indexString2 + 1] = std::min(substitutionCost[indexString2], temp) + 1;
}
corner = upper;
}
}
return substitutionCost[lengthString2];
}
void fileRead(vector<string>& v, ifstream& fin) {
string line;
while (getline(fin, line)) {
v.push_back(line);
}
}
void search(vector<string>& v, string word) {
for (int i = 0; i < v.size(); i++) {
int distance = levensthein(word,v[i]);
if (distance == 1)
cout << v[i] << endl;
}
}
int main() {
vector<string> wordVector;
ifstream fin("text.txt");
if (!fin) {
cout << "text.txt can't opened" << endl;
return 0;
}
fileRead(wordVector, fin);
fin.close();
cout << "reading text.txt." << endl;
while (true) {
cout << "Input a word: >>";
string word;
getline(cin, word);
if (word == "exit")
break;
search(wordVector, word);
}
cout << "Terminated" << endl;
}
And if you want to convert this to more modern C++, you can also use:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <numeric>
#include <algorithm>
// Distance between 2 strings
size_t levensthein(const std::string& string1, const std::string& string2)
{
// First get the string lengths
const size_t lengthString1{ string1.size() };
const size_t lengthString2{ string2.size() };
// If one of the string length is 0, then return the length of the other
// This results in 0, if both lengths are 0
if (lengthString1 == 0) return lengthString2;
if (lengthString2 == 0) return lengthString1;
// Initialize substitition cost vector
std::vector<size_t> substitutionCost(lengthString2 + 1);
std::iota(substitutionCost.begin(), substitutionCost.end(), 0);
// Calculate substitution cost
for (size_t indexString1{}; indexString1 < lengthString1; ++indexString1) {
substitutionCost[0] = indexString1 + 1;
size_t corner{ indexString1 };
for (size_t indexString2{}; indexString2 < lengthString2; ++indexString2) {
size_t upper{ substitutionCost[indexString2 + 1] };
if (string1[indexString1] == string2[indexString2]) {
substitutionCost[indexString2 + 1] = corner;
}
else {
const size_t temp = std::min(upper, corner);
substitutionCost[indexString2 + 1] = std::min(substitutionCost[indexString2], temp) + 1;
}
corner = upper;
}
}
return substitutionCost[lengthString2];
}
int main() {
// Open file and check, if it could be opened
if (std::ifstream fin("text.txt"); fin) {
// Read all words from the file
std::vector words(std::istream_iterator<std::string>(fin), {});
// Read words to search for, until user enters exit
std::string word{};
while (word != "exit") {
// Tell user, what to do
std::cout << "\n\nInput a word: >> ";
// Show result
if (std::getline(std::cin, word) and word != "exit")
std::copy_if(words.begin(), words.end(), std::ostream_iterator<std::string>(std::cout, "\n"), [&](const std::string& s) { return 1u == levensthein(s, word); });
}
}
else std::cerr << "\nError. Could not open source file\n\n";
}
And if there is the restriction that only words of equal length shall be shown, then you can write a simple comparison function by yourself.
This would look like:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <numeric>
#include <algorithm>
bool oneLetterDifferent(const std::string& string1, const std::string& string2) {
bool equalLength{ string1.length() == string2.length() };
unsigned int unequalCounter{};
if (equalLength) for (size_t i{}; i < string1.length(); ++i) {
if (string1[i] != string2[i])
++unequalCounter;
}
return equalLength and (unequalCounter < 2);
}
int main() {
// Open file and check, if it could be opened
if (std::ifstream fin("text.txt"); fin) {
// Read all words from the file
std::vector words(std::istream_iterator<std::string>(fin), {});
// Read words to search for, until user enters exit
std::string word{};
while (word != "exit") {
// Tell user, what to do
std::cout << "\n\nInput a word: >> ";
// Show result
if (std::getline(std::cin, word) and word != "exit")
std::copy_if(words.begin(), words.end(), std::ostream_iterator<std::string>(std::cout, "\n"), [&](const std::string& s) { return oneLetterDifferent(s, word); });
}
}
else std::cerr << "\nError. Could not open source file\n\n";
}