I'm trying to write a program in C++ that takes in two strings containing numbers and adds them together to return a "sum" (which is also a string).
I've written comparable programs in Java and Python, so I decided that while learning C++, I might as well write something comparable. I don't know why I'm receiving the errors, and I'm not receiving any errors while compiling with Visual Studio or g++.
Below is the reference to the function in question in the main program.
Number base(NULL);
Number r = base.addNums("1", "1");
cout << r.toString() << endl;
I have ensured that I have a constructor as follows for the reference to the addNums function:
Number(void){}
I wrote some comments to try and explain my thought process while writing the header file. The method in question is as follows:
Number addNums(string in1, string in2){
// Calling number 1: X, and number 2: Y
const char* x;
const char* y;
x = in1.c_str();
y = in2.c_str();
// Flag for one number having more digits
bool flag = false;
// Flag for X having more digits
bool xIsBigger = false;
// For storing the sum later
string summ = "";
// Check and see if the flags are needed
if (!(strlen(x) == strlen(y))){
flag = true;
if (strlen(x) > strlen(y)){
xIsBigger = true;
}
}
// Prepend the zeroes to the necessary variable
// to make it work as written addition does
if (flag){
if (xIsBigger){
string zeroes;
for (unsigned int i = 0; i < (strlen(x) - strlen(y)); ++i){
zeroes += "0";
}
string newYStr = zeroes + in2;
const char* newY = newYStr.c_str();
// Add zeroes to Y variable
y = newY;
} else{
string zeroes;
for (unsigned int i = 0; i < (strlen(y) - strlen(x)); ++i){
zeroes += "0";
}
string newXStr = zeroes + in1;
const char* newX = newXStr.c_str();
// Add variables to X value
x = newX;
}
}
// If we encounter x + y > 9, we need this
int carry = 0;
// Current digit being processed
char digitX, digitY;
// Digit to be carried
char toCarry;
// Iterate through the number right to left
// to simulate top-down addition
for (int i = strlen(x) - 1; i >= 0; --i){
digitX = x[i];
digitY = y[i];
// If we're carrying a 1, add it to the top number
if (carry > 0){
digitX += 1;
carry = 0;
}
// Add together the two numbers stored in characters
int currentSum = atoi(&digitX) + atoi(&digitY);
// If x + y > 9, we need to carry
if (currentSum > 9){
string sumString = "" + currentSum;
// Max possible is 9 + 9, so we only have to carry 1
carry = 1;
// Add the second digit in the number to the position in the sum
summ = sumString.at(1) + summ;
}
// Didn't need a carry
else{
string sumString = "" + currentSum;
summ = sumString + summ;
}
}
// Return the object containing the sum
return Number(summ);
}
I'm relatively new to the use of pointers, but in the process of learning some more of the language and writing this program, and through extensive googling of syntax and language-specifics, I've been forced into what I feel is the need to use them.
I'm very sorry I cannot provide more information and I appreciate any help or critique that can help me.
Thanks in advance!
'string newYStr' may be going out of scope? Try declaring it in the top and then check.
Related
I am working on a function called add(BigDecimals c) which keeps getting an error that not all control paths are returning a value:
BigDecimal BigDecimal::add(BigDecimal c)
{
string fFirst = to_string(this->fraction()); //fraction part of the first number
string fSecond = to_string(c.fraction()); //fraction part of the second number
if (fFirst.length() < fSecond.length()) //fraction part of first/second number
{
string str(this->toString()); //convert fraction to string
for (unsigned int i = 0; i < fFirst.length() - fSecond.length(); i++) //difference between first and second
{
str += "0"; //pad in the 0's
}
this->equals(str); //call the equals function
}
if (fSecond.length() < fFirst.length()) //flip numbers around, second < first
{
string str(this->toString()); //convert fraction to string
for (unsigned int i = 0; i < fSecond.length() - fFirst.length(); i++) //difference between second and first
{
str += "0"; //pad in the 0's
}
this->equals(str); //call the equals function
}
for (unsigned int i = fSecond.length(); i > 0; i++)
{
int carryFlag = 0; //carry flag set to 0
int sum = carryFlag + stoi(this->at(i).toString()) + stoi(c.at(i).toString());
if (sum >= 10) //greater than 10
{
carryFlag = 1;
sum = sum % 10;
}
else //less than 10
{
carryFlag = 0; //set carry flag to 0
}
return BigDecimal(to_string(sum)); //this is the only thing I want to
//return
}
//It wants to return something here, but I am not sure what.
}
I have tried to fix this by replacing if statements with else statements, but nothing really works. I have no idea how to fix this error, so any help is appreciated!
Your logic is flawed (and the error message and the fact you don't know what to do about it is a good indication of that).
Your code will always return on the first iteration of the loop. Clearly what you want to do is accumulate a digit string one digit at a time, but that's not what the code you've written does.
This is something more like what you want. However I think you have other errors to do with the padding of numbers, so this code isn't going to work, but hopefully will give you some idea.
string result = "";
int carryFlag = 0; //carry flag set to 0
for (unsigned int i = fSecond.length(); i > 0; i--)
{
int sum = carryFlag + stoi(this->at(i).toString()) + stoi(c.at(i).toString());
if (sum >= 10) //greater than 10
{
carryFlag = 1;
sum = sum % 10;
}
else //less than 10
{
carryFlag = 0; //set carry flag to 0
}
result = to_string(sum) + result;
}
if (carryflag)
result = "1" + result;
return BigDecimal(result);
Notice the return is only after the loop has finished, and a new variable called result accumulates the digit generated each time round the loop.
Also notice the carryflag variable has been moved outside of the loop. The whole point of the carry is to hold the carry from one iteration of the loop to the next, so it can't be inside the loop. Also if there is a carry left over after all the digits have been added, you need to add a one digit to the beginning of the result.
Also I've changed i++ to i-- in the loop. You are iterating backwards through the strings you are adding so you need i--. It's an improvment but as I said before I still think this loop is wrong.
Clearly you understand how to do long addition, but what you haven't mastered yet is how to translate that into code. You have to think very carefully and precisely about what you are asking the computer to do.
The resultnum value of this function is "01" if i try to add two strings x and y with values "0" "1". If i tried using resultnum.find_first_of("0") it returns position as -1 instead of 0 .... i just want to get rid of that leading zero and i am unable to get rid of it... Maybe i am doing some silly mistake but please help me identify why it is returning -1 for position of 0 in result.
string addStrings(string num1, string num2) {
char carry = {0},x={0},y={0},z={0};
std::string resultnum;
long loopUnitl=std::max(num1.size(),num2.size());
long maxSize = loopUnitl+1;
resultnum.reserve(maxSize);
std::string::reverse_iterator rnum1_it=num1.rbegin();
std::string::reverse_iterator rnum2_it=num2.rbegin();
while(loopUnitl)
{
if(rnum1_it != num1.rend())
{
x = *rnum1_it;
rnum1_it++;
}
else
{
x = '0';
}
if(rnum2_it != num2.rend())
{
y = *rnum2_it;
rnum2_it++;
}
else
y = '0';
z = (x -'0') + (y - '0') + carry;
if (z > 9)
{
carry = 1;
z -= 10;
}
else
{
carry = 0; //Else no carry was generated
}
resultnum[loopUnitl] = (z+'0');
loopUnitl=loopUnitl-1;
if(loopUnitl==0)
{
resultnum[loopUnitl] = carry+'0';
resultnum[maxSize]='\0';
}
}
return resultnum;
}
You need to use resultnum.resize() instead of resultnum.reserve().
Your use of operator[] to insert chars into resultnum is undefined behavior, because the valid range for accessing characters is [0, size()), not [0, capacity()) (had you used the at() method instead of operator[], your code would have raised exceptions warning you about indexes being out of range).
Alternatively, if you want to keep using reserve(), you should use the insert() method to add characters to the front of the string on each loop iteration, instead of using operator[].
A string's size() and capacity() are two different things. The capacity() is how much memory the string has physically allocated to hold characters, but the size() is how many of those characters are actually valid data. Operations like searching act on size(), not capacity().
Since the string's size() is never > 0, that is why find_first_of() returns -1.
Thank you so much for your suggestions and reply. I did change the above code to not use [] operator and just added to the string and finally reversed the string and now code works perfectly.I am so thankful to you :) .
string addStrings(string num1, string num2) {
char carry = {0};
std::string resultnum;
char x={0},y={0};
char z={0};
long loopUnitl=std::max(num1.size(),num2.size());
long maxSize = loopUnitl+1;
resultnum ="";
std::string::reverse_iterator rnum1_it=num1.rbegin();
std::string::reverse_iterator rnum2_it=num2.rbegin();
while(loopUnitl)
{
if(rnum1_it != num1.rend())
{
x = *rnum1_it;
rnum1_it++;
}
else
{
x = '0';
}
if(rnum2_it != num2.rend())
{
y = *rnum2_it;
rnum2_it++;
}
else
y = '0';
z = (x -'0') + (y - '0') + carry;
if (z > 9)
{
carry = 1;
z -= 10;
}
else
{
carry = 0; //Else no carry was generated
}
resultnum += (z+'0');
loopUnitl=loopUnitl-1;
if(loopUnitl==0)
{
if(carry)
resultnum += (carry+'0');
}
}
std::reverse(resultnum.begin(),resultnum.end());
return resultnum;
}
I am going to have an array that is 50 elements long. Each element will contain one digit to form a 50 digit number. What I want to do is multiply this 50 digit long array by another 50 digit long array. The way I thought of doing this was converting each number to form one string. Then produce an algorithm that would multiply line by line 20 digits at a time. Then once the last for loop breaks out of scope, I could reconstruct the new array, digit by digit from converting it from a string. Any alternate ideas before I attempt this, or is what I got what you would do too?
int n1[50], n2[50], out[51];
// n1 and n2 must be populated here
int carry = 0;
for (int cur = 49; cur >= 0; --cur) {
out[cur+1] = n1[cur] * n2[cur] + carry;
carry = out[cur+1] / 10;
out[cur+1] %= 10;
}
out[0] = carry;
I believe you could find the question at leetcode OJ named "Multiply Strings".
This is my solution. Just for reference. Wish this will help :)
class Solution {
public:
string multiply(string num1, string num2) {
int s1(num1.size()), s2(num2.size()), size(s1+s2);
vector<int> digit(size,0), carry(size,0); // digit: store current digit, carry: store carry digit
for(int i = 0; i < s1; ++i){
for(int j = 0; j < s2; ++j){
int mul = num1[s1-1-i]-'0';
int muled = num2[s2-1-j]-'0';
int tmp = mul*muled;
digit[size-1-i-j] += tmp%10; // accum
carry[size-1-i-j-1] += tmp/10; // accum
}
}
int carrFlag(0); // initial carry_flag
for(int i = size-1; i >= 0; --i){ // merge digit and carry
int sum = digit[i] + carry[i] + carrFlag;
ret.insert(ret.begin(),1,'0'+sum%10); // compose result string
carrFlag = sum/10; // update carry_flag
}
int pos(0);
while(ret[pos] == '0') ++pos; // get rid of extra 0's
if(pos>=size) return "0"; // edge case
return ret.substr(pos);
}
private:
string ret;
};
vector<int> add_vectors(const vector<int> &first, const vector<int> &second){
vector<int> result;
int length = 0;
int carry = 0;
int firsts_size = first.size();
int seconds_size = second.size();
if (firsts_size >= seconds_size){
int length = firsts_size;
}
else{
int length = seconds_size;
}
for (int i = length - 1; i >= 0; i--){
int digit_sum = first[i] + second[i] + carry;
if (digit_sum > 9){
carry = ((digit_sum / 10) % 10);
}
result.push_back(digit_sum);
}
return result;
}
So hey guys, you have all helped me out a couple of times and I am hoping that you can do the same thing again for me. So the purpose of this function in a C++ program is to take two vectors with digits, taken from large numbers, and to add them together and create a vector in the end with the sum to return from the function. However, I am having an issue with this, and I can't tell if it is a problem with the way I have done the actual addition or if some way I am printing them out in my main.
I have created another function to take a vector comprised of digits and turn it into a string to print back out as output, and I know this function works because it works a lot throughout my program. So I am convinced that something is going on with this function and causing me not to be able to print. However, Visual Studio does not throw any errors from it or anything, simply that where the output is supposed to be is left blank, which has left me stumped. Any help is greatly appreciated!! Just remember one thing, since this is the first program from my class I can't use anything too advanced to solve this issue. Thanks for the Help
I will assume you have the position i of the vector associated with the (i-1)-th power of 10.
EDITED: now it works also with different size vectors
vector<int> add_vectors(const vector<int> &first, const vector<int> &second){
vector<int> result;
int length = 0;
int carry = 0;
int firsts_size = first.size();
int seconds_size = second.size();
int digit_sum = 0;
if (firsts_size >= seconds_size){
length = firsts_size; // int here is not necessary
}
else{
length = seconds_size; // int here is not necessary
}
for (int i = 0, i<lenght; i++){
if (i>=lenght){
if (i>=firsts_size){
digit_sum = second[i] + carry;
}
else{
digit_sum = first[i] + carry;
}
}
else{
digit_sum = first[i] + second[i] + carry;
}
if (digit_sum > 9){
carry = 1; // carry will be no mor than 1 adding two numbers
digit_sum = digit_sum - 10;
}
else{
carry = 0;
}
result.push_back(digit_sum);
}
if (carry > 0){
result.push_back(carry);
}
return result;
}
I'm building my own string class and I'm trying to use this function to convert a numerical string to an integer:
int String::convertToInt() const {
int exp = length() - 1;
int result = 0;
for(int i = 0; i < length(); ++i) {
result += (charAt(i) - '0') * (10 ^ exp);
--exp;
}
return result;
}
Something isn't working right, but I can't pick out what it is. When I try to convert "49" to an int, it converts it to 134.
^ is XOR. I believe you're looking for std::pow(10, exp).
Or even this:
int String::convertToInt() const {
int order = std::pow(10, length() - 1);
int result = 0;
for(int i = 0; i < length(); ++i) {
result += (charAt(i) - '0') * order;
order /= 10;
}
return result;
}
The easiest way is to realize that 49 is 4 * 10 + 9, and 493 similarly is 49 * 10 + 3.
That is to say, the result is 10 times the first N-1 digits plus the last digit. You can write that as a loop or as a recursive function. Stack depth won't hurt you; after about 20 digits you'd overflow even a 64 bits result. So
int String::convertToInt() const {
if (empty()) return 0; // Recursive functions better terminate.
// TODO: negative numbers.
return 10 * convertToInt(substr(0, length()-1)) + (back() - '0');
}
or
int String::convertToInt() const {
// TODO: negative numbers.
int result = 0;
for(int i = 0; i < length(); ++i) {
result * = 10;
result += (charAt(i) - '0');
}
return result;
}
A more efficient approach would be:
// I know you said you are using something else
// but the same principle applies here
std::string s = "12345";
unsigned int result = 0;
unsigned int place = 1;
for (std::size_t i = s.length() - 1; i >= 0; --i, place *= 10)
{
result += (s[i] - '0') * place;
}
Basically, you start at the right-most character and work your way left. Each character you move left, you multiply your place by 10 (very similar to how most of us learned to do addition growing up: add your 1's ... add your 10's ... add your 100's ... etc.). This also assumes that you already know the string contains nothing but numeric characters ('0'-'9').