add strings without using builtin library function, what am i doing wrong? - c++

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;
}

Related

stoi() terminate after throwing and instance of 'std::invalid argument in c++-- What am I doing wrong?

Fairly new to coding. Trying some of the easy projects at LeetCode, and failing... Ha! I am trying to take an integer and convert it to a string so I can reverse it, then re-convert the reversed string back into a integer.
This code is throwing the "terminate after throwing and instance of 'std::invalid argument' what(): stoi" error. I've spent an hour searching google and other questions here on SO, but can't figure out why it's not working.
bool isPalindrome(int x) {
std::string backwards ="";
std::string NumString = std::to_string(x);
for (int i = NumString.size(); i >= 0 ; i--) {
backwards += NumString[i];
}
int check = std::stoi(backwards);
if (check == x) {
return true;
}
else {
return false;
}
}
EDIT: I think I figured it out. It was adding the null character to the end of the string upon first conversion, then adding it to the beginning of the string when I reversed it. Spaces can't be converted to integers.
So... I changed this line and it works:
for (int i = NumString.size() - 1; i >= 0 ; i--)
you can also reverse number without using string.
bool isPalindrome(int x) {
long long rev = 0;
int cur = x;
while( cur > 0) {
rev *= 10;
rev += cur % 10;
cur /=10;
}
return rev == x;
}
Its simpler than your answer that you edited in. YOu have
for (int i = NumString.size(); i >= 0 ; i--) {
backwards += NumString[i];
}
Imagine that Numstring has length 3 (no matter what spaces, digits,....)
So now you are efectively doing
for (int i = 3; i >= 0 ; i--) {
backwards += NumString[i];
}
So first loop goes
backwards += NumString[3];
well the indexes of things in an array of length 3 in c++ are 0,1,2. YOu are going one off the end
This is why you see loops doing
for(int i = 0; i < len; i++){}
Note the i < len not i <= len

Why do i get 0 instead of negative number when subtracting?

I was trying to solve "codewars" kata. And it looked pretty easy at first. When I wrote the program, it was working correctly only with a positive return value. So, when the result is a positive number, it's OK, however, when trying to subtract, I always get 0 instead of a negative number. I thought that the problem could be with type of the int. So I tried to change it to signed int. But it didn't help.
So, the task sounds like this: you have to make addition and subtracting on a given string. The return value must also be a string.
Examples:
"1plus2plus3plus4" --> "10"
"1plus2plus3minus4" --> "2"
Here is my code:
#include <string>
std::string calculate(std::string str)
{
std::string temp; signed int result = 0;
for (auto& x : str)
{
if (std::isdigit(x) && result == 0 )
result = std::stoi(std::string(1,x));
if (std::isdigit(x) && result !=0 )
{
if (temp == "plus") // if it's operation PLUS than add
{
result += std::stoi(std::string(1,x)); // c++always get 0 instead of signed int
}
else // if operation MINUS than subtract
{
result -= std::stoi(std::string(1,x)); // here always get result as 0
}
temp = "";
}
if (std::isalpha(x)) temp += x;
}
return std::to_string(result-1);
}
Your loop should not be checking for result == 0/result != 0 to know if result has a value. Think of what happens if the running result is actually 0 halfway through the iteration, ie "1plus1minus...".
If you step through your code with a debugger, you would see that on the very 1st iteration, x is '1', so if (std::isdigit(x) && result == 0 ) is true, so result gets set to 1, but then the following if (std::isdigit(x) && result !=0 ) is now true. But temp has not been set to anything yet, so if (temp == "plus") is false, and the loop falls into the code that subtracts from result, thus making it 0, when it should not be changing result at all.
Try something more like this instead:
#include <string>
std::string calculate(const std::string &str)
{
std::string temp;
int result = 0;
if (!str.empty() && std::isdigit(str[0]))
{
result = str[0] - '0';
for (size_t i = 1; i < str.size(); ++i)
{
char x = str[i];
if (std::isdigit(x))
{
int num = (x - '0');
if (temp == "plus")
{
result += num;
}
else if (temp == "minus")
{
result -= num;
}
temp = "";
}
else if (std::isalpha(x))
temp += x;
}
}
return std::to_string(result);
}
Demo

Insert symbol into string C++

I need to insert symbol '+' into string after its each five symbol.
st - the member of class String of type string
int i = 1;
int original_size = st.size;
int count = 0;
int j;
for (j = 0; j < st.size; j++)
{
if (i % 5)
count++;
}
while (st.size < original_size + count)
{
if (i % 5)
{
st.insert(i + 1, 1, '+');
st.size++;
}
i++;
}
return st;
I got an error in this part of code. I think it is connected with conditions of of the while-cycle. Can you help me please how to do this right?
If I've understood you correctly then you want to insert a '+' character every 5 chars in the original string. One way to do this would be to create a temporary string and then reassign the original string:
std::string st("A test string with some chars");
std::string temp;
for (int i = 1; i <= st.size(); ++i)
{
temp += st[i - 1];
if (i % 5 == 0)
{
temp += '+';
}
}
st = temp;
You'll notice I've started the loop at 1, this is to avoid the '+' being inserted on the first iteration (0%5==0).
#AlexB's answer shows how to generate a new string with the resulting text.
That said, if your problem is to perform in-place insertions your code should look similar to this:
std::string st{ "abcdefghijk" };
for(auto i = 4; i != st.size(); i += 5)
st.insert(i+1, 1, '+'); // insert 1 character = '+' at position i
assert(st == "abcde+fghij+k");
std::string InsertEveryNSymbols(const std::string & st, size_t n, char c)
{
const size_t size(st.size());
std::string result;
result.reserve(size + size / n);
for (size_t i(0); i != size; ++i)
{
result.push_back(st[i]);
if (i % n == n - 1)
result.push_back(c);
}
return result;
}
You don't need a loop to calculate the length of the resulting string. It's going to be simply size + size / 5. And doing multiple inserts makes it a quadratic-complexity algorithm when you can just as easily keep it linear.
Nothing no one else has done, but eliminates the string resizing and the modulus and takes advantage of a few new and fun language features.
std::string temp(st.length() + st.length()/5, '\0');
// preallocate string to eliminate need for resizing.
auto loc = temp.begin(); // iterator for temp string
size_t count = 0;
for (char ch: st) // iterate through source string
{
*loc++ = ch;
if (--count == 0) // decrement and test for zero much faster than
// modulus and test for zero
{
*loc++ = '+';
count = 5; // even with this assignment
}
}
st = temp;

Segmentation Fault while simulating top-down addition in C++

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.

Find if we can get palindrome

Given a string S.We need to tell if we can make it to palindrome by removing exactly one letter from it or not.
I have a O(N^2) approach by modifying Edit Distance method.Is their any better way ?
My Approach :
int ModifiedEditDistance(const string& a, const string& b, int k) {
int i, j, n = a.size();
int dp[MAX][MAX];
memset(dp, 0x3f, sizeof dp);
for (i = 0 ; i < n; i++)
dp[i][0] = dp[0][i] = i;
for (i = 1; i <= n; i++) {
int from = max(1, i-k), to = min(i+k, n);
for (j = from; j <= to; j++) {
if (a[i-1] == b[j-1]) // same character
dp[i][j] = dp[i-1][j-1];
// note that we don't allow letter substitutions
dp[i][j] = min(dp[i][j], 1 + dp[i][j-1]); // delete character j
dp[i][j] = min(dp[i][j], 1 + dp[i-1][j]); // insert character i
}
}
return dp[n][n];
}
How to improve space complexity as max size of string can go upto 10^5.
Please help.
Example : Let String be abc then answer is "NO" and if string is "abbcbba then answer is "YES"
The key observation is that if the first and last characters are the same then you needn't remove either of them; which is to say that xSTRINGx can be turned into a palindrome by removing a single letter if and only if STRING can (as long as STRING is at least one character long).
You want to define a method (excuse the Java syntax--I'm not a C++ coder):
boolean canMakePalindrome(String s, int startIndex, int endIndex, int toRemove);
which determines whether the part of the string from startIndex to endIndex-1 can be made into a palindrome by removing toRemove characters.
When you consider canMakePalindrome(s, i, j, r), then you can define it in terms of smaller problems like this:
If j-i is 1 then return true; if it's 0 then return true if and only if r is 0. The point here is that a 1-character string is a palindrome regardless of whether you remove a character; a 0-length string is a palindrome, but can't be made into one by removing a character (because there aren't any to remove).
If s[i] and s[j-1] are the same, then it's the same answer as canMakePalindrome(s, i+1, j-1, r).
If they're different, then either s[i] or s[j-1] needs removing. If toRemove is zero, then return false, because you haven't got any characters left to remove. If toRemove is 1, then return true if either canMakePalindrome(s, i+1, j, 0) or canMakePalindrome(s, i, j-1, 0). This is because you're now testing whether it's already a palindrome if you remove one of those two characters.
Now this can be coded up pretty easily, I think.
If you wanted to allow for removal of more than one character, you'd use the same idea, but using dynamic programming. With only one character to remove, dynamic programming will reduce the constant factor, but won't reduce the asymptotic time complexity (linear in the length of the string).
Psudocode (Something like this I havn't tested it at all).
It is based on detecting the conditions that you CAN remove a character, ie
There is exactly 1 wrong character
It is a palendrome (0 mismatch)
O(n) in time, O(1) in space.
bool foo(const std::string& s)
{
int i = 0;
int j = s.size()-1;
int mismatch_count = 0;
while (i < j)
{
if (s[i]==s[j])
{
i++; j--;
}
else
{
mismatch_count++;
if (mismatch_count > 1) break;
//override first preference if cannot find match for next character
if (s[i+1] == s[j] && ((i+2 >= j-1)||s[i+2]==s[j-1]))
{
i++;
}
else if (s[j-1]==s[i])
{
j--;
}
else
{
mismatch_count++; break;
}
}
}
//can only be a palendrome if you remove a character if there is exactly one mismatch
//or if a palendrome
return (mismatch_count == 1) || (mismatch_count == 0);
}
Here's a (slightly incomplete) solution which takes O(n) time and O(1) space.
// returns index to remove to make a palindrome; string::npos if not possible
size_t willYouBeMyPal(const string& str)
{
size_t toRemove = string::npos;
size_t len = str.length();
for (size_t c1 = 0, c2 = len - 1; c1 < c2; ++c1, --c2) {
if (str[c1] != str[c2]) {
if (toRemove != string::npos) {
return string::npos;
}
bool canRemove1 = str[c1 + 1] == str[c2];
bool canRemove2 = str[c1] == str[c2 - 1];
if (canRemove1 && canRemove2) {
abort(); // TODO: handle the case where both conditions are true
} else if (canRemove1) {
toRemove = c1++;
} else if (canRemove2) {
toRemove = c2--;
} else {
return string::npos;
}
}
}
// if str is a palindrome already, remove the middle char and it still is
if (toRemove == string::npos) {
toRemove = len / 2;
}
return toRemove;
}
Left as an exercise is what to do if you get this:
abxyxcxyba
The correct solution is:
ab_yxcxyba
But you might be led down a bad path:
abxyxcx_ba
So when you find the "next" character on both sides is a possible solution, you need to evaluate both possibilities.
I wrote a sample with O(n) complexity that works for the tests I threw at it. Not many though :D
The idea behind it is to ignore the first and last letters if they are the same, deleting one of them if they are not, and reasoning what happens when the string is small enough. The same result could be archived with a loop instead of the recursion, which would save some space (making it O(1)), but it's harder to understand and more error prone IMO.
bool palindrome_by_1(const string& word, int start, int end, bool removed = false) // Start includes, end excludes
{
if (end - start == 2){
if (!removed)
return true;
return word[start] == word[end - 1];
}
if (end - start == 1)
return true;
if (word[start] == word[end - 1])
return palindrome_by_1(word, start + 1, end - 1, removed);
// After this point we need to remove a letter
if (removed)
return false;
// When two letters don't match, try to eliminate one of them
return palindrome_by_1(word, start + 1, end, true) || palindrome_by_1(word, start, end - 1, true);
}
Checking if a single string is palindrome is O(n). You can implement a similar algorithm than moves two pointers, one from the start and another from the end. Move each pointer as long as the chars are the same, and on the first mismatch try to match which char you can skip, and keep moving both pointers as long as the rest chars are the same. Keep track of the first mismatch. This is O(n).
I hope my algorithm will pass without providing code.
If a word a1a2....an can be made a palindrome by removing ak, we can search for k as following:
If a1 != an, then the only possible k would be 1 or n. Just check if a1a2....an-1 or a2a3....an is a palindrome.
If a1 == an, next step is solving the same problem for a2....an-1. So we have a recursion here.
public static boolean pal(String s,int start,int end){
if(end-start==1||end==start)
return true;
if(s.charAt(start)==s.charAt(end))
return pal(s.substring(start+1, end),0,end-2);
else{
StringBuilder sb=new StringBuilder(s);
sb.deleteCharAt(start);
String x=new String(sb);
if(x.equals(sb.reverse().toString()))
return true;
StringBuilder sb2=new StringBuilder(s);
sb2.deleteCharAt(end);
String x2=new String(sb2);
if(x2.equals(sb2.reverse().toString()))
return true;
}
return false;
}
I tried the following,f and b are the indices at which characters do not match
int canwemakepal(char *str)//str input string
{
long int f,b,len,i,j;
int retval=0;
len=strlen(str);
f=0;b=len-1;
while(str[f]==str[b] && f<b)//continue matching till we dont get a mismatch
{
f++;b--;
}
if(f>=b)//if the index variable cross over each other, str is palindrome,answer is yes
{
retval=1;//true
}
else if(str[f+1]==str[b])//we get a mismatch,so check if removing character at str[f] will give us a palindrome
{
i=f+2;j=b-1;
while(str[i]==str[j] && i<j)
{
i++;j--;
}
if(i>=j)
retval=1;
else
retval=0;
}
else if(str[f]==str[b-1])//else check the same for str[b]
{
i=f+1;j=b-2;
while(str[i]==str[j] && i<j)
{
i++;j--;
}
if(i>=j)
retval=1;
else
retval=0;
}
else
retval=0;
return retval;
}
I created this solution,i tried with various input giving correct result,still not accepted as correct solution,Check it n let me know if m doing anything wrong!! Thanks in advance.
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
int t = s.nextInt();
String result[] = new String[t];
short i = 0;
while(i < t)
{
String str1 = s.next();
int length = str1.length();
String str2 = reverseString(str1);
if(str1.equals(str2))
{
result[i] = "Yes";
}
else
{
if(length == 2)
{
result[i] = "Yes";
}
else
{
int x = 0,y = length-1;
int counter = 0;
while(x<y)
{
if(str1.charAt(x) == str1.charAt(y))
{
x++;
y--;
}
else
{
counter ++;
if(str1.charAt(x) == str1.charAt(y-1))
{
y--;
}
else if(str1.charAt(x+1) == str1.charAt(y))
{
x++;
}
else
{
counter ++;
break;
}
}
}
if(counter >= 2)
{
result[i] = "No";
}
else
result[i]="Yes";
}
}
i++;
} // Loop over
for(int j=0; j<i;j++)
{
System.out.println(result[j]);
}
}
public static String reverseString(String original)
{
int length = original.length();
String reverse = "";
for ( int i = length - 1 ; i >= 0 ; i-- )
reverse = reverse + original.charAt(i);
return reverse;
}