std::stoi only converts first few characters - c++

I am using stoi in one of my functions with the intent of converting a string of numbers into an integer. I was about halfway through a homework problem but then I ran into this. Oddly, if the number has an even number of characters, stoi only converts the first half. Any help would be greatly appreciated!
Code:
#include <fstream>
#include <vector>
#include <string>
using namespace std;
string start;
string endD;
int sDigit;
int eDigit;
int i;
vector<int> palindromes;
void construct(int layer, int digits, string prev)
{
string temp = prev;
if(layer > (digits % 2) + digits/2)
{
short a = (short) digits/2;
for(int i = a; i >= 0; i--)
{
if(i == a && digits % 2 == 1)
{
continue;
}
else
{
temp.push_back(temp[i]);
}
}
cout << temp << " " << stoi(temp) << endl; // Output is here
palindromes.push_back(stoi(temp));
}
else if(layer == 1 && digits == sDigit)
{
for(int i = start[0] - '0'; i < 10; i++)
{
temp[0] = i + '0';
construct(layer + 1, digits, temp);
}
}
else if(layer == 1 && digits == eDigit)
{
for(int i = '1'; i <= endD[0]; i++)
{
temp[0] = i;
construct(layer + 1, digits, temp);
temp = prev;
}
}
else if(layer == 1)
{
for(int i = 1; i < 10; i++)
{
temp[0] = '0' + i;
construct(layer + 1, digits, temp);
temp = prev;
}
}
else
{
for(int i = 0; i < 10; i++)
{
temp.push_back(i + '0');
construct(layer + 1, digits, temp);
temp = prev;
}
}
}
int main()
{
int startD, endDD;
cin >> startD >> endDD;
start = to_string(startD);
endD = to_string(endDD);
int tempS = startD;
int tempE = endDD;
while(tempS != 0)
{
tempS /= 10;
sDigit++;
}
while(tempE != 0)
{
tempE /= 10;
eDigit++;
}
for(int i = sDigit; i <= eDigit; i++)
{
construct(1, i, "x");
}
for(int i = 0; i < palindromes.size(); i++)
{
//cout << palindromes[i] << endl;
}
}```
Input: 1 1000
Output:

Your code has undefined behavior because in this line
temp.push_back(temp[i]);
you are accessing temp out-of-bounds. You can see this by adding a line
std::cout << "check " << i << " " << temp.size() << "\n";
just before that line.
Output will be (see here):
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
check 1 1
check 0 2
1
...
When the size is 1 the last valid index is 0. The problem is not with stoi but with the logic of your algorithm.

Related

Why does the code below causes Segmentation Fault (SIGSEGV)?

PROBLEM STATEMENT
You are given a strictly increasing sequence of integers A1,A2,…,AN. Your task is to compress this sequence.
The compressed form of this sequence is a sequence of ranges separated by commas (characters ','). A range is either an integer or a pair of integers separated by three dots (the string "..."). When each range a...b in the compressed form is decompressed into the subsequence (a,a+1,…,b), we should obtain the (comma-separated) sequence A again.
For each maximal contiguous subsequence (a,a+1,…,b) of A such that b≥a+2, the compressed form of A must contain the range a...b; if b≤a+1, such a sequence should not be compressed into a range. A contiguous subsequence is maximal if it cannot be extended by at least one element of A next to it. It can be proved that the compressed form of any sequence is unique (i.e. well-defined).
Input
The first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains a single integer N.
The second line contains N space-separated integers A1,A2,…,AN.
Output
For each test case, print a single line containing one string ― the compressed form of the given sequence.
Constraints
1≤T≤100
1≤N≤100
1 ≤ Ai ≤ 1000 for each valid i
A1 < A2 < …... <AN
Subtasks
Subtask #1 (100 points): Original constraints
Example Input
3
12
1 2 3 5 6 8 9 10 11 12 15 17
4
4 5 7 8
1
4
Example Output
1...3,5,6,8...12,15,17
4,5,7,8
4
MY Code:
#include <bits/stdc++.h>
using namespace std;
bool b[1005];
int a[1005];
int main()
{
int test, i, j, size, count;
cin >> test;
while (test--)
{
for (i = 0; i < 1005; i++)
b[i] = false;
cin >> size;
for (i = 0; i < size; i++)
{
cin >> a[i];
b[a[i]] = true;
}
for (i = 0; i < 1005; i++)
{
if (b[i] == true)
{
cout << i;
j = i;
count = 0;
while (b[j] == true)
{
count++;
j++;
}
if (count > 2)
{
i = j;
if ((j - 1) != a[size - 1])
cout << "..." << i - 1 << ",";
else
cout << "..." << i - 1;
}
if (count == 2)
{
i = j;
if ((j - 1) != a[size - 1])
cout << "," << i - 1 << ",";
else
cout << "," << i - 1;
}
if (count == 1 && ((j - 1) != a[size - 1]))
cout << ",";
}
}
}
return 0;
}
}
MY Question:
Above code runs perfectly on my device giving desired output. But when I am submitting this solution to
Online Judge , it says segmentation fault. It's sure that fundamentally I am accessing the memory incorrectly. Could you please show me where it is?
b is defined a bool[1005]
In this part
for(i=0 ; i<4000 ; i++)
b[i] = false;
You are writing false value 4000 times, exceeding the array size.
Overwriting past the array is allowed on the compiler but will have undefined behaviour in runtime.
In short: it can or can not cause a segfault.
Here is another approach given that the input data is in a file input.txt:
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
class Reader {
public:
Reader(const std::string& filename) :
filename_(std::move(filename)), is_(filename_)
{
is_.exceptions( std::ifstream::failbit | std::ifstream::badbit );
}
int get_N() {
int N;
is_ >> N;
return N;
}
std::vector<int> get_ints(int N) {
std::vector<int> v;
v.reserve(N);
for (int i = 0; i < N; i++ ) {
int value;
is_ >> value;
v.push_back(value);
}
return v;
}
int get_num_cases() {
int num_cases;
is_ >> num_cases;
return num_cases;
}
private:
std::string filename_;
std::ifstream is_;
};
bool start_range_cur( std::vector<int> &v, int j, int N )
{
if ( j>= (N - 2) ) return false;
return ((v[j+1] - v[j]) == 1) && ((v[j+2] - v[j+1]) == 1);
}
bool in_range_cur( std::vector<int> &v, int j )
{
return (v[j+1] - v[j]) == 1;
}
void print_range( int min, int max, bool print_comma)
{
std::cout << min << ".." << max;
if (print_comma) std::cout << ",";
}
void print_single(int val, bool print_comma)
{
std::cout << val;
if (print_comma) {
std::cout << ",";
}
}
int main() {
Reader is {"input.txt"};
int num_cases = is.get_num_cases();
for (int i = 0; i < num_cases; i++) {
int N = is.get_N();
std::vector<int> v = is.get_ints(N);
bool in_range = false;
int range_start;
for( int j = 0; j< N; j++ ) {
if (in_range) {
if (j == (N - 1)) {
print_range(range_start, v[j], false);
}
else if (in_range_cur(v, j)) {
continue;
}
else {
print_range(range_start, v[j], true);
in_range = false;
}
}
else {
if (j == (N - 1)) {
print_single(v[j], false);
}
else if (start_range_cur(v, j, N)) {
in_range = true;
range_start = v[j];
}
else {
print_single(v[j], true);
}
}
}
std::cout << '\n';
}
return 0;
}

Parenthesized Expression (Infix and Post fix) Conversion and Evaluation

I have the below code working fine but outputs only 2nd input, not 1st or 3rd.
My code should get fully parenthesized expression from console and convert it to postfix expression and then that postfix expression should be evaluated in modulo 10.Therefore, all results (including intermediate results) are single decimal digits in {0, 1, …, 9}. I need to store only single digits in the stack.
My inputs and outputs are shown in below.I only got 2nd input correctly.
Please advise.
Expression 1: (((2+(5^2))+7)
Answer:
252^+7+
4 in modulo 10
Expression 2: ((((2+5)*7)+((9*3)*2))^2)
Answer:
25+7*93*2*+2^
9 in modulo 10
Expression 3: ((((2*3)*(4*6))*7)+(((7+8)+9)*((2+4)*((7+8)+9))))
Answer:
23*46*7*789++24+78+9+**+
4 in modulo 10
My code:
#include <iostream>
#include <string>
#include<sstream>
using namespace std;
class STACK {
private:
char *s;
int N;
public:
STACK(int maxN) {
s = new char[maxN];
N = 0;
}
int empty() const {
return N == 0;
}
void push(char item) {
s[N++] = item;
}
char pop() {
return s[--N];
}
};
int main() {
string infixExpr;
string postfixExpr = "";
cout << "Enter infix expression:" << endl;
cin >> infixExpr; //converting to postfix read from the input
int N = infixExpr.size(); //strncpy(a, infixExpr.c_str(), N);
STACK ops(N);
char ch;
for (int i = 0; i < N; i++) {
if (infixExpr[i] == ')')
{
ch = ops.pop();
postfixExpr.push_back(ch);
}
if ((infixExpr[i] == '+') || (infixExpr[i] == '*') || (infixExpr[i] == '^'))
ops.push(infixExpr[i]);
if ((infixExpr[i] >= '0') && (infixExpr[i] <= '9'))
{
//cout << infixExpr[i] << " ";
postfixExpr.push_back(infixExpr[i]);
}
}
cout <<"Answer :"<<endl;
cout <<postfixExpr <<endl; //evaluate post fix expression
N = postfixExpr.size();
STACK save(N);
int result;
int num;
int count = 0;
string temp = "";
for (int i = 0; i < N; i++) {
// cout << " Expr[i] " << postfixExpr[i] << endl;
if (postfixExpr[i] == '+')
save.push((save.pop() + save.pop()) % 10);
if (postfixExpr[i] == '*')
save.push((save.pop() * save.pop()) % 10);
if (postfixExpr[i] == '^') {
count = save.pop() - '0';
num = save.pop() - '0'; //cout << result << "- " <<"-" <<count<<endl;
result = 1;
for(int j = 1; j <= count; j++)
{
result = result * num;
result = result % 10;
}
stringstream convert;
convert << result;//add the value of Number to the characters in the stream
temp = convert.str();//set Result to the content of the stream
save.push(temp[0]);
}
if ((postfixExpr[i] >= '0') && (postfixExpr[i] <= '9'))
{
save.push(postfixExpr[i]);
}
}
cout << save.pop() <<" in module 10"<< endl;
return 1;
}

C++ binary input as a string to a decimal

I am trying to write a code that takes a binary number input as a string and will only accept 1's or 0's if not there should be an error message displayed. Then it should go through a loop digit by digit to convert the binary number as a string to decimal. I cant seem to get it right I have the fact that it will only accept 1's or 0's correct. But then when it gets into the calculations something messes up and I cant seem to get it correct. Currently this is the closest I believe I have to getting it working. could anyone give me a hint or help me with what i am doing wrong?
#include <iostream>
#include <string>
using namespace std;
string a;
int input();
int main()
{
input();
int decimal, x= 0, length, total = 0;
length = a.length();
// atempting to make it put the digits through a formula backwords.
for (int i = length; i >= 0; i--)
{
// Trying to make it only add the 2^x if the number is 1
if (a[i] = '1')
{
//should make total equal to the old total plus 2^x if a[i] = 1
total = total + pow(x,2);
}
//trying to let the power start at 0 and go up each run of the loop
x++;
}
cout << endl << total;
int stop;
cin >> stop;
return 0;
}
int input()
{
int x, x2, count, repeat = 0;
while (repeat == 0)
{
cout << "Enter a string representing a binary number => ";
cin >> a;
count = a.length();
for (x = 0; x < count; x++)
{
if (a[x] != '0' && a[x] != '1')
{
cout << a << " is not a string representing a binary number>" << endl;
repeat = 0;
break;
}
else
repeat = 1;
}
}
return 0;
}
I don't think that pow suits for integer calculation. In this case, you can use shift operator.
a[i] = '1' sets the value of a[i] to '1' and return '1', which is always true.
You shouldn't access a[length], which should be meaningless.
fixed code:
int main()
{
input();
int decimal, x= 0, length, total = 0;
length = a.length();
// atempting to make it put the digits through a formula backwords.
for (int i = length - 1; i >= 0; i--)
{
// Trying to make it only add the 2^x if the number is 1
if (a[i] == '1')
{
//should make total equal to the old total plus 2^x if a[i] = 1
total = total + (1 << x);
}
//trying to let the power start at 0 and go up each run of the loop
x++;
}
cout << endl << total;
int stop;
cin >> stop;
return 0;
}
I would use this approach...
#include <iostream>
using namespace std;
int main()
{
string str{ "10110011" }; // max length can be sizeof(int) X 8
int dec = 0, mask = 1;
for (int i = str.length() - 1; i >= 0; i--) {
if (str[i] == '1') {
dec |= mask;
}
mask <<= 1;
}
cout << "Decimal number is: " << dec;
// system("pause");
return 0;
}
Works for binary strings up to 32 bits. Swap out integer for long to get 64 bits.
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
string getBinaryString(int value, unsigned int length, bool reverse) {
string output = string(length, '0');
if (!reverse) {
for (unsigned int i = 0; i < length; i++) {
if ((value & (1 << i)) != 0) {
output[i] = '1';
}
}
}
else {
for (unsigned int i = 0; i < length; i++) {
if ((value & (1 << (length - i - 1))) != 0) {
output[i] = '1';
}
}
}
return output;
}
unsigned long getInteger(const string& input, size_t lsbindex, size_t msbindex) {
unsigned long val = 0;
unsigned int offset = 0;
if (lsbindex > msbindex) {
size_t length = lsbindex - msbindex;
for (size_t i = msbindex; i <= lsbindex; i++, offset++) {
if (input[i] == '1') {
val |= (1 << (length - offset));
}
}
}
else { //lsbindex < msbindex
for (size_t i = lsbindex; i <= msbindex; i++, offset++) {
if (input[i] == '1') {
val |= (1 << offset);
}
}
}
return val;
}
int main() {
int value = 23;
cout << value << ": " << getBinaryString(value, 5, false) << endl;
string str = "01011";
cout << str << ": " << getInteger(str, 1, 3) << endl;
}
I see multiple misstages in your code.
Your for-loop should start at i = length - 1 instead of i = length.
a[i] = '1' sets a[i] to '1' and does not compare it.
pow(x,2) means and not . pow is also not designed for integer operations. Use 2*2*... or 1<<e instead.
Also there are shorter ways to achieve it. Here is a example how I would do it:
std::size_t fromBinaryString(const std::string &str)
{
std::size_t result = 0;
for (std::size_t i = 0; i < str.size(); ++i)
{
// '0' - '0' == 0 and '1' - '0' == 1.
// If you don't want to assume that, you can use if or switch
result = (result << 1) + str[i] - '0';
}
return result;
}

C++ Error: Line 1440 Expression: string subscript out of range

The program builds and runs, however after entering the first integer and pressing enter then the error pop up box appears, then after pressing ignore and entering the second integer and pressing enter the pop up box appears and after pressing ignore it returns the correct answer. I am at my wits end with this can somebody help me fix the pop up box thing.
#include "stdafx.h"
#include <iostream>
#include <cctype>
#include <string>
using namespace std;
#define numbers 100
class largeintegers {
public:
largeintegers();
void
Input();
void
Output();
largeintegers
operator+(largeintegers);
largeintegers
operator-(largeintegers);
largeintegers
operator*(largeintegers);
int
operator==(largeintegers);
private:
int integer[numbers];
int len;
};
void largeintegers::Output() {
int i;
for (i = len - 1; i >= 0; i--)
cout << integer[i];
}
void largeintegers::Input() {
string in;
int i, j, k;
cout << "Enter any number:";
cin >> in;
for (i = 0; in[i] != '\0'; i++)
;
len = i;
k = 0;
for (j = i - 1; j >= 0; j--)
integer[j] = in[k++] - 48;
}
largeintegers::largeintegers() {
for (int i = 0; i < numbers; i++)
integer[i] = 0;
len = numbers - 1;
}
int largeintegers::operator==(largeintegers op2) {
int i;
if (len < op2.len) return -1;
if (op2.len < len) return 1;
for (i = len - 1; i >= 0; i--)
if (integer[i] < op2.integer[i])
return -1;
else if (op2.integer[i] < integer[i]) return 1;
return 0;
}
largeintegers largeintegers::operator+(largeintegers op2) {
largeintegers temp;
int carry = 0;
int c, i;
if (len > op2.len)
c = len;
else
c = op2.len;
for (i = 0; i < c; i++) {
temp.integer[i] = integer[i] + op2.integer[i] + carry;
if (temp.integer[i] > 9) {
temp.integer[i] %= 10;
carry = 1;
} else
carry = 0;
}
if (carry == 1) {
temp.len = c + 1;
if (temp.len >= numbers)
cout << "***OVERFLOW*****\n";
else
temp.integer[i] = carry;
} else
temp.len = c;
return temp;
}
largeintegers largeintegers::operator-(largeintegers op2) {
largeintegers temp;
int c;
if (len > op2.len)
c = len;
else
c = op2.len;
int borrow = 0;
for (int i = c; i >= 0; i--)
if (borrow == 0) {
if (integer[i] >= op2.integer[i])
temp.integer[i] = integer[i] - op2.integer[i];
else {
borrow = 1;
temp.integer[i] = integer[i] + 10 - op2.integer[i];
}
} else {
borrow = 0;
if (integer[i] - 1 >= op2.integer[i])
temp.integer[i] = integer[i] - 1 - op2.integer[i];
else {
borrow = 1;
temp.integer[i] = integer[i] - 1 + 10 - op2.integer[i];
}
}
temp.len = c;
return temp;
}
largeintegers largeintegers::operator*(largeintegers op2) {
largeintegers temp;
int i, j, k, tmp, m = 0;
for (i = 0; i < op2.len; i++) {
k = i;
for (j = 0; j < len; j++) {
tmp = integer[j] * op2.integer[i];
temp.integer[k] = temp.integer[k] + tmp;
temp.integer[k + 1] = temp.integer[k + 1] + temp.integer[k] / 10;
temp.integer[k] %= 10;
k++;
if (k > m) m = k;
}
}
temp.len = m;
if (temp.len > numbers) cout << "***OVERFLOW*****\n";
return temp;
}
using namespace std;
int main() {
int c;
largeintegers num1, num2, result;
num1.Input();
num2.Input();
num1.Output();
cout << " + ";
num2.Output();
result = num1 + num2;
cout << " = ";
result.Output();
cout << "\n\n";
num1.Output();
cout << " - ";
num2.Output();
result = num1 - num2;
cout << " = ";
result.Output();
cout << "\n\n";
num1.Output();
cout << " * ";
num2.Output();
result = num1 * num2;
cout << " = ";
result.Output();
cout << "\n\n";
c = num1 == num2;
num1.Output();
switch (c) {
case -1:
cout << " is less than ";
break;
case 0:
cout << " is equal to ";
break;
case 1:
cout << " is greater than ";
break;
}
num2.Output();
cout << "\n\n";
system("pause");
}
It seems you are falling victim to the difference between C-style strings and C++ strings. C-style strings are a series of chars followed by a zero (or null) byte. C++ strings are objects that contain a series of characters (usually char, but eventually this will be an assumption you should break) and that know their own length. C++ strings can contain null bytes in the middle of themselves without problem.
To loop through all of the characters of a C++-style string, you can do one of a number of things:
You can use the .size() or .length() members of a string variable to find the number of characters in it, as in for (int i=0; i<str.size(); i++) { char c = str[i];
You can use .begin() and .end() to get iterators to the beginning and end of the string, respectively. A for loop in the form for (std::string::iterator it=str.begin(); it!=str.end(); ++it) will loop you through the members of the string by accessing *it.
If you're using C++11, you can use the for loop construct as follows: for (auto c: str) where c will be of the type of a character of the string str.
In the future, to solve problems like these, you can try using the debugger to see what happens when your program crashes or hits an exception. You likely would find that inside of largeintegers::Input() you running into either a memory access violation or some other problem.
Finally, as a future-looking criticism, you should not use C-style arrays (where you say int integer[ numbers ];) in favor of using C++-style containers, such as vector. A vector is a series of objects (such as ints) that can expand as needed.

Palindrome Function

I need to rewrite the program to use a function isPalindrome. It needs to input a 5 digit integer and return a boolean (true if it is a palindrome, false if it is not), and it cannot contain any cout statements. I am not sure how I would do this without a cout function. Here is my code:
#include <iostream>
using namespace std;
int main()
{
int number, digit1, digit2, digit3, digit4, digit5;
cout << "\nEnter a 5-digit integer: ";
cin >> number;
//Break down input number into individual digits:
digit1 = number / 10000;
digit2 = number % 10000 / 1000;
digit3 = number % 10000 / 100;
digit4 = number % 10000 / 10;
digit5 = number % 10;
if ( digit1 == digit5 && digit2 == digit4 )
cout << number <<" is a palindrome.\n";
else
cout << number << " is not a palindrome.\n";
return 0;
}
int isPalindrome ()
{
}
This should help get you started (without ruining too much of the fun)
int main(){
//accept integer input using cin
if(isPalindrome(input))
cout << "yaay!";
else
cout << "nooouuu!";
}
bool isPalindrome (int input)
{
//test things here
return ( digit1 == digit5 && digit2 == digit4 )
// ^ returns true if condition satisfied
}
Additionally, your way of separating out the digits is incorrect. It should be:
digit1 = number/10000 % 10;
digit2 = number/1000 % 10;
digit3 = number/100 % 10;
digit4 = number/10 % 10;
digit5 = number % 10;
Ofcourse, the above should actually be in a loop.
It doesn't have to be specified how many digits does the number contain. You can try something like this:
bool isPalindrome(int number) {
int reverse = 0, copy = number;
while(copy != 0) {
reverse = reverse*10 + copy%10;
copy /= 10;
}
return number == reverse;
}
string s;
cout<<"\nEnter a string : " ;
cin>>s;
int length = s.length();
char* arr = new char();
int k = length;
for(int i = 0 ; i <= length ; i++)
{
arr[i] = s[k];
k -= 1;
}
if(!palindrome(s, arr, length))
{
cout<<"\nNot Palindrome\n";
}
else
{
cout<<"\nPalindrome\n";
}
}
bool palindrome(string& s, char* arr, int length)
{
int j = 0;
for(int i = 1 ; i <= length; i++)
{
if(arr[i]!= s[j])
{
return false;
}
j++;
}
return true;
}