I am writing up a function that reverses the order of the string "rdd" to "ddr",
when I run it I get an error that substring is out of range. Any help is appreciated!
#include <iostream>
#include <string>
#include <stdio.h>
#include <ctype.h>
using namespace std;
string reverse(const string & s);
int main() {
cout << reverse("rdd") << endl;
}
string reverse(const string & s) {
string rname(s);
for (unsigned i = rname.size()-1; i >= 0; i--) {
cout << rname[i];
}
return rname;
}
This is problem:
for (unsigned i = rname.size()-1; i >= 0; i--) {
Since i is unsigned, i-- will take it from 0 to UINT_MAX. The test i >= 0 can never fail for unsigned int. After this happens you access out of bounds in the loop body.
Instead the loop could look like:
for (unsigned i = rname.size(); i --> 0; )
(using the --> operator), or a better option would be to use C++ idioms:
for (auto it = rname.rbegin(); it != rname.rend(); ++it)
cout << *it;
Also see reverse adapters although that might be overkill for this case.
Your i is unsigned, therefore the condition i >= 0 is always satisfied. Consider:
unsigned int i = 0;
i--; // i will undeflow, and assume the largest unsigned number possible
if(i < 0) printf("Works?"); // suprise! It will be false and printf does not fire!
for (unsigned i = rname.size()-1; i >= 0; i--) {
The problem is in the above statement because -
rname.size() will return length of string. So this loop will run from rname.size()-1to 0(both including) then i-- will be UINT_MAX and condition which is i>=0, will always be true but your string size may less than UINT_MAX so it will return an error which is out of bound error.
Related
Consistently comparing digits symmetrically to its middle digit. If first number is bigger than the last , first is wining and I have to display it else I display last and that keep until I reach middle digit(this is if I have odd number of digits), if digit don't have anything to be compared with it wins automatically.
For example number is 13257 the answer is 7 5 2.
Another one 583241 the answer is 5 8 3.
For now I am only trying to catch when number of digits is odd. And got stuck.. This is my code. The problem is that this code don't display any numbers, but it compares them in the if statement(I checked while debugging).
#include <iostream>
using namespace std;
int countDigit(int n) {
int count = 0;
while (n != 0) {
count++;
n /= 10;
}
return count;
}
int main() {
int n;
cin >> n;
int middle;
int count = countDigit(n);
if (count % 2 == 0) {
cout<<"No mid digit exsist!!";
}
else {
int lastDigit = n % 10;
middle = (count + 1) / 2;
for (int i = 0; i < middle; i++) {
for (int j = lastDigit; j<middle; j--) {
if (i > j) {
cout << i <<' ';
}
else {
cout << j;
}
}
}
}
return 0;
}
An easier approach towards this, in my opinion, would be using strings. You can check the size of the string. If there are even number of characters, you can just compare the first half characters, with the last half. If there are odd numbers, then do the same just print the middle character.
Here's what I'd do for odd number of digits:
string n;
cin>>n;
int i,j;
for(i=0,j=n.size()-1;i<n.size()/2,j>=(n.size()+1)/2;i++,j--)
{
if(n[i]>n[j]) cout<<n[i]<<" ";
else cout<<n[j]<<" ";
}
cout<<n[n.size()/2]<<endl;
We analyze the requirements and then come up with a design.
If we have a number, consisting of digits, we want to compare "left" values with "right" values. So, start somehow at the left and the right index of digits in a number.
Look at this number: 123456789
Index: 012345678
Length: 9
in C and C++ indices start with 0.
So, what will we do?
Compare index 0 with index 8
Compare index 1 with index 7
Compare index 2 with index 6
Compare index 3 with index 5
Compare index 4 with index 4
So, the index from the left is running up and the index from the right is running down.
We continue as long as the left index is less than or equal the right index. All this can be done in a for or while loop.
It does not matter, wether the number of digits is odd or even.
Of course we also do need functions that return the length of a number and a digit of the number at a given position. But I see that you know already how to write these functions. So, I will not explain it further here.
I show you 3 different examples.
Ultra simple and very verbose. Very inefficient, because we do not have arrays.
Still simple, but more compressed. Very inefficient, because we do not have arrays.
C++ solution, not allowed in your case
Verbose
#include <iostream>
// Get the length of a number
unsigned int length(unsigned long long number) {
unsigned int length = 0;
while (number != 0) {
number /= 10;
++length;
}
return length;
}
// Get a digit at a given index of a number
unsigned int digitAt(unsigned int index, unsigned long long number) {
index = length(number) - index - 1;
unsigned int result = 0;
unsigned int count = 0;
while ((number != 0) && (count <= index)) {
result = number % 10;
number /= 10;
++count;
}
return result;
}
// Test
int main() {
unsigned long long number;
if (std::cin >> number) {
unsigned int indexLeft = 0;
unsigned int indexRight = length(number) - 1;
while (indexLeft <= indexRight) {
if (digitAt(indexLeft, number) > digitAt(indexRight, number)) {
std::cout << digitAt(indexLeft, number);
}
else {
std::cout << digitAt(indexRight, number);
}
++indexLeft;
--indexRight;
}
}
}
Compressed
#include <iostream>
// Get the length of a number
size_t length(unsigned long long number) {
size_t length{};
for (; number; number /= 10) ++length;
return length;
}
// Get a digit at a given index of a number
unsigned int digitAt(size_t index, unsigned long long number) {
index = length(number) - index - 1;
unsigned int result{}, count{};
for (; number and count <= index; ++count, number /= 10)
result = number % 10;
return result;
}
// Test
int main() {
if (unsigned long long number; std::cin >> number) {
// Iterate from left and right at the same time
for (size_t indexLeft{}, indexRight{ length(number) - 1 }; indexLeft <= indexRight; ++indexLeft, --indexRight)
std::cout << ((digitAt(indexLeft,number) > digitAt(indexRight, number)) ? digitAt(indexLeft, number) : digitAt(indexRight, number));
}
}
More modern C++
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
if (std::string numberAsString{}; std::getline(std::cin, numberAsString) and not numberAsString.empty() and
std::all_of(numberAsString.begin(), numberAsString.end(), std::isdigit)) {
for (size_t indexLeft{}, indexRight{ numberAsString.length() - 1 }; indexLeft <= indexRight; ++indexLeft, --indexRight)
std::cout << ((numberAsString[indexLeft] > numberAsString[indexRight]) ? numberAsString[indexLeft] : numberAsString[indexRight]);
}
}
You are trying to do something confusing with nested for-cycles. This is obviously wrong, because there is nothing “quadratic” (with respect to the number of digits) in the entire task. Also, your code doesn’t seem to contain anything that would determine the highest-order digit.
I would suggest that you start with something very simple: string’ify the number and then iterate over the digits in the string. This is obviously neither elegant nor particularly fast, but it will be a working solution to start with and you can improve it later.
BTW, the sooner you get out of the bad habit of using namespace std; the better. It is an antipattern, please avoid it.
Side note: There is no need to treat odd and even numbers of digits differently. Just let the algorithm compare the middle digit (if it exists) against itself and select it; no big deal. It is a tiny efficiency drawback in exchange for a big code simplicity benefit.
#include <cstdint>
#include <iostream>
#include <string>
using std::size_t;
using std::uint64_t;
uint64_t extract_digits(uint64_t source) {
const std::string digits{std::to_string(source)};
auto i = digits.begin();
auto j = digits.rbegin();
const auto iend = i + (digits.size() + 1) / 2;
uint64_t result{0};
for (; i < iend; ++i, ++j) {
result *= 10;
result += (*i > *j ? *i : *j) - '0';
}
return result;
}
int main() {
uint64_t n;
std::cin >> n;
std::cout << extract_digits(n) << std::endl;
}
If the task disallows the use of strings and arrays, you could try using pure arithmetics by constructing a “digit-inverted” version of the number and then iterating over both numbers using division and modulo. This will (still) have obvious limitations that stem from the data type size, some numbers cannot be inverted properly etc. (Use GNU MP for unlimited integers.)
#include <cstdint>
#include <iostream>
using std::size_t;
using std::uint64_t;
uint64_t extract_digits(uint64_t source) {
uint64_t inverted{0};
size_t count{0};
for (uint64_t div = source; div; div /= 10) {
inverted *= 10;
inverted += div % 10;
++count;
}
count += 1;
count /= 2;
uint64_t result{0};
if (count) for(;;) {
const uint64_t a{source % 10}, b{inverted % 10};
result *= 10;
result += a > b ? a : b;
if (!--count) break;
source /= 10;
inverted /= 10;
}
return result;
}
int main() {
uint64_t n;
std::cin >> n;
std::cout << extract_digits(n) << std::endl;
}
Last but not least, I would strongly suggest that you ask questions after you have something buildable and runnable. Having homework solved by someone else defeats the homework’s purpose.
This question already has answers here:
How to find whether the string is a Lapindrome? [closed]
(2 answers)
Closed 2 years ago.
The question is to check whether a given string is a lapindrome or not(CodeChef). According to the question, Lapindrome is defined as a string which when split in the middle, gives two halves having the same characters and same frequency of each character.
I have tried solving the problem using C++ with the code below
#include <iostream>
#include<cstring>
using namespace std;
bool lapindrome(char s[],int len){
int firstHalf=0,secondHalf=0;
char c;
for(int i=0,j=len-1;i<j;i++,j--){
firstHalf += int(s[i]);
secondHalf += int(s[j]);
}
if(firstHalf == secondHalf){
return true;
}
else
return false;
}
int main() {
// your code goes here
int t,len;
bool result;
char s[1000];
cin>>t;
while(t){
cin>>s;
len = strlen(s);
result = lapindrome(s,len);
if(result == true)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
--t;
}
return 0;
}
I have taken two count variables which will store the sum of ascii code of characters from first half and second half. Then those two variables are compared to check whether both the halves are equal or not.
I have tried the code on a couple of custom inputs and it works fine. But after I submit the code, the solution seems to be wrong.
Replace the lapindrome function to this one:
bool isLapindrome(std::string str)
{
int val1[MAX] = {0};
int val2[MAX] = {0};
int n = str.length();
if (n == 1)
return true;
for (int i = 0, j = n - 1; i < j; i++, j--)
{
val1[str[i] - 'a']++;
val2[str[j] - 'a']++;
}
for (int i = 0; i < MAX; i++)
if (val1[i] != val2[i])
return false;
return true;
}
Example Output
Input a string here: asdfsasd
The string is NOT a lapindrome.
---
Input a string here: asdfsdaf
The string is a lapindrome.
Enjoy!
You're not counting frequencies of the characters, only their sum. You could simply split the string into halves, create two maps for character frequencies of both sides e.g. std::map containing the count for each character. Then You can compare both maps with something like std::equal to check the complete equality of the maps (to see whether the halves are the same in terms of character frequency).
Instead of counting the frequency of characters (in the two halfs of input string) in two arrays or maps, it's actually sufficient to count them in one as well.
For this, negative counts have to be allowed.
Sample code:
#include <iostream>
#include <string>
#include <unordered_map>
bool isLapindrome(const std::string &text)
{
std::unordered_map<unsigned char, int> freq;
// iterate until index (growing from begin) and
// 2nd index (shrinking from end) cross over
for (size_t i = 0, j = text.size(); i < j--; ++i) {
++freq[(unsigned char)text[i]]; // count characters of 1st half positive
--freq[(unsigned char)text[j]]; // count characters of 2nd half negative
}
// check whether positive and negative counts didn't result in 0
// for at least one counted char
for (const std::pair<unsigned char, int> &entry : freq) {
if (entry.second != 0) return false;
}
// Otherwise, the frequencies were balanced.
return true;
}
int main()
{
auto check = [](const std::string &text) {
std::cout << '\'' << text << "': "
<< (isLapindrome(text) ? "yes" : "no")
<< '\n';
};
check("");
check("abaaab");
check("gaga");
check("abccab");
check("rotor");
check("xyzxy");
check("abbaab");
}
Output:
'': yes
'abaaab': yes
'gaga': yes
'abccab': yes
'rotor': yes
'xyzxy': yes
'abbaab': no
Live Demo on coliru
Note:
About the empty input string, I was a bit uncertain. If it's required to not to count as Lapindrome then an additional check is needed in isLapindrome(). This could be achieved with changing the final
return true;
to
return !text.empty(); // Empty input is considered as false.
The problem with your code was, that you only compare the sum of the characters. What's meant by frequency is that you have to count the occurrence of each character. Instead of counting frequencies in maps like in the other solutions here, you can simply sort and compare the two strings.
#include <iostream>
#include <string>
#include <algorithm>
bool lapindrome(const std::string& s) {
// true if size = 1, false if size = 0
if(s.size() <= 1) return (s.size());
std::string first_half = s.substr(0, s.size() / 2);
std::sort(first_half.begin(), first_half.end());
std::string second_half = s.substr(s.size() / 2 + s.size() % 2);
std::sort(second_half.begin(), second_half.end());
return first_half == second_half;
}
// here's a shorter hacky alternative:
bool lapindrome_short(std::string s) {
if (s.size() <= 1) return (s.size());
int half = s.size() / 2;
std::sort(s.begin(), s.begin() + half);
std::sort(s.rbegin(), s.rbegin() + half); // reverse half
return std::equal(s.begin(), s.begin() + half, s.rbegin());
}
int main() {
int count;
std::string input;
std::cin >> count;
while(count--) {
std::cin >> input;
std::cout << input << ": "
<< (lapindrome(input) ? "YES" : "NO") << std::endl;
}
return 0;
}
Live Demo
I have a string variable of all digits that I am parsing into an array called hugeInt. Doing this in a loop where I pick off one digit at a time out of the string and trying to put into the array. I have tried the code below which uses std::stoi directly and it gives me an error I think because it is a string. So I also tried converting the digit using const char *digit = strInt[j].c_str() but this gives me an error also. So how do I get what I thought was a one character string (which is a digit) from a real string to convert to an int. code below. My .h file
// HugeInteger.h
#ifndef HUGEINTEGER_H
#define HUGEINTEGER_H
#include <array>
class HugeInteger {
private:
static const int SIZE = 40;
std::array<short int,SIZE> hugeInt;
public:
HugeInteger(long = 0);
HugeInteger(std::string strInt);
void displayHugeInt();
};
#endif
my implementation code
// HugeInteger.cpp
#include <iostream>
#include <stdexcept>
#include "HugeInteger.h"
HugeInteger::HugeInteger(long int num) {
for (short &element : hugeInt) {
element = 0;
}
for (int i = SIZE-1; i >= 0; i--) {
hugeInt[i] = num % 10;
num /= 10;
if (num == 0) {
break;
}
}
}
HugeInteger::HugeInteger(std::string strInt) {
for (short &element : hugeInt) {
element = 0;
}
if (strInt.length() > 40) {
throw std::invalid_argument("String integer is over 40 digits - too large.");
}
for (int i = SIZE-1, j = strInt.length()-1; j >= 0; i--, j--) {
if (isdigit(strInt[j])) {
hugeInt[i] = std::stoi(strInt[j]);
}
else {
throw std::invalid_argument("String integer has non digit characters.");
}
}
}
void HugeInteger::displayHugeInt() {
bool displayStarted = false;
for (short &element : hugeInt) {
if (!displayStarted) {
if (element == 0) {
continue;
}
else {
std::cout << element;
displayStarted = true;
}
}
else {
std::cout << element;
}
}
std::cout << std::endl;
}
The problem is in the second constructor (for a string) in the for loop where hugeInt[i] = std::stoi(strInt[j]); is. Any help or suggestions welcomed and appreciated.
strInt[j] is a char, not a std::string. We can't std::stoi a single character, but since we know it is is a digit (thanks to isdigit(strInt[j])), we can cheat like heck and
hugeInt[i] = strInt[j] - '0';
to get the value of the digit because C++ guarantees that all digits are encoded to ascend from '0' and are contiguous. This means that '0' - '0' will be 0. '1' - '0' will be 1. '2' - '0' will be 2, and so on.
Actually since strInt[j] is a ch, I had to use a different string constructor. This one compiles and runs correctly hugeInt[i] = std::stoi(std::string(1,strInt[j]));.
How to convert string like 3 word 12 with word to a int only contain number 312 without using stoi in C++? My Codeblode gave me an error stoi is not a member of std when I tried to use it.
Thank you in advance!
Go through the line and skip non-digit symbols. And for digits use -'0' conversion and *10 shift approach. E.G.:
#include <stdio.h>
#include <ctype.h>
//or cctype to use isdigit()
#include <string.h>
//or cstring to use strlen()
int main()
{
char str[] = "3 word 12 with word"; // can be any string
int result = 0; // to store resulting number
// begin of solution
for (int i = 0; i < strlen(str); i++)
{
if (isdigit(str[i]))
{
result *= 10;
result += str[i] - int('0');
}
}
// end of solution
printf("%d\n", result);
return 0;
}
Same idea as in VolAnd's answer. Just, because the question is tagged c++, using some STL stuff.
#include <iostream>
#include <numeric>
#include <string>
using namespace std;
int main(){
std::string input("3 word 12 with word");
int num = std::accumulate(input.begin(), input.end(), 0,
[](int val, const char elem) {
if (isdigit(elem)) {
val = val*10 + (elem-'0');
}
return val;
}
);
std::cout << num << std::endl;
return 0;
}
see http://en.cppreference.com/w/cpp/algorithm/accumulate
note: It gets slightly more interesting if you want to allow a leading minus sign....
And using boost::adaptors::filter(rng, pred) on this one would be fun but slightly overdoing it ;-)
Assuming that s is your initial string.
int toInt(string s) {
string digits;
for(size_t i = 0; i < s.size(); i++)
if(s[i] >= '0' && s[i] <= '9')
digits.push_back(s[i]);
int res = 0;
for(size_t i = 0; i < digits.size(); i++)
res = res * 10 + digits[i] - '0';
return res;
}
Leading zeros are not a problem.
Note however that it is possible to receive an overflow if the resulting digits string will contain a big number.
I'm not trying to ask you guys to help me to do homework because i've do much research and also try to program it myself but still i encounter problem and i think so far i've know where the problem is but still no solution can be figure out by me :
The Code
#include <iostream>
#include <string>
#include <cmath>
int main(void)
{
using namespace std;
int num;
int max;
string answer = "";
cin >> num;
for(int i = 2 ; i < num ; i++)
{
max = sqrt(i);
if(max < 2) // This must be done beacuse sqrt(2) and sqrt(3)
{ // is 1 which will make it become nonprime.
answer += i;
answer += ' ';
continue;
}
for(int j = 2 ; j <= max ; j++) // Trial division ,divide each by integer
{ // more than 1 and less than sqrt(oftheinteger)
if(i % j == 0)
break;
else if(j == max)
{
answer += i + " ";
answer += ' ';
}
}
}
cout <<"The answer is " << answer ;
return 0;
}
The Question
1.)This program will prompt for a number from user and return all the prime number before it(e.g if user input 9 : then the answer is 2 , 3 , 5 , 7).
2.)I think the wrong part is the string and integer concatenation , till now i still puzzle how to concat string and integer in C++(Previous Javascript programmer so i'm accustomed to using + as string-int concat operator)
3.)Beside the problem i mention above , so far i've go through the code and find none of other problem exist.If any expert manage to find any , mind to point it out to enlighten me??
4.)If there's any mistake in terms of coding or algorithm or anything done by me , please don't hesitate to point it out , i'm willing to learn.
Thanks for spending time reading my question
The usual way to perform formatting in C++ is to use streams.
In this situation, you can use a std::stringstream to accumulate the results, and then convert it into a string when you do the final printing.
Include sstream to get the required type and function declarations:
#include <sstream>
Declare answer to be a std::stringstream instead of a std::string:
stringstream answer;
and then wherever you have:
answer += bla;
, replace it with:
answer << bla;
To get a std::string out of answer, use answer.str():
cout << "The answer is " << answer.str();
If you have to store your complete output before printing it out (I would probably print it as I go, but up to you), a simple way is to use stringstreams.
In this case, rather than answer being an std::string, we can change it to an std::stringstream (and include the <sstream> header).
Now rather than having:
answer += i;
We can just make a simple change and have:
answer << i;
Just as you would if you were printing to cout (which is an ostream).
So basically, += in your code would become <<.
Similar to printing to cout, you can also chain together such as:
answer << a << b
Now to print your stringstream to cout, all you'd need to do is:
cout << my_stringstream.str()
See how you go. I don't want to provide you with the complete since it's homework.
You can go around the string concatenation problem if you just print what you have so far:
int main()
{
int num;
int max;
string answer = "";
cin >> num;
cout << "The answer is ";
for(int i = 2 ; i < num ; i++)
{
max = sqrt((double)i);
if(max < 2) // This must be done beacuse sqrt(2) and sqrt(3)
{ // is 1 which will make it become nonprime.
cout << i << ' ';
continue;
}
for(int j = 2 ; j <= max ; j++) // Trial division ,divide each by integer
{ // more than 1 and less than sqrt(oftheinteger)
if(i % j == 0)
break;
else if(j == max)
{
cout << i << ' ';
}
}
}
return 0;
}
As other mentioned one way to do concatenation is std::stringstream.
it's not very beautiful, but it works. I use a general library "genlib.h", I'm not sure what you use, so you might need to replace that or I can send it to you.
#include "genlib.h"
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
bool IsPrime(int num);
int main()
{
int num;
int i = 2;
cout << "Enter an integer to print previous primes up to: ";
cin >> num;
cout << endl << "The primes numbers are: " << endl;
while(i < num){
if (IsPrime(i) == true){
cout << i << ", ";
}
i++;
}
return 0;
}
bool IsPrime(int num){
if((num == 2) || (num == 3)) {
return true;
}else if ((num % 2) == 0){
return false;
}else{
for (int i = 3; i < sqrt(double(num))+1; i++){
if ((num % i) == 0){
return false;
}
return true;
}
}
}
you need tn convert the integer to string (char*, exactly) using :
answer += itoa(i);
or using standard function :
char str[10];
sprintf(str,"%d",i);
answer += str;
and if you want to avoid using sqrt function, you can replace :
for(int i = 2 ; i < num ; i++)
{
max = sqrt(i);
with :
for(int i = 2 ; i*i < num ; i++)
{
The problem is that the + operator of std::string accepts strings as parameter, pointers to an array of chars, or single chars.
When a single char is used in the + operator, then a single char is added to the end of the string.
Your C++ compiler converts the integer to char before passing it to the operator + (both char and int are signed integer values, with different bit number), and therefore your string should contain a strange char instead of the numbers.
You should explicitly convert the integer to string before adding it to the string, as suggested in other answers, or just output everything to std::cout (its operator << accepts also int as parameter and convert them correctly to string).
As a side note, you should receive a warning from the C++ compiler that your integer i has been converted to char when you add it to the string (the integer has been converted to a lower resolution or something like that). This is why is always good to set the warning level to high and try to produce applications that don't generate any warning during the compilation.
You could perform a faster lookup by storing your known prime numbers in a set. These two sample functions should do the trick:
#include <iostream>
#include <set>
#include <sstream>
#include <string>
typedef std::set< unsigned int > PrimeNumbers;
bool isComposite(unsigned int n, const PrimeNumbers& knownPrimeNumbers)
{
PrimeNumbers::const_iterator itEnd = knownPrimeNumbers.end();
for (PrimeNumbers::const_iterator it = knownPrimeNumbers.begin();
it != itEnd; ++it)
{
if (n % *it == 0)
return true;
}
return false;
}
void findPrimeNumbers(unsigned int n, PrimeNumbers& primeNumbers)
{
for (unsigned int i = 2; i <= n; ++i)
{
if (!isComposite(i, primeNumbers))
primeNumbers.insert(i);
}
}
You could then invoke findPrimeNumbers like so:
unsigned int n;
std::cout << "n? ";
std::cin >> n;
PrimeNumbers primeNumbers;
findPrimeNumbers(n, primeNumbers);
And if you really need to dump the result in a string:
std::stringstream stringStream;
int i = 0;
PrimeNumbers::const_iterator itEnd = primeNumbers.end();
for (PrimeNumbers::const_iterator it = primeNumbers.begin();
it != itEnd; ++it, ++i)
{
stringStream << *it;
if (i < primeNumbers.size() - 1)
stringStream << ", ";
}
std::cout << stringStream.str() << std::endl;
Since you're willing to learn, you can perform both join and split algorithm on string/sequence by using Boost String Algorithms Library.
This solution is not perfect, but it's basic C++ usage (simple containers, no structure, only one typedef, ...).
Feel free to compare your results with The First 1000 Primes.
Good luck