Addition string to avoid number limitation - c++

I want to add two numbers by adding number by number like when you are child.
In order to calculate very long numbers (more than the C++ limitation).
My first step is to try an example 2 numbers having a sum < 10:
string valeur1 = "135";
string valeur2 = "844";
string result;
for (int i = 0; i < valeur1.length(); i++)
{
std::ostringstream ss;
int value;
int value3;
int value2;
//string to int
valeur1[i] >> value;
valeur2[i] >> value2;
value3 = (value + value2);
// int to string
ss << value3;
result = result + ss.str();
}
cout << result;
Am I headed in the right direction?

I think you are headed in the right direction. Three things you can improve:
You have to take into account when value3 is larger than 10 (You seem aware of that)
Be careful when the two numbers don't have the same number of digits. Now your code will fail in that case.
You are using an array of characters. Why not use an array of integers instead? If you only want to avoid the size limitation of an integer I think it would be a much better option as you wouldn't need all the string<->integer conversions.

Your first step is very simple:
#include <string>
#include <iostream>
int main()
{
std::string s1 = "135";
std::string s2 = "844";
std::string result;
for(size_t i=0;i<std::min(s1.size(),s2.size());i++)
result+= std::to_string(s1[i]-'0'+s2[i]-'0');
std::cout<<result<<std::endl;
return 0;
}
Edit:
As noted Gerard Abello , you should take into account the different size of strings and case when sum is greater than 3. However,I believe that the string representation is a good option. One of the options for adding the numbers as strings.
# include <string>
# include <iostream>
std::pair<int,std::string> simpleConvert(const std::string &str);
std::string add(const std::string &first,const std::string &second);
int main()
{
std::string s1 = "128";
std::string s2 = "9999";
std::string result = add(s1,s2);
std::cout<<result<<std::endl;
return 0;
}
std::pair<int,std::string> simpleConvert(const std::string &str)
{
if(str.size()==1)
return std::make_pair(0,str);
else if(str.size()==2)
return std::make_pair(str[0]-'0',std::string(str.begin()+1,str.end()));
}
std::string add(const std::string &first,const std::string &second)
{
std::string s1(first.rbegin(),first.rend());
std::string s2(second.rbegin(),second.rend());
auto n = s1.size();
auto m = s2.size();
auto min = std::min(n,m);
auto max = std::max(n,m);
for(size_t j=min;j!=max;j++)
if(n<m)
s1+="0";
else
s2+="0";
std::string result;
int add=0;
for(size_t i=0;i<s1.size();i++)
{
auto temp = simpleConvert(std::to_string(s1[i]-'0'+s2[i]-'0'+add));
result+= temp.second;
add = temp.first;
}
if(add!=0)
result+=std::to_string(add);
return std::string(result.rbegin(),result.rend());
}

Related

How to find the index of element (and a few other things)

I was writing a code that would substitute some random 17 character strings into a single alphabet, and I can't find a way. Basically, what I'm trying to do is this:
char strings[] = {
"L-nIbhm5<z:92~+,x",
"9bC5f0q#qA(RKZ>|r",
"9bC5f0q#qA(RKZ>|r",
"k=5,ln(08IAl(gGAK",
"|N,8]dGu)'^MaYpu[",
"!&,Y*nz8C*,J}{+d]",
"Us9%^%?n5!~e##*+#",
"zF8,1KV#¥]$k?|9R#",
"0B4>=nioEjp>4rhgi",
}
char alphabet[]{
"a","b","c","d","e","f","g","h","i",
}
replace(std::string str){
/**get str and then see the index of the corresponding string in strings[], and replace the string with alphabet[index number], while deleting the original string part that was replaced**/
int main(){
cin >> std::string replace;
replace(replace);
example input: L-nIbhm5<z:92~+,x9bC5f0q#qA(RKZ>|r9bC5f0q#qA(RKZ>|r
expected output: abc
EDIT:
New Code
Changes from the original code
It also has a bigger array than the simplified version(previous code). It displays the structure of the full program.(where the strings are routed to and why)
Basically What it's doing
getting input from user, put it in the input variable, input goes through algorithm() function untouched, and then goes to the replace function and is replaced. It then the replaced string gets returned back through the original route to the main function, where it is displayed.
I've kept the arrays a string type because the const char* gave me a segmentation error.
std::string Subs[53]=
{
"LQlMv]G5^^1kcm?fk",
"7W^S;/vB(6%I|w[fl",
"<w7>4f//Z55ZxK'z.",
"_W5g(lu<pTu3^_A7n",
"OfLm%8:EF}0V1?BSS",
"|+E6t,AZ~XewXP17T",
"L-nIbhm5<z:92~+,x",
"L-nIbhm5<z:92~+,x",
"9bC5f0q#qA(RKZ>|r",
"9bC5f0q#qA(RKZ>|r",
"k=5,ln(08IAl(gGAK",
"|N,8]dGu)'^MaYpu[",
"!&,Y*nz8C*,J}{+d]",
"Us9%^%?n5!~e##*+#",
"zF8,1KV#¥]$k?|9R#",
"0B4>=nioEjp>4rhgi",
"EG#0[W9.N4i~E<f3x",
"(0Pwkk&IPchJHs.7A",
"7XgmQ6fW<|J+NY[m0",
".g4CwX/DU!!~!zbtZ",
"+_U'qn_/9Fo|gT/!n",
"=0s(mYh&F%y=MBS5(",
"cg71(}bo+Q5P8F[T6",
"lc|a\%5.9pOpooU+QR",
"E_(3A:o+.]qL3MYA6",
"H#O'X_RiVS#8l0bKD",
"Y1gbGD`~8d>HSWN35",
"LQlMv]G5^^1kcm?fk",
"T4}gI;`BFVfhw=-sf",
"6BHMA0IRix]/=(jht",
"yS$=#Jdpp?P2k6SMQ",
"t1~|kkh+>4d>}OQ`a",
"2Y-\\CU\"944yBluWD5",
"'M\\ZbIX5{`Xd;qi!o",
"?N+RtVqj_r(C5##0\"",
"2;*Livh?V$X/8z#Md",
")IN|7FOs2l-mAM[d#",
"(~f268J},xXrK'Rp'",
"&r/qf9fFHnzV!RzH/",
"}naDRH4p$NI2a).t,",
"{8DM+7!.Mge|~fnO|",
")r[#nI0YDH>6cE38p",
"(0Pwkk&IPchJHs.7A",
")r[#nI0YDH>6cE38p",
"8M-=cQFQ,pPo7eu=p",
"0PHw=/|(tZ1}FHm/'",
"[su`'0Oybc.\"-/W5)",
"1uHl[IC7Sr#NUJV;I",
"8z8%,jK0CDOkJz8I?",
"3Ao2yXDN%YzpE&Suy",
"zNs`7E'e/$i8VqaUL",
"bzHmA^K2>7`UZ?!AO",
};
std::string Alphabet[53] =
{
" ","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","r","w","x","y","z",
"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
};
std::string replace(std::string rep) {
int len = sizeof(Subs)/sizeof(Subs[0]);
std::stringstream ss1;
for(int i = 0; i < len; i++) {
if (rep.find(Subs[i]) != std::string::npos) {
ss1 << Subs[i];
}
}
std::string input = ss1.str();
return input;
}
std::string algorithm(std::string input)
{
//some other algorithms come here(not relative to this question)
input = replace(input);
return input;
}
int main(void){
int ed;
std::cin >> ed;
if(ed == 1){
//different function(not relative to the question)
}
else if(ed == 0){
std::string input;
std::cin >> input;
input = algorithm(input);
std::cout << input << std::endl;
}
else{
std::cout << "1 or 0" << std::endl;
main();
}
return 0;
}
example input: L-nIbhm5<z:92~+,x9bC5f0q#qA(RKZ>|r9bC5f0q#qA(RKZ>|r
expected output: abc
actual output: L-nIbhm5<z:92~+,xL-nIbhm5<z:92~+,x9bC5f0q#qA(RKZ>|r9bC5f0q#qA(RKZ>|r
Sorry it's become long.
There are few mistakes in above code :
char array initialization is not correct.
method body for main and replace method is not closed.
Currently by default return type of replace method is int.
There is string#find method which can be helpful here.
I have tried to make those fixes and here is updated code in C++17 :
#include <iostream>
#include <sstream>
using namespace std;
const char *strings[9] = {
"L-nIbhm5<z:92~+,x",
"9bC5f0q#qA(RKZ>|r",
"9bC5f0q#qA(RKZ>|r",
"k=5,ln(08IAl(gGAK",
"|N,8]dGu)'^MaYpu[",
"!&,Y*nz8C*,J}{+d]",
"Us9%^%?n5!~e##*+#",
"zF8,1KV#¥]$k?|9R#",
"0B4>=nioEjp>4rhgi"
};
const char *alphabet[9] = {
"a","b","c","d","e","f","g","h","i"
};
void replace(std::string rep) {
int len = sizeof(strings)/sizeof(strings[0]);
std::stringstream ss1;
for(int i = 0; i < len; i++) {
if (rep.find(strings[i]) != std::string::npos) {
ss1 << alphabet[i];
}
}
std::cout << ss1.str();
}
int main(){
std::string rep;
cin >> rep;
replace(rep);
}
For reference : https://onlinegdb.com/Bd9DXSPAa
Note - Above code is just for reference, please make sure to add all test cases handling.
I made a c++17 version for your code.
Replacing 'c' style arrays and pointers with C++ style containers, iterators.
And using std::string::replace function. Use the standardlibrary if you can,
its tested and well documented.
#include <algorithm>
#include <iostream>
#include <regex>
#include <string>
#include <vector>
// std::vector/std::array instead of 'c' style arrays.
// allows us to us range based for loops later.
std::vector<std::string> strings =
{
"L-nIbhm5<z:92~+,x",
"9bC5f0q#qA(RKZ>|r",
"k=5,ln(08IAl(gGAK",
"|N,8]dGu)'^MaYpu[",
"!&,Y*nz8C*,J}{+d]",
"Us9%^%?n5!~e##*+#",
//"zF8,1KV#¥]$k?|9R#", // <<== I commented out this line, ¥ is not a valid charcter in my environment
"0B4>=nioEjp>4rhgi"
};
// a string is already an array of characters.
std::string alphabet{ "abcdefghijkl" };
std::string replace_with_alphabet(const std::string& input)
{
std::string retval{ input };
std::size_t index{ 0 };
// range based for, it will keep the order of the vector.
for (const auto& str : strings)
{
// look if you can find any of the predefined strings
// in the input strings.
const size_t pos = retval.find(str, 0);
// if found
if (pos != std::string::npos)
{
// get the next character from the alphabet
std::string replacement{ alphabet[index++] };
// use std::string::replace for replacing the substring
const size_t len = str.length();
retval.replace(pos, len, replacement, 0);
}
}
return retval;
};
/**get str and then see the index of the corresponding string in strings[], and replace the string with alphabet[index number], while deleting the original string part that was replaced**/
int main()
{
auto output = replace_with_alphabet("L-nIbhm5<z:92~+,x9bC5f0q#qA(RKZ>|rk=5,ln(08IAl(gGAK");
std::cout << output << std::endl;
}

Find sum of numbers in a string without loops in c++

I've found plenty of resources online how how to calculate the sum of numbers in an alphanumeric string, and I've got a working c++ code below.
#include <iostream>
using namespace std;
int findSum(string str)
{
string temp = "";
int sum = 0;
for (char ch: str)
{
if (isdigit(ch))
temp += ch;
else
{
sum += atoi(temp.c_str());
temp = "";
}
}
return sum + atoi(temp.c_str());
}
int main()
{
string str = "t35t5tr1ng";
cout << findSum(str);
return 0;
}
For the example above, "t35t5tr1ng" returns "41".
Now I'm trying to do the same thing, without using any loops.
On the top of my head, I'm thinking arrays, but even then I'm not sure how to parse the values in the array without a for loop of some kind.
Any suggestions or help would be appreciated!
You can use standard algorithms instead of writing loops. Even if it's just a for-loop under the hood, but it can make user code easier to understandby stating the intent.
int findSum(string str)
{
// replace all the non-digits with spaces
std::replace_if(str.begin(), str.end(),
[](unsigned char c) {
return !std::isdigit(c);
}, ' ');
// sum up space separated numbers
std::istringstream iss{str};
return std::accumulate(
std::istream_iterator<int>{iss},
std::istream_iterator<int>{}, 0);
}
Here's a demo.
Here is another solution using std::accumulate:
#include <numeric>
#include <iostream>
#include <string>
#include <cctype>
int findSum(std::string str)
{
int curVal = 0;
return std::accumulate(str.begin(), str.end(), 0, [&](int total, char ch)
{
// build up the number if it's a digit
if (std::isdigit(static_cast<int>(ch)))
curVal = 10 * curVal + (ch - '0');
else
{
// add the number and reset the built up number to 0
total += curVal;
curVal = 0;
}
return total;
});
}
int main()
{
std::string str = "t35t5tr1ng";
std::cout << findSum(str);
return 0;
}

How can I read the numbers in a char array as integers?

I want to pass dimension parameters of a matrix class as a char array, I can get the number of dimensions by counting the number of commas written in the parameters but I cant seem to read the numbers in a char as integers.
When I try to convert from char to int I get huge unrelated numbers. How can I read the numbers in a char array as integers?
template <class T>
matrix <T>::matrix (char * dimensions)
{
int nod = 0;
for(int i=0;dimensions[i];i++)
{
if (dimensions[i] == ',') nod++;
}
Number_of_dimensions = nod+1;
//...
}
You can use the following idea, illustrated with a rough pseudo-code snipper:
std::string s = "1234,4556";
//While you still have a string to parse
while (s.length()) {
//Use a comma to delimit a token
std::string delimiter = ",";
//Find the position of the comma or the end of the string
unsigned int comma_pos = s.find(delimiter);
//Find the sub-string before the comma
std::string token = s.substr(0, comma_pos); // token is "1234"
//Find your int
int i = std::stoi(token);
//"Eat" the token, continue
s.erase(0, comma_pos+1);
}
This is a particularly rough example, but the core idea is there: use std::string::substr() to find your sub-string with a comma delimiter, then convert the token to an int.
You also might want to consider looking for several delimiters, such as '\n'.
Split() function splits string by delimiter. In our case delimiter is comma. The number of elements is dimension. Than we convert each element to number using std::stringstream (C++98, or std::stoi in C++11).
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
std::vector<std::string> Split(const std::string &s, char delim)
{
std::vector<std::string> elems;
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim))
elems.push_back(item);
return elems;
}
std::vector<int> GetDim(char *dimensions)
{
std::vector<std::string> dim_str = Split(dimensions, ',');
std::vector<int> elems(dim_str.size());
for (size_t i = 0; i < dim_str.size(); ++i) {
std::stringstream ss(dim_str[i]);
ss >> elems.at(i);
}
return elems;
}
int main() {
std::string s = "1234,4556";
std::vector<int> d = GetDim(&*s.begin());
std::cout << "Dimensions: " << d.size() << std::endl;
std::cout << "Values: ";
for (size_t i = 0; i < d.size(); ++i) {
std::cout << d[i] << " ";
}
std::cout << std::endl;
return 0;
}
I suggest you not to use pointer as arguments. Use std::string or std::vector instead. Do not forget const qualifier. So GetDim() can be:
std::vector<int> GetDim(const std::string& dimensions)
{
std::vector<std::string> dim_str = Split(dimensions, ',');
std::vector<int> elems(dim_str.size());
for (size_t i = 0; i < dim_str.size(); ++i) {
std::stringstream ss(dim_str[i]);
ss >> elems.at(i);
}
return elems;
}

Extracting integer values from string elements and adding up

I have the following lines of code:
vector<string> c;
string a;
for(int i=0;i<4;i++){
cin>>a;
c.push_back(a);
}
If I provide input as:
120$,132$,435$,534$
How can I extract the integer values separately and add them up to get the total value?
You can use e.g. std::getline with a custome "line" separator using the comma, strip the last character from the string (the '$') and use std::stoi to convert to an integer:
std::vector<int> c;
for (int i = 0; i < 4; i++)
{
std::string a;
std::getline(std::cin, a, ',');
a = a.substr(a.length() - 1); // Remove trailing dollar sign
c.push_back(std::stoi(a));
}
Edit: Using std::accumulate:
int sum = std::accumulate(c.begin(), c.end(), 0);
Edit 2: Using std::strtol instead of std::stoi:
The function std::stoi is new in the latest C++ standard (C++11) and it not supported in all standard libraries yet. Then you can use the older C function strtol:
c.push_back(int(std::strtol(a.c_str(), 0, 10)));
You can use regex and streams:
#include <regex>
#include <iostream>
#include <sstream>
const std::string Input("120$,132$,435$,534$");
int main(int argc, char **argv)
{
const std::regex r("[0-9]+");
int Result = 0;
for (std::sregex_iterator N(Input.begin(), Input.end(), r); N != std::sregex_iterator(); ++N)
{
std::stringstream SS(*N->begin());
int Current = 0;
SS >> Current;
Result += Current;
std::cout << Current << '\n';
}
std::cout << "Sum = " << Result;
return 0;
}
Output:
120
132
435
534
Sum = 1221
If you must ensure that the number is followed by a '$' then change the regex to: "[0-9]+\\$" the stringstream part will ignore the trailing '$' in the number conversion:
#include <regex>
#include <iostream>
#include <sstream>
const std::string Input("120$,132$,435$,534$,1,2,3");
int main(int argc, char **argv)
{
const std::regex r("[0-9]+\\$");
int Result = 0;
for (std::sregex_iterator N(Input.begin(), Input.end(), r); N != std::sregex_iterator(); ++N)
{
std::stringstream SS(*N->begin());
int Current = 0;
SS >> Current;
Result += Current;
std::cout << Current << '\n';
}
std::cout << "Sum = " << Result;
return 0;
}
Output:
120
132
435
534
Sum = 1221
If the input isn't too large (and particularly if it comes as a single
line), the simplest solution is to pack it all into a string, and parse
that, creating a std::istringstream to convert each of the numeric
fields (or using boost::lexical_cast<>, if by some odd chance it has
the appropriate semantics—it normally does when translating a
string to a built-in numeric type). For something this simple, it's
possible, however, to read directly from a stream, however:
std::istream&
ignoreDollar( std::istream& stream )
{
if ( stream.peek() == '$' ) {
stream.get();
}
return stream;
}
std::istream&
checkSeparator( std::istream& stream )
{
if ( stream.peek() == ',' ) {
stream.get();
} else {
stream.setstate( std::ios_base::failbit );
}
return stream;
}
std::vector<int> values;
int value;
while ( std::cin >> value ) {
values.push_back( value );
std::cin >> ignoreDollar >> checkSeparator;
}
int sum = std::accumulate( values.begin(), values.end(), 0 );
(In this particular case, it might be even simpler to just do everything
in the while loop. The manipulators are a generally useful technique,
however, and can be used in a wider context.)
A simple version:
int getIntValue(const std::string& data)
{
stringstream ss(data);
int i=0;
ss >> i;
return i;
}
int getSum(std::vector<std::string>& c)
{
int sum = 0;
for (auto m = c.begin(); m!= c.end(); ++m)
{
sum += getIntValue(*m);
}
return sum;
}
Done

C++ Parse string to integer with specific classes

It might sound stupid, but I was just wondering how can I parse a string to an integer in C++?
This is for a school project, and the explanation sheet says :
"Only the use of iostream and string classes and system() function is permitted; The use of any other class or function is prohibited."
I have searched around a bit, but the only suggestions I found are using classes like atoi or atof.
The input string is already checked for error before the parsing, so it will always only contain an integer.
I wouldn't mind doing the parsing manually with conditionals, but I don't think it would be my teacher's (or anyone's) preferred way.
Thanks a bunch if you can help.
So, you can use system(), huh? Behold this masterpiece of engineering:
#include <fstream>
void download_boost() {
system("wget http://downloads.sourceforge.net/"
"project/boost/boost/1.47.0/boost_1_47_0.tar.bz2"
"?r=http%3A%2F%2Fwww.boost.org%2Fusers%2Fhistory%2F"
"version_1_47_0.html&ts=1316116936&use_mirror=kent"
" -O boost_1_47_0.tar.bz2");
}
void unpack_boost() {
system("tar --bzip2 -xf boost_1_47_0.tar.bz2");
}
void write_program() {
std::ofstream os("blah.cpp");
os << "#include \"boost/lexical_cast.hpp\"\n"
"#include <iostream>\n"
"#include <string>\n"
"int main() { std::string s; std::cin >> s;"
"int i = boost::lexical_cast<int>(s);"
"std::cout << i; }";
}
void compile_program() {
system("g++ -Iboost_1_47_0 blah.cpp");
}
void run_program() {
system("./a.out");
}
int main() {
download_boost();
unpack_boost();
write_program();
compile_program();
run_program();
}
(I'm assuming a typical Linux installation with some common tools installed.)
#include <iostream>
#include <string>
int stringToInt(const std::string &text)
{
int number = 0;
int powerIndex = 1;
for (int i = text.length() - 1; i >= 0; i--)
{
number += powerIndex * (text.at(i) - '0');
powerIndex *= 10;
}
return number;
}
std::string intToString (int number)
{
std::string text = "";
int numberHolder = number;
while (numberHolder)
{
char digit = (numberHolder % 10) + '0';
text = digit + text;
numberHolder /= 10;
}
return text;
}
int main ()
{
//Testing...
int number = stringToInt("123");
std::string text = intToString(456);
std::cout << number << "\n" << text << "\n";
return 0;
}
stringstreams come closest to what you want to do, although it may seem a little cumbersome at first.
Example:
#include <string>
#include <sstream>
// (...)
std::string str = "12345";
std::istringstream ss(str);
int num;
ss >> num;
As a function (and optimized):
#include <sstream>
#include <string>
int stringToInt(const std::string &str) {
static std::istringstream ss;
ss.clear();
ss.str(str);
int num;
ss >> num;
return num;
}
Here, I am reusing the std::istringstream by applying the static keyword. I have created a very simple benchmark that demonstrates that this is approximately 2 times faster than not reusing: http://pastebin.com/vLSmCyMF
Warning regarding thread-safety: As рытфолд has noted in the comments, the above implementation of stringToInt is not thread-safe. If you want to call this function safely from multiple threads, you should use the thread_local storage class specifier (available since C++11).
std::string mystring = "12";
std::ostringstream str(mystring);
int someint;
str >> someint;
Basically, given a std::string mystring that contains only an integer:
Start with an int result = 0;.
While mystring has digits
Multiply result by ten
Add biggest digit (first in string)
Remember that the character '0' does not have the value of 0.
Remove the biggest digit from the string
So:
If I have the string "1543", result = 0
we multiply result by ten : result = 0
we add the first digit: result = 1
remove the first digit from the string "543"
we multiply result by ten : result = 10
we add the first digit: result = 15
remove the first digit from the string "43"
we multiply result by ten : result = 150
we add the first digit: result = 154
remove the first digit from the string "3"
we multiply result by ten : result = 1540
we add the first digit: result = 1543
remove the first digit from the string ""
string is empty, so we're done
I wrote code, but then remembered this was a homework problem.