My code parses an integer into parts and writes them to an array, but now I want to collect the array back into an integer.
I will modify the data inside the array so I need to collect everything back after the changes.
int a = 123456789;
std::string stringInt = std::to_string(a);
std::vector<int> numbers;
numbers.reserve(stringInt.length());
for (const auto& chr : stringInt)
{
// ...
numbers.push_back(chr - '0');
cout << chr << "\n" << endl;
}
You can add up the integers, multiplying the result by 10 every time:
int b = 0;
for (const auto& chr : stringInt)
{
numbers.push_back(chr - '0');
b *= 10;
b += chr - '0';
}
std::cout << b << std::endl;
Alternatively you can put the chars into a string instead of turning them into int and putting them into a vector and then use std::stoi to get an int back out of the string:
std::string numbers;
for (const auto& chr : stringInt)
{
numbers.push_back(chr);
cout << chr << "\n" << endl;
}
int b = std::stoi(numbers);
std::cout << b << std::endl;
Related
I am running a C++ program to sort strings as numbers.
I am saving strings in a char array vector but want to sort numbers as numbers so I am converting number strings into long doubles by calling "tonum()" then converting them back to strings when I am done by calling "tostring()". I am calling "numstr()" strictly for readability and debugging. I convert numbers 0 through 7 and the 6th number across for each value changes every time I run it. In my actual program, the first 5 numbers also seem to change. How do I get consistent results for a long double so that I can properly sort long doubles in char arrays?
#include<iostream>
std::string::size_type sz;
//___________________________________________________
std::string tonum(std::string str)
{
const int len = sizeof(long double);
std::string out = "0000000000000000";
union
{
long double dbl;
char array[len];
};
try
{
dbl = stold(str);
}
catch(std::exception &err)
{
dbl = 0;
}
for (int i = 0; i < len; i++)
{
std::cout << (int)array[i] << "\n";
out[len-i-1] = array[i];
}
return(out);
}
//___________________________________________________
std::string fromnum(std::string str)
{
const int len = sizeof(long double);
std::string out = "";
union
{
long double dbl;
char array[len];
};
for (int i = 0; i < len; i++)
{
array[len-i-1] = str[i];
}
out = std::to_string(dbl);
return(out);
}
//_____________________________________________________
std::string numstr(std::string str)
{
std::string out = fromnum(str) + ":";
for (int i = 0; i < str.length(); i++)
{
std::string look = std::to_string(str[i]);
int lookint = stold(look,&sz);
if (lookint < 0) lookint += 256;
std::string look2 = std::to_string(lookint);
out += look2 + " ";
}
return(out);
}
//_____________________________________________________
int main()
{
std::cout << numstr(tonum("0")) << "\n";
std::cout << numstr(tonum("1")) << "\n";
std::cout << numstr(tonum("2")) << "\n";
std::cout << numstr(tonum("3")) << "\n";
std::cout << numstr(tonum("4")) << "\n";
std::cout << numstr(tonum("5")) << "\n";
std::cout << numstr(tonum("6")) << "\n";
std::cout << numstr(tonum("7")) << "\n";
}
//_____________________________________________________
This question already has answers here:
cout << order of call to functions it prints?
(3 answers)
Closed 2 years ago.
#include <iostream>
using namespace std;
int output_1(string s, char c);
int output_2(string s, char c);
int main() {
string str;
char c;
cout << "Enter a string: ";
getline(cin, str);
cout << "Enter a character: ";
cin >> c;
cout << "[1] the number of times the character appears: " << output_1(str, c) << endl;
cout << "[2] That character is found at Index/Indices: " << output_2(str, c) << endl;
return 0;
}
int output_1(string s, char c) {
int count = 0;
for (int x = 0; x < s.length(); x++)
if (s[x] == c)
count++;
return count;
}
int output_2(string s, char c) {
for (int x = 0; x < s.length(); x++) {
if (c == s[x]){
cout << x << " ";
}
}
}
Why is the second output not in order and have an extra 0 at the end?
Enter a string: test
Enter a character: t
[1] the number of times the character appears: 2
0 3 [2] That character is found at Index/Indices: 0
The problem is this line:
cout << "[2] That character is found at Index/Indices: " << output_2(str, c) << endl;
The first thing to note is that << is just syntactic sugar for a function call. So we can re-write it to look like this:
cout.op<<("[2] That character is found at Index/Indices: ")
.op<<(output_2(str, c))
.op<<(endl);
Because they are chained statements you can think of this as:
std::ostream& t1 = cout.op<<("[2] That character is found at Index/Indices: ");
std::ostream& t2 = t1.op<<(output_2(str, c));
std::ostream& t3 = t2.op<<(endl);
So what we have are three method calls to op<<() each passing one parameter. Before calling these methods that the compiler must get the operands to the calls. The first one is easy as it is a literal string, the second one requires a function call. So the compiler must call the function output_2() before it can call op<<() and the third one is an function (easy to pass the address).
But the compiler can sequence that call to output_2() at any point (as long as it happens before the call to op<<(). So it looks the compiler is doing this:
<Seq Start>
void& x = output_2(str, c); // yes I know thats not legal C++ just for explaining.
std::ostream& t1 = cout.op<<("[2] That character is found at Index/Indices: ");
std::ostream& t2 = t1.op<<(x);
std::ostream& t3 = t2.op<<(endl);
<Seq End>
Note: The compiler could place the call anywhere between <Seq Start> and <Seq End> (before it is needed) it's just an implementation detail. Now the call to output_2() also actually outputs to the std::cout followed by a int (which is not returned (undefined behavior by itself)).
Instead of printing value in main, Try this :
//call this from main
output_1(str, c);
output_2(str, c);
Then:
void output_1(string s, char c) {
int count = 0;
for (int x = 0; x < s.length(); x++)
if (s[x] == c)
count++;
cout<< count<<endl;
}
void output_2(string s, char c) {
for (int x = 0; x < s.length(); x++) {
if (c == s[x]){
cout << x << " ";
}
}
}
This is UB. output_2 should return an int, but doesn't return anything. Now you get a 0, but it could be anything.
As you're building op an ostream in output_2, you could use a stringstream internally and convert that to a string for the output.
#include<string>
#include<iostream>
#include<algorithm>
#include<sstream>
int output_1(std::string const& s, char c) {
return std::count(cbegin(s), cend(s), c);
}
std::string output_2(std::string const& s, char c) {
std::stringstream os;
for (int x = 0; x < s.length(); ++x) {
if (c == s[x]){
os << x << " ";
}
}
return os.str();
}
int main() {
std::string str = "test";
char c = 't';
std::cout << "[1] the number of times the character appears: " << output_1(str, c) << '\n';
std::cout << "[2] That character is found at Index/Indices: " << output_2(str, c) << '\n';
}
You issue is that output_2 lies. The return type of int says the function returns a value. There is no return statement, so there is undefined behavior.
My suggested solution:
void output_2(string s, char c)
{
for (int x = 0; x < s.length(); x++)
{
if (c == s[x])
{
cout << x << " ";
}
}
}
int main()
{
//...
cout << "[1] the number of times the character appears: " << output_1(str, c) << endl;
cout << "[2] That character is found at Index/Indices: ";
output_2(str, c);
cout << endl;
return 0;
}
In the above code fragments, the return type of output_2 is set to void since it doesn't return a value.
In the main function, the output_2() is removed from the cout statement (since output_2() doesn't return a value), and set as a separate function call.
Running through output_2():
int output_2(string s, char c) {
for (int x = 0; x < s.length(); x++) {
if (c == s[x]){
cout << x << " ";
}
}
}
First pass (t) prints 0.
Second pass (e) prints nothing.
Third pass (s) prints nothing
Fourth pass (t) prints 3
You wrote output_2() as returning int, but actually you should be returning an array of integers and printing those (or something similar). The return value of a function that is supposed to return an int but has no return line is undefined. The behaviour of the whole program is also undefined because of this missing return statement. Anyway, in your specific case, it looks like output_2() returned 0 and so finally after control was returned to main it printed
cout << "[2] That character is found at Index/Indices: " << output_2(str, c) << endl;
where output_2(str, c) prints a zero (in an undefined manner). I think one thing that you were missing (with respect to order) is that the line
cout << "[2] That character is found at Index/Indices: " << output_2(str, c) << endl;
first allows output_2() to print 0 and 3 and then starts to print this line.
I'm trying to access a vector in c++, but it throws subscript out of range
string s = "itwqbtcdprfsuprkrjkausiterybzncbmdvkgljxuekizvaivszowqtmrttiihervpncztuoljftlxybpgwnjb";
vector<int> result(s.size());
result.resize(s.size());
for (int i = 0; i < s.size(); i++)
{
int d = s[i];
result[d]++;
}
Not sure what you want with int d = s[i];, but d would be something like 'i' which is unrelated to result.size().
'i' is basically 105 in ASCII.
You probably want a map
const std::string s =
"itwqbtcdprfsuprkrjkausiterybzncbmdvkgljxuekizvaivszowqtmrttiihervpncztuoljftlxybpgwnjb";
std::map<char, std::size_t> result;
for (char c : s)
{
result[c]++;
}
for (const auto& p : result) {
std::cout << "letter " << p.first << " appears " << p.second << "times\n";
}
If you want keep your vector, you may do something like:
const std::string s =
"itwqbtcdprfsuprkrjkausiterybzncbmdvkgljxuekizvaivszowqtmrttiihervpncztuoljftlxybpgwnjb";
std::vector<std::size_t> result(26);
for (char c : s) {
if ('a' <= c && c <= 'z') {
result[c - 'a']++;
}
}
for (std::size_t i = 0; i != result.size(); ++i) {
std::cout << "letter " << char('a' + ) << " appears " << result[i] << "times\n";
}
Simply put, s.size () is the wrong value to resize result with. I would try something like
vector<int> result(CHAR_MAX, 0);
and remove the call to resize, which is not so much redundant as it is actively pernicious.
I have two groups (A) and (B) and a amount of variables abcde... (>2) to sort into the groups, that at least one variable is in group (A) and one is in group (B). The programm should print out all combinations. The order of the output is not important.
For 3 variables "abc" The result should be:
A | B
-------
ac | b
ab | c
bc | a
a | bc
b | ac
c | ab
The programm I wrote is:
#include <string>
#include <stdio.h>
using namespace std;
string gencombinations(string , string );
string removeCharsFromString( string , string);
int main(){
string result;
string a = "";
string b = "";
string batch = "abc";
a = batch;
cout << "batch \ta = {"; cout << a; cout << "},\t batch b = {"; cout << b; cout << "}\t"; cout << endl;
result = gencombinations(a, b);
//cout << result << endl;
return 0;
}
string gencombinations(string a, string b){
string _tmp;
string _tmp2;
for(int i = 0; i < a.size(); i++ ) {
_tmp = a.at(i+1);
b = _tmp+b;
cout << "remove \t {"; cout << _tmp; cout << "},\t\t from a = {"; cout << a; cout << "}\t"; cout << endl;
a= removeCharsFromString( a, _tmp );
cout << "batch \ta = {"; cout << a; cout << "},\t batch b = {"; cout << b; cout << "}\t"; cout << endl;
if(a.size() > 1)
_tmp2 = gencombinations(a, b);
if(_tmp2 != "") return _tmp2;
b = removeCharsFromString( b, _tmp );
}
return _tmp2;
}
string removeCharsFromString( string str, string charsToRemove ) {
for (int i = 0; i < charsToRemove.length(); ++i ) {
//cout << "charsToRemove = {"; cout << charsToRemove.at(i); cout << "},\t From String = {"; cout << str; cout << "}\t"; cout << endl;
std::string::size_type s = str.find(charsToRemove.at(i));
if (s != std::string::npos)
str.erase(i+1, 1);
}
return str;
}
Which gives the output:
batch a = {abc}, batch b = {}
remove {b}, from a = {abc}
batch a = {ac}, batch b = {b}
remove {c}, from a = {ac}
batch a = {a}, batch b = {cb}
and breaks. (That there is no Variable in batch B in the beginning is no problem).
Getting rid of out_of_range (answer from #Paul) I get:
string gencombinations(string a, string b){
string _tmp;
string _tmp2;
string _resul;
for(int i = 0; i < a.size(); i++ ) {
_tmp = a.at(i);
b = _tmp+b;
if(a.size() > 1)
a= removeCharsFromString( a, _tmp );
cout << "batch \ta = {"; cout << a; cout << "},\t batch b = {"; cout << b; cout << "}\t"; cout << endl;
if(a.size() > 1){
cout << "recursion" << endl;
_tmp2 = gencombinations(a, b);
}
if(_tmp2 != "") {
return _tmp2;
cout << "_tmp2 is empty" << endl;
}
b = removeCharsFromString( b, _tmp );
a = _tmp;
}
return _tmp2;
}
string removeCharsFromString( string str, string charsToRemove ){
for (int i = 0; i < charsToRemove.length(); ++i ) {
std::string::size_type s = str.find(charsToRemove.at(i));
if (s != std::string::npos)
str.erase(i, 1);
}
return str;
}
With the output:
batch a = {bcd}, batch b = {a}
recursion
batch a = {cd}, batch b = {ba}
recursion
batch a = {d}, batch b = {cba}
How to get the recursion right?
This line:
for(int i = 0; i < a.size(); i++ ) {
_tmp = a.at(i+1);
contains a logic mistake. Strings are 0-based in c++, like any other type of array or vector. At some point the code tries to read the first char after the end of the string from the array. At that point the program will throw an out_of_range-exception (just wrap that line with a try-catch to watch it yourself).
As for your code: I don't quite understand the purpose of tmp2. There's no line in the code where tmp2 is explicitly created, so it's always "", independent of the input.
But there are actually simpler solutions to this than moving each character at an arbitrary time from a to b, which will always produce duplicates aswell. Instead you could use one of these simplifications:
Using a permutation of 0s and 1s
Use a permutation of 0s and 1s, where 0 means put the char in a and 1 means put the char in b:
void gencombinations(string allchars){
for(unsigned int permute = 0 ; permute < (1 << allchars.size()) ; permute++){
string a, b;
for(unsigned int bit = 0 ; bit < allchars.size() ; bit++)
if(permute & (1 << bit))
a += allchars[bit];
else
b += allchars[bit];
cout << "batch: a = {" + a + "}, b: {" + b + "}" << endl;
}
}
Note that this solution only works for input-strings of a specific size. The bitcount of permute determines the maximum-length of the input-string. E.g. datatypes with 32 bits would allow input-strings of a maximum-length of 32. For input-alphabets that are larger than 64, a workaround to this basic solution is required.
Using recursive calls and distribution
Use recursive method-calls and fork, where one call adds the char to a and one to b:
gencombinations(string chars , string a , string b){
if(chars.size()){
char c = chars[0];
chars.erase(0 , 1);
gencombinations(chars , a + c , b);
gencombinations(chars , a , b + c);
}else
cout << "batch: a = {" + a + "}, b = {" + b + "}";
}
You don't have to remove anything. Just keep building your group strings a and b from the batch until the batch has been exausted.
Of course, you must consider two cases for each letter from the batch: It goes either into group A or into group B. When you recurse, you must fork your recursion for each of these cases. You must also remove the current letter from the batch, but that is easy, because it is the first letter in the string:
#include <string>
#include <iostream>
using namespace std;
void combo(string batch, string a, string b)
{
if (batch.size() == 0) {
if (a.size() && b.size()) {
cout << a << " :: " << b << "\n";
}
} else {
combo(batch.substr(1), a + batch[0], b);
combo(batch.substr(1), a, b + batch[0]);
}
}
int main()
{
combo("abc", "", "");
return 0;
}
This solution just prints the strings at the bottom level of the recursion. You could as well append them to a string stream or string.
cout<<"Set B : {";
for(i=0;i<b;i++)
{
cout<<setB[i];
cout<<",";
}
cout<<" }"<<endl;
The code above is not printing correctly. It should print Set B : {1,2,3} but it prints an extra comma ==> Set B : {1,2,3,}
Use
cout << "Set B : {";
for (i = 0; i < b; ++i) {
if (i > 0) cout << ",";
cout << setB[i];
}
cout << " }" << endl;
I changed your algorithm :
Before it meant : "Put the number and then put a comma"
Now it means : "If there is a number behind me put a comma, then put the number"
Before, you always printed a comma when you printed a number so you had an extra comma.
For each iteration of the for loop, the program is going to execute -everything- inside the for loop. So, your loop runs through and prints each number in your set and then a comma.
The problem is that even on your last run through the loop, it is going to print a comma, because it's part of the loop.
cout << "Set B : {";
for(i = 0; i < b; i++){
cout << setB[i];
if (i < (b-1))
cout << ",";
}
cout << " }" << endl;
This code will run the exact same, except the second to last time it runs through the loop, it will not print a comma. No need to get too fancy. :)
Personally I like this solution better. You first print out the first element and then a , [second element].
cout <<"Set B : {" << setB[0];
for(i = 1; i < b; i++)
{
cout << ",";
cout<<setB[i];
}
cout << " }" << endl;
Warning!: This will NOT work if the array is empty.
The loop code prints a pair of number and comma. Try using this one:
cout<<"Set B : {";
for(i=0;i<b;i++)
{
cout<<setB[i];
if(i < b-1) cout<<",";
}
cout<<"}"<<endl;
You're loop is executing the cout << "," 3 times. The following will give what you want:
#include <iostream>
using namespace std;
int main(){
int setB[] = {1,2,3};
cout<<"Set B : {";
for(int i=0;i<3;i++)
{
cout<<setB[i];
if ( i < 2 )
cout<<",";
}
cout<<" }"<<endl;
return 0;
}
The way I often deal with these loops where you want to put something like a space or a comma between a list of items is like this:
int main()
{
// initially the separator is empty
auto sep = "";
for(int i = 0; i < 5; ++i)
{
std::cout << sep << i;
sep = ", "; // make the separator a comma after first item
}
}
Output:
0, 1, 2, 3, 4
If you want to make it more speed efficient you can output the first item using an if() before entering the loop to output the rest of the items like this:
int main()
{
int n;
std::cin >> n;
int i = 0;
if(i < n) // check for no output
std::cout << i;
for(++i; i < n; ++i) // rest of the output (if any)
std::cout << ", " << i; // separate these
}
An other way, without extra branch:
std::cout << "Set B : {";
const char* sep = "";
for (const auto& e : setB) {
std::cout << sep << setB[i];
sep = ", ";
}
std::cout <<" }" << std::endl;
I really like to promote the use of a range library to write declarative code instead of nested for-if statements in an imperative style.
#include <range/v3/all.hpp>
#include <vector>
#include <iostream>
#include <string>
int main()
{
using namespace ranges;
std::vector<int> const vv = { 1,2,3 };
auto joined = vv | view::transform([](int x) {return std::to_string(x);})
| view::join(',');
std::cout << to_<std::string>(joined) << std::endl;
return 0;
}
If you can use STL, try the following:
#include <iterator>
#include <iostream>
int main() {
int setB[]{1,2,3};
std::cout << "Set B : { ";
for(auto i = std::begin(setB), e = std::end(setB); i != e;) {
std::cout << *i;
for(++i; i !=e; ++i) { std::cout << ", " << *i; }
}
std::cout << " }" << std::endl;
return 0;
}