Width constraint of the output lines to the console - c++

Class prints a string to the console.
How to make the width of output lines is equal characterWidth = 40,
ie after 40 characters was transferred to a new line?
#include <string>
#include <iostream>
class StringProcessing {
public:
StringProcessing() : characterWidth(40),
textToBeFormatted("NULL") {}
inline void StringProcessing::initString() {
textToBeFormatted =
"text some text some text some text some text some text"
"text some text some text some text some text some text"
"text some text some text some text some text"
"text some text some text some text some text some text"
"text some text some text some text some text some text";
}
inline void displayString()
{ std::cout << textToBeFormatted << std::endl; }
private:
int characterWidth;
std::string textToBeFormatted;
};
I have an idea but here the words in the console are cut off, so they need to be transferred to the next line and perform a width alignment
inline void displayString()
{
const std::string& s = textToBeFormatted;
for (int i = 0; i < s.length() / 40 + (bool)(s.length() % 40); ++i)
{
std::cout << std::left
<< std::setfill(' ')
<< std::setw(40)
<< s.substr(i * 40, 40)
<< std::endl;
}
}

Here is the answer suitable for me
#include <string>
#include <iostream>
#include <iomanip>
class StringProcessing
{
public:
StringProcessing() : characterWidth(40),
textToBeFormatted("NULL") {}
inline void initString() {
textToBeFormatted = "text some text some text some text some text some text"
"text some text some text some text some text some text"
"text some text some text some text some text some text"
"text some text some text some text some text some text"
"text some text some text some text some text some text";
}
inline void displayString()
{
const std::string& s = textToBeFormatted;
const int& width = characterWidth;
for (int current = 0; current < s.length();)
{
if (s.length() < width)
{
output(s);
break;
}
if (s.length() - current < width)
{
output(s.substr(current));
break;
}
std::string substr = s.substr(current, width);
current += width;
size_t space = substr.rfind(' ');
if (space != std::string::npos && (substr[width - 1] != ' ' &&
(s.length() > current && s[current] != ' ')))
{
current -= width - space - 1;
substr = substr.substr(0, space + 1);
}
output(substr);
}
}
private:
inline void output(const std::string& s)
{
std::cout << setfill(' ') << std::right << std::setw(characterWidth) << s << std::endl;
}
int characterWidth;
std::string textToBeFormatted;
};

Related

Find second to last word in a string C++

Hi I need to find second to last word in a string. Right now below program is printing the last one.
#include <iostream>
#include <string>
using namespace std;
int main() {
string text{"some line with text"};
// find last space, counting from backwards
int i = text.length() - 2; // last character
while (i != 0 && !isspace(text[i]))
{
--i;
}
string lastword = text.substr(i+1); // +1 to skip leading space
cout << lastword << endl;
return 0;
}
Output: (Printing last word)
text
You can split the string into words and hold the previous word before saving the current word.
#include <iostream>
#include <string>
#include <sstream>
int main() {
std::string text{"some line with text"};
std::stringstream ss(text);
std::string previousword, lastword, newword;
while (ss >> newword) {
previousword = lastword;
lastword = newword;
}
std::cout << previousword << std::endl;
return 0;
}
Also note that using using namespace std; is discouraged.
You don't need any loops. Just add error checking:
int main() {
std::string text{ "some line with text" };
std::size_t pos2 = text.rfind(' ');
std::size_t pos1 = text.rfind(' ', pos2-1);
std::cout << text.substr(pos1+1, pos2-pos1-1) << std::endl;
return 0;
}
Just keep counting spaces until you arrive to the word you want or use a stringstream as MikeCAT proposed.
Here there is a function that finds any last word number without having to copy the entire string in a stringstream:
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
string getNLastWord(string text, int n)
{
bool insideAWord = false;
int wordNum = 0;
int wordEnd = -1;
for(int i = text.size() - 1; i > 0; i--)
{
if(text[i] != ' ' && !insideAWord)
{
wordNum++;
insideAWord = true;
}
else if(text[i] == ' ')
{
insideAWord = false;
}
if(wordNum == n)
{
wordEnd = i;
break;
}
}
if(wordEnd == -1)
{
cout << "There are no " << n << " words from right." << endl;
}
else
{
int wordStart;
for(wordStart = wordEnd; wordStart > 0; wordStart--)
{
if(text[wordStart] == ' ')
{
wordStart++;
break;
}
}
return text.substr(wordStart,wordEnd+1-wordStart);
}
return "";
}
int main() {
string text = "some text";
cout << getNLastWord(text,2);
return 0;
}

How to compare two text files and find the similarities between then?

i have loaded both of my files into an array and im trying to compare both of the files to get the comparisons inside the file. However when I run my code I don't receive an output.
This is the contents of both files.
file1
tdogicatzhpigu
file2
dog
pig
cat
rat
fox
cow
So when it does a comparison between the words from search1.txt and the words from text1.txt. I want to find the occurence of each word from search1.txt in text1.txt
What I want to eventually output is whether it has been found the index of the location inside the array.
e.g
"dog". Found, location 1.
Here is my code
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream file1("text1.txt");
if (file1.is_open())
{
string myArray[1];
for (int i = 0; i < 1; i++)
{
file1 >> myArray[i];
any further help would be greatly appreciated. Thanks in advance.
I believe the goal is to search the text in file1 for each word in file2.
You can't use equality for the two strings, as they aren't equal. You'll need to use the std::string::find method:
std::string target_string;
std::getline(file1, target_string);
std::string keyword;
while (getline(file2, keyword))
{
const std::string::size_type position = target_string.find(keyword);
std::cout << "string " << keyword << " ";
if (position == std::string::npos)
{
std::cout << "not found.\n";
}
else
{
std::cout << "found at position " << position << "\n";
}
}
Edit 1:
An implemented example:
#include <iostream>
#include <string>
using std::cout;
using std::string;
using std::endl;
int main()
{
const std::string target_string = "tdogicatzhpigu";
const std::string key_list[] =
{
"dog",
"pig",
"cat",
"rat",
"fox",
"cow",
};
static const unsigned int key_quantity =
sizeof(key_list) / sizeof(key_list[0]);
for (unsigned int i = 0; i < key_quantity; ++i)
{
const std::string::size_type position = target_string.find(key_list[i]);
std::cout << "string " << key_list[i] << " ";
if (position == std::string::npos)
{
std::cout << "not found.\n";
}
else
{
std::cout << "found at position " << position << "\n";
}
}
return 0;
}

How to create a 0x appended hex string from a hex string for each byte of hex characters in C++?

Trying to convert my following go code question
How to create a 0x appended hex string from a hex string for each byte of hex characters in golang?
to C++ - but completely lost.
#include <iostream>
#include <string>
using namespace std;
// Function to append 0x
void appendX(string str)
{
// Appends 1 occurrences of "X" to str
str.append(1, 'X');
cout << "Modified append() : ";
cout << str;
}
int main()
{
string str("01234567891011121314151617181920");
cout << "String : " << str << endl;
appendX(str);
return 0;
}
Your function appendX() is going to append only one 'X' at the end of your input string, as your comment also says.
But if you are trying to append "0x" after every hex byte within your string, (as asked in the GO language question you mentioned), you should be appending "0x" after every 2 characters in your input string. Try below:
void appendX(String str)
{
String outstr;
for(int i=0;i<str.size();i=i+2)
{
outstr.append("0x");
outstr.append(str,i,2);
}
cout << "Modified append() : ";
cout << outstr;
}
Simplest/Understandable way is to iterate over a string and add the desirable amount of characters to a result string.
std::string insertStringInto(const std::string& s, const int interval, const std::string& sep_str)
{
std::string result_str;
auto chars_count_until_sep = interval;
for (auto ch: s)
{
if (chars_count_until_sep == 0)
{
result_str += sep_str;
chars_count_until_sep = interval;
}
result_str += ch;
--chars_count_until_sep;
}
return result_str;
}
int main()
{
std::string str("01234567891011121314151617181920");
std::cout << "String : " << insertStringInto(str,2,", 0x") << std::endl;
return 0;
}
Using the Ranges V3 library (in the future all these functions should be available in the C++ standard library):
std::string insertStringInto(const std::string& in_string, const int interval, const std::string& sep_str)
{
using namespace ranges::views;
auto concat_to_str = [](auto grp) { // auxilllary function to concat single characters into a string
return ranges::accumulate(grp, std::string {});
};
auto r = in_string // Use the characters from the input string parameter
| chunk(interval) // Split string up into interval count of characters
| transform(concat_to_str) // combine characters from chunks into strings
| intersperse(sep_str); // intersperse between the chunks the separator text
return concat_to_str(r); // concat all the strings into 1 string
}
int main()
{
std::string str("01234567891011121314151617181920");
std::cout << "String : " << insertStringInto(str, 2, ", 0x") << std::endl;
return 0;
}

How to convert hex representation from URL (%) to std::string (chinese text)?

Intro
I have some input that I need to convert to the correct Chinese characters but I think I'm stuck at the final number to string conversion. I have checked using this hex to text converter online tool that e6b9af corresponds to the text 湯.
MWE
Here is a minimal example that I made to illustrate the problem. The input is "%e6%b9%af" (obtained from an URL somewhere else).
#include <iostream>
#include <string>
std::string attempt(std::string path)
{
std::size_t i = path.find("%");
while (i != std::string::npos)
{
std::string sub = path.substr(i, 9);
sub.erase(i + 6, 1);
sub.erase(i + 3, 1);
sub.erase(i, 1);
std::size_t s = std::stoul(sub, nullptr, 16);
path.replace(i, 9, std::to_string(s));
i = path.find("%");
}
return path;
}
int main()
{
std::string input = "%E6%B9%AF";
std::string goal = "湯";
// convert input to goal
input = attempt(input);
std::cout << goal << " and " << input << (input == goal ? " are the same" : " are not the same") << std::endl;
return 0;
}
Output
湯 and 15120815 are not the same
Expected output
湯 and 湯 are the same
Additional question
Are all characters in foreign languages represented in 3 bytes or is that just for Chinese? Since my attempt assumes blocks of 3 bytes, is that a good assumption?
Based on your suggestions and changing an example from this other post. This is what I came up with.
#include <iostream>
#include <string>
#include <sstream>
std::string decode_url(const std::string& path)
{
std::stringstream decoded;
for (std::size_t i = 0; i < path.size(); i++)
{
if (path[i] != '%')
{
if (path[i] == '+')
decoded << ' ';
else
decoded << path[i];
}
else
{
unsigned int j;
sscanf(path.substr(i + 1, 2).c_str(), "%x", &j);
decoded << static_cast<char>(j);
i += 2;
}
}
return decoded.str();
}
int main()
{
std::string input = "%E6%B9%AF";
std::string goal = "湯";
// convert input to goal
input = decode_url(input);
std::cout << goal << " and " << input << (input == goal ? " are the same" : " are not the same") << std::endl;
return 0;
}
Output
湯 and 湯 are the same

How to read in one file and display content vertically and then read in another file and display content vertically in c++

Hi I'm working on a program that reads in two files and i want to display the files content in their own columns for ex.
File1 File2
Time data Time data
I'm not quit sure how to create columns as such, I already have the code to read in the files and perform the functions needed its the output I'm stumped on. If anyone has any suggestions or help that would be awesome. Thanks! PS. This is NOT Homework Related.
I would do something like this:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <string>
using namespace std;
int readLines(const std::string& fileName1, const std::string& fileName2)
{
string line1;
string line2;
ifstream file1 (fileName1.c_str());
ifstream file2 (fileName2.c_str());
if (file1.is_open() && file2.is_open())
{
cout << setw(20) << left << "File1" << "File2" << endl;
bool done;
done = file1.eof() && file2.eof();
while (!done)
{
getline (file1, line1);
getline (file2, line2);
line1.erase(std::remove(line1.begin(), line1.end(), '\n'), line1.end());
line2.erase(std::remove(line2.begin(), line2.end(), '\n'), line2.end());
cout << setw(20) << left << (file1.eof() ? "" : line1) << (file2.eof() ? "" : line2) << endl;
done = file1.eof() && file2.eof();
}
file1.close();
file2.close();
}
else
{
cout << "Unable to open some file";
}
return 0;
}
int main ()
{
std::string fileName1("example1.txt");
std::string fileName2("example2.txt");
readLines(fileName1, fileName2);
return 0;
}
It really depends on what tools you are planning to use...
You can use some version of "curses" (a library with console manipulation functions such as "go to this position", "print text in green", etc), and then just walk around the screen as you like.
Or you could just read the files into separate variables and then print from each file in a loop. This requires no special codding. Just use an array or vector for the files themselves and the data you read from them.
Something like this:
const int nfiles = 2;
const char *filenames[nfiles] = { "file1.txt", "file2.txt" };
ifstream files[nfiles];
for(int i = 0; i < nfiles; i++)
{
if (!files[i].open(filenames[i]))
{
cerr << "Couldn't open file " << filenames[i] << endl;
exit(1);
}
}
bool done = false;
while(!done)
{
int errs = 0;
std::string data[nfiles];
for(int i = i < nfiles; i++)
{
if (!(files[i] >> data[i]))
{
errs++;
data[i] = "No data";
}
}
if (errs == nfiles)
{
done = true;
}
else
{
for(int i = 0; i < nfiles; i++)
{
... display data here ...
}
}
}