Unexpected results when using std::stringstream - c++

I am a beginner in C++, started last week. I am trying to make a simple program converting a number of inches to foot inch notation: E.g. 62 turns into 5'2". However when I try to compile I have some error in line 8. I don't know what it is. Thanks in advance.
#include <iostream>
#include <sstream>
using namespace std;
string ConvertToFootInchMeasure (int totalInches){
string feet = ""+totalInches/12;
string inches = "" + totalInches%12;
stringstream converted;
conveted<<feet;
converted<<"'";
converted<<inches;
converted<<"\"";
return converted.str();
}

That code can be easily fixed like this:
string ConvertToFootInchMeasure (int totalInches){
stringstream converted;
// Do inline calculations and use formatted text output for the results
converted << (totalInches/12) << "'" << (totalInches%12) << "\"";
return converted.str();
}
To explain further: You tried to concatenate the numeric results of the totalInches/12 and totalInches%12 operations to a std::string variable, but the right side of the statement doesn't do that.
Note:
std::string operator+(std::string, char c) doesn't do conversion of numerics to string and concatenation as you tried to use with:
string feet = ""+totalInches/12;
also it seems to be even worse in your case because the term
""+totalInches/12
does pointer arithmetics for a const char* pointer, and the string variable is initialized from e.g. a pointer address "" + (62/12).

Related

Proper way to convert HEX to ASCII read from a file C++

In my code bellow CODE 1 reading HEX from a file and storing in in string array won't convert it to ASCII when printed out.
#include <iostream>
#include <sstream>
#include <fstream>
int main(int argc, char** argv)
{
// CODE 1
std::ifstream input("C:\\test.txt"); // The test.txt contains \x48\x83\xEC\x28\x48\x83
std::stringstream sstr;
input >> sstr.rdbuf();
std::string test = sstr.str();
std::cout << "\nString from file: " << test;
//char* lol = new char[test.size()];
//memcpy(lol, test.data(), test.size());
////////////////////////////////////////////////////////
// CODE 2
std::string test_2 = "\x48\x83\xEC\x28\x48\x83";
std::cout << "\n\nHardcoded string: " << test_2 << "\n";
// Prints as ASCII "H(H" , which I want my CODE 1 to do.
}
In my CODE 2 sample, same HEX is used and it prints it as ASCII. Why is it not the same for CODE 1?
Okay, it looks like there is some confusion. First, I have to ask if you're SURE you know what is in your file.
That is, does it contain, oh, it looks like about 20 characters:
\
x
4
8
et cetera?
Or does it contain a hex 48 (one byte), a hex 83 (one byte), for a total of 5-ish characters?
I bet it's the first. I bet your file is about 20 characters long and literally contains the string that's getting printed.
And if so, then the code is doing what you expect. It's reading a line of text and writing it back out. If you want it to actually interpret it like the compiler does, then you're going to have to do the steps yourself.
Now, if it actually contains the hex characters (but I bet it doesn't), then that's a little different problem, and we'll have to look at that. But I think you just have a string of characters that includes \x in it. And reading / writing that isn't going to automatically do some magic for you.
When you read from file, the backslash characters are not escaped. Your test string from file is literally an array of chars: {'\\', 'x', '4', '8', ... }
Whereas your hardcoded literal string, "\x48\x83\xEC\x28\x48\x83"; is fully hex escaped by the compiler.
If you really want to store your data as a text file as a series of "backslash x NN" sequences, you'll need to convert after you read from file. Here's a hacked up loop that would do it for you.
std::string test = sstr.str();
char temp[3] = {};
size_t t = 0;
std::string corrected;
for (char c : test)
{
if (isxdigit(c))
{
temp[t] = c;
t++;
if (t == 2)
{
t = 0;
unsigned char uc = (unsigned char)strtoul(tmp, nullptr, 16);
corrected += (char)uc;
}
}
}
You can split the returned string in \x then make casting from string to int,
finally casting to char.
this resource will be helpful
strtok And convert

Concatenate float with string and round to 2 decimal places

So I have a function below formatted as polymorphic void display(string& outStr). The output from this function should basically be formatted into one large string, which will be saved to the outStr parameter and returned to the calling function.
I have successfully formatted my large string into multiple lines but I would like to round my float value to 2 decimal places but I can't figure out how with the way I'm currently appending my strings. I tried using the round() and ceil() functions as some posts online have suggested, but 6 zeros still appear after each decimal place. I would appreciate some help with this as I've been looking for solutions for a while but none of them have worked.
Additionally, I was wondering if the to_string() function I used to convert my float to a string would compile and execute correctly in C++98? I'm using C++11 but my teacher is using C++98 and I'm extremely worried that it won't compile on her end.
If not, can anyone suggest how else I could achieve the same result of turning a float into a string while still formatting multiple lines into the outStr string parameter and returning it to the function? I am not allowed to change the function's parameters, it must stay as display(string& outStr)
My output is a lot longer and complex but I simplified the example for the sake of getting a short and easy solution.
Again, I would appreciate any help!
#include <iostream>
using namespace std;
#include <string>
#include <sstream>
#include <cmath>
#include "Math.h"
void Math::display(string& outStr){
float numOne = 35;
float numTwo = 33;
string hello = "Hello, your percent is: \n";
outStr.append(hello);
string percent = "Percent: \n";
outStr.append(percent);
float numPercent = ceil(((numOne / numTwo) * 100) * 100.0) / 100.0;
outStr.append(to_string(numPercent));
outStr.append("\n");
}
Output should look like:
Hello, your percent is:
Number:
106.06%
There is no need to do any crazy conversions. Since the function is called display, my guess is that it's actually supposed to display the value instead of just save it to a string.
The following code demonstrates how that can be accomplished by just formatting your printing.
#include <cstdio>
#include <iomanip>
#include <iostream>
int main() {
double percentage = 83.1415926;
std::cout << "Raw: " << percentage << "%\n";
std::cout << "cout: " << std::fixed << std::setprecision(2) << percentage << "%\n";
printf("printf: %.2f\%%\n", percentage); // double up % to print the actual symbol
}
Output is:
Raw: 83.1416%
cout: 83.14%
printf: 83.14%
If the function is as backwards as you describe it, there are two possibilities. You don't understand what's actually required and are giving us a bad explanation (my guess given that function signature), or the assignment itself is pure garbage. As much as SO likes to rag on professors, I find it difficult to believe that what you've described and written is what the professor wants. It makes no sense.
A couple notes: there is nothing polymorhpic about the code you've shown. to_string() exists as of C++11, which is easily seen by looking up the function (Link). There is also a discrepancy between what your code attempts to print versus what your output is, and that's before we even get to the number formatting portion. "Percent" or "Number"?

In c++, how do you get the input of a string, float and integer from 1 line?

An input file is entered with the following data:
Juan Dela Cruz 150.50 5
'Juan Dela Cruz' is a name that I would like to assign to string A,
'150.50' is a number I would like to assign to float B
and 5 is a number I would like to assign to int C.
If I try cin, it is delimited by the spaces in between.
If I use getline, it's getting the whole line as a string.
What would be the correct syntax for this?
If we analyze the string, then we can make the following observation. At the very end, we have an integer. In front of the integer we have a space. And in front of that the float value. And again in fron of that a space.
So, we can simply look from the back of the string for the 2nd last space. This can easily be achieved by
size_t position = lineFromeFile.rfind(' ', lineFromeFile.rfind(' ')-1);
We need a nested statement of rfind please see here, version no 3.
Then we build a substring with the name. From start of the string up to the found position.
For the numbers, we put the rest of the original string into an std::istringstream and then simply extract from there.
Please see the following simple code, which has just a few lines of code.
#include <iostream>
#include <string>
#include <cctype>
#include <sstream>
int main() {
// This is the string that we read via getline or whatever
std::string lineFromeFile("Juan Dela Cruz 150.50 5");
// Let's search for the 2nd last space
size_t position = lineFromeFile.rfind(' ', lineFromeFile.rfind(' ')-1);
// Get the name as a substring from the original string
std::string name = lineFromeFile.substr(0, position);
// Put the numbers in a istringstream for better extraction
std::istringstream iss(lineFromeFile.substr(position));
// Get the rest of the values
float fValue;
int iValue;
iss >> fValue >> iValue;
// Show result to use
std::cout << "\nName:\t" << name << "\nFloat:\t" << fValue << "\nInt:\t" << iValue << '\n';
return 0;
}
Probably simplest in this case would be to read whole line into string and then parse it with regex:
const std::regex reg("\\s*(\\S.*)\\s+(\\d+(\\.\\d+)?)\\s+(\\d+)\\s*");
std::smatch match;
if (std::regex_match( input, match, reg)) {
auto A = match[1];
auto B = std::stof( match[2] );
auto C = std::stoi( match[4] );
} else {
// error invalid format
}
Live example
As always when the input does not (or sometimes does not) match a strict enough syntax, read the whole line and then apply the rules which to a human are "obvious".
In this case (quoting comment by john):
Read the whole string as a single line. Then analyze the string to work out where the breaks are between A, B and C. Then convert each part to the type you require.
Specifically, you probably want to use reverse searching functions (e.g. https://en.cppreference.com/w/cpp/string/byte/strrchr ), because the last parts of the input seem the most strictly formatted, i.e. easiest to parse. The rest is then the unpredictable part at the start.
either try inputting the different data type in different lines and then use line breaks to input different data types or use the distinction to differentiate different data types like adding a . or comma
use the same symbol after each data package, for example, Juan Dela Cruz;150.50;5 then you can check for a ; and separate your string there.
If you want to use the same input format you could use digits as an indicator to separate them

Bit manipulation on character string

Can we apply bit manipulation on a character string?
If so, is it always possible to retrieve back a character string from the manipulated string?
I was hoping to use the XOR operator on two strings by converting them to binary and then back to character string.
I took up some code from another StackOverflow question but it only solves half the problem
std::string TextToBinaryString(string words)
{
string binaryString = "";
for (char& _char : words)
{
binaryString +=std::bitset<8>(_char).to_string();
}
return binaryString;
}
I don't know how to convert this string of ones and zeroes back to a string of characters.
I did read std::stio in some google search results as a solution but was not able to understand them.
The manipulation that I wish to do is
std::string message("Hello World");
int n = message.size();
bin_string = TextToBinaryString(message)
std::string left,right;
bin_string.copy(left,n/2,0);
bin_string.copy(right,n,n/2);
std::string result = left^right;
I know I can hardcode this by picking up every entry and applying the operation but it is the conversion of the binary string back to characters that are making me scratch my head.
*EDIT: *I am trying to implement a cipher framework called Feistel cipher (SORRY, should had made that clear before) there they use the property of XOR that when you XOR something with the same thing again it cancels out... For eg. (A^B)^B=A. I wanted to output the ciphered jibberish in the middle. Hence, the query.
Can we apply bit manipulation on a character string?
Yes.
A character is an integer type, so you can do anything to them you can do to any other integer. What happened when you tried?
If so, is it always possible to retrieve back a character string from the manipulated string?
No. It is sometimes possible to recover the original string, but some manipulations are not reversible.
XOR, the particular operation you asked about, is self-reversing, so it works in that case but not in general.
A cheesy example (depends on ASCII character set, don't do this in real code for converting case, etc. etc.)
#include <iostream>
#include <string>
int main() {
std::string s("a");
std::cout << "original: " << s << '\n';
s[0] ^= 0x20;
std::cout << "modified: " << s << '\n';
s[0] ^= 0x20;
std::cout << "restored: " << s << '\n';
}
shows (on an ASCII-compatible) system
original: a
modified: A
restored: a
Note that I'm not converting "a" into "1100001" first, and then using XOR (somehow) zero bit 5 giving "1000001" and then converting that back into "A". Why would I?
This part of your question suggests you don't understand the difference between values and representations: the character is always stored in binary. You can also always treat it as if it is stored in octal, or in decimal, or in hexadecimal - the choice of base only affects how we write (or print) the value, and not what the value is in itself.
Writing a Feistel cipher where the plaintext and key are the same length is trivial:
std::string feistel(std::string const &text, std::string const &key)
{
std::string result;
std::transform(text.begin(), text.end(), key.begin(),
std::back_inserter(result),
[](char a, char b) { return a^b; }
);
return result;
}
This doesn't work at all if the key is shorter, though - looping round the key appropriately is left as an exercise for the reader.
Oh, and printing the encoded string is unlikely to work nicely (unless your key is helpfully just a sequence of space characters, as above).
You probably want something like this:
#include<string>
#include<cassert>
using namespace std;
std::string someBitmanipulation(string words)
{
std::string manipulatedstring;
for (char& thechar : words)
{
thechar ^= 0x5A; // xor with 0x5A
}
return manipulatedstring;
}
int main()
{
std::string original{ "ABC" };
// xor each char of original with 0x5a at put result into manipulated
auto manipulated = someBitmanipulation(original);
// check if manipulating the manipulated string is the same as the original string
assert(original == someBitmanipulation(manipulated));
}
You don't need std::bitset at all.
Now change thechar ^= 0x5A; to say thechar |= 0x5A; and see what happens.

C++, best way to change a string at a particular index

I want to change a C++ string at a particular index like this:
string s = "abc";
s[1] = 'a';
Is the following code valid? Is this an acceptable way to do this?
I didn't find any reference which says it is valid:
http://www.cplusplus.com/reference/string/string/
Which says that through "overloaded [] operator in string" we can perform the write operation.
Assigning a character to an std::string at an index will produce the correct result, for example:
#include <iostream>
int main() {
std::string s = "abc";
s[1] = 'a';
std::cout << s;
}
For those of you below doubting my IDE/library setup, see jdoodle demo: http://jdoodle.com/ia/ljR, and screenshot: https://imgur.com/f21rA5R
Which prints aac. The drawback is you risk accidentally writing to un-assigned memory if string s is blankstring or you write too far. C++ will gladly write off the end of the string, and that causes undefined behavior.
A safer way to do this would be to use string::replace: http://cplusplus.com/reference/string/string/replace
For example
#include <iostream>
int main() {
std::string s = "What kind of king do you think you'll be?";
std::string s2 = "A good king?";
// pos len str_repl
s.replace(40, 1, s2);
std::cout << s;
//prints: What kind of king do you think you'll beA good king?
}
The replace function takes the string s, and at position 40, replaced one character, a questionmark, with the string s2. If the string is blank or you assign something out of bounds, then there's no undefined behavior.
Yes. The website you link has a page about it. You can also use at function, which performs bounds checking.
http://www.cplusplus.com/reference/string/string/operator%5B%5D/
Yes the code you have written is valid. You can also try:
string num;
cin>>num;
num.at(1)='a';
cout<<num;
**Input**:asdf
**Output**:aadf
the std::replace can also be used to replace the charecter. Here is the reference link http://www.cplusplus.com/reference/string/string/replace/
Hope this helps.
You could use substring to achieve this
string s = "abc";
string new_s = s.substr(0,1) + "a" + s.substr(2);
cout << new_s;
//you can now use new_s as the variable to use with "aac"