I'm an absolute beginner in c++. Literally. It's just been a week.
Today I was writing a program to test how many iterations are needed to make a certain number palindromic.
Here is the code:
#include <iostream>
#include <string>
#include <algorithm>
/* This program calculates the steps needed
to make a certain number palindromic.
It is designed to output the values for
numbers 1 to 1000
*/
using namespace std;
class number
{
public:
string value;
void reverse();
};
void number::reverse()
{
std::reverse(value.begin(),value.end());
}
void palindrome(number num)
{
string n=num.value;
number reversenum, numsum, numsumreverse;
reversenum=num;
reversenum.reverse();
numsum.value=num.value;
numsumreverse.value=numsum.value;
numsumreverse.reverse();
int i=0;
while (numsum.value.compare(numsumreverse.value) !=0)
{
reversenum=num;
reversenum.reverse();
numsum.value=to_string(stoll(num.value,0,10)+stoll(reversenum.value,0,10));
numsumreverse.value=numsum.value;
numsumreverse.reverse();
num.value=numsum.value;
i++;
}
cout << "The number " << n << " becomes palindromic after " << i << " steps : " << num.value << endl;
}
int main()
{
number temp;
int i;
for (i=1; i<1001; i++)
{
temp.value=to_string(i);
palindrome(temp);
}
return 0;
}
It goes on smooth for numbers upto 195. But, in case of 196 I get an error.
It says:
terminate called after throwing an instance of 'std::out_of_range'
what(): stoll
I cannot make out what to do. I tried starting from 196 but the error persisted. Any help will be greatly appreciated. :)
UPDATE: This time I tried to do it using ttmath library. But arghs! It again stops at 195 and doesn't even report an error! I might be doing something foolish. Any comments would be appreciated. Here's the updated code:
#include <iostream>
#include <string>
#include <algorithm>
#include <ttmath/ttmath.h>
/* This program calculates the steps needed
to make a certain number palindromic.
It is designed to output the values for
numbers 1 to 1000
*/
using namespace std;
class number
{
public:
string value;
void reverse();
};
void number::reverse()
{
std::reverse(value.begin(),value.end());
}
template <typename NumTy>
string String(const NumTy& Num)
{
stringstream StrStream;
StrStream << Num;
return (StrStream.str());
}
void palindrome(number num)
{
string n=num.value;
number reversenum, numsum, numsumreverse;
reversenum=num;
reversenum.reverse();
numsum.value=num.value;
numsumreverse.value=numsum.value;
numsumreverse.reverse();
ttmath::UInt<100> tempsum, numint, reversenumint;
int i=0;
while (numsum.value.compare(numsumreverse.value) !=0)
{
reversenum=num;
reversenum.reverse();
numint=num.value;
reversenumint=reversenum.value;
tempsum=numint+reversenumint;
numsum.value=String<ttmath::UInt<100> >(tempsum);
numsumreverse.value=numsum.value;
numsumreverse.reverse();
num.value=numsum.value;
i++;
}
cout << "The number " << n << " becomes palindromic after " << i << " steps : " << num.value << endl;
}
int main()
{
number temp;
int i;
for (i=196; i<1001; i++)
{
temp.value=to_string(i);
palindrome(temp);
}
return 0;
}
UPDATE: It's solved. Some research suggested that 196 might be a Lychrel Number. And the result I was getting after implying the ttmath library is just reassuring that my algorithm works. I have tried it out for all the numbers upto 10000 and it gave out the perfect results. Here is the final code:
#include <iostream>
#include <string>
#include <algorithm>
#include <ttmath/ttmath.h>
#include <limits>
/* This program calculates the steps needed
to make a certain number palindromic.
It is designed to output the values for
numbers inside a desired range
*/
using namespace std;
string LychrelList;
int LychrelCount=0;
class number
{
public:
string value;
void reverse();
};
void number::reverse()
{
std::reverse(value.begin(),value.end());
}
template <typename NumTy>
string String(const NumTy& Num)
{
stringstream StrStream;
StrStream << Num;
return (StrStream.str());
}
void palindrome(number num)
{
string n=num.value;
number reversenum, numsum, numsumreverse;
reversenum=num;
reversenum.reverse();
numsum.value=num.value;
numsumreverse.value=numsum.value;
numsumreverse.reverse();
ttmath::UInt<100> tempsum, numint, reversenumint;
int i=0;
while ((numsum.value.compare(numsumreverse.value) !=0) && i<200)
{
reversenum=num;
reversenum.reverse();
numint=num.value;
reversenumint=reversenum.value;
tempsum=numint+reversenumint;
numsum.value=String<ttmath::UInt<100> >(tempsum);
numsumreverse.value=numsum.value;
numsumreverse.reverse();
num.value=numsum.value;
i++;
}
if (i<200) cout << "The number " << n << " becomes palindromic after " << i << " steps : " << num.value << endl;
else
{
cout << "A solution for " << n << " could not be found!!!" << endl;
LychrelList=LychrelList+n+" ";
LychrelCount++;
}
}
int main()
{
cout << "From where to start?" << endl << ">";
int lbd,ubd;
cin >> lbd;
cout << endl << "And where to stop?" << endl <<">";
cin >> ubd;
cout << endl;
number temp;
int i;
for (i=lbd; i<=ubd; i++)
{
temp.value=to_string(i);
palindrome(temp);
}
if (LychrelList.compare("") !=0) cout << "The possible Lychrel numbers found in the range are:" << endl << LychrelList << endl << "Total - " << LychrelCount;
cout << endl << endl << "Press ENTER to end the program...";
cin.ignore(numeric_limits<streamsize>::max(), '\n');
string s;
getline(cin,s);
cout << "Thanks for using!";
return 0;
}
It's a really awesome community. Special thanks to Marco A. :)
UPDATE AGAIN: I've devised my own add() function that cuts the program's dependency on external libraries. It resulted in a smaller executable and faster performance too. Here is the code:
#include <iostream>
#include <string>
#include <algorithm>
#include <limits>
/* This program calculates the steps needed
to make a certain number palindromic.
It is designed to output the values for
numbers inside a desired range
*/
using namespace std;
string LychrelList;
int LychrelCount=0;
string add(string sA, string sB)
{
int iTemp=0;
string sAns;
int k=sA.length()-sB.length();
int i;
if (k>0){for (i=0;i<k;i++) {sB="0"+sB;}}
if (k<0) {for (i=0;i<-k;i++) {sA="0"+sA;}}
for (i=sA.length()-1;i>=0;i--)
{
iTemp+=sA[i]+sB[i]-96;
if (iTemp>9)
{
sAns=to_string(iTemp%10)+sAns;
iTemp/=10;
}
else
{
sAns=to_string(iTemp)+sAns;
iTemp=0;
}
}
if (iTemp>0) {sAns=to_string(iTemp)+sAns;}
return sAns;
}
void palindrome(string num)
{
string n=num;
string reversenum, numsum, numsumreverse;
numsum=num;
numsumreverse=numsum;
reverse(numsumreverse.begin(),numsumreverse.end());
int i=0;
while ((numsum.compare(numsumreverse) !=0) && i<200)
{
reversenum=num;
reverse(reversenum.begin(),reversenum.end());
numsum=add(num,reversenum);
numsumreverse=numsum;
reverse(numsumreverse.begin(),numsumreverse.end());
num=numsum;
i++;
}
if (i<200) cout << "The number " << n << " becomes palindromic after " << i << " steps : " << num << endl;
else
{
cout << "A solution for " << n << " could not be found!!!" << endl;
LychrelList=LychrelList+n+" ";
LychrelCount++;
}
}
int main()
{
cout << "From where to start?" << endl << ">";
int lbd,ubd;
cin >> lbd;
cout << endl << "And where to stop?" << endl <<">";
cin >> ubd;
cout << endl;
string temp;
int i;
for (i=lbd; i<=ubd; i++)
{
temp=to_string(i);
palindrome(temp);
}
if (LychrelList.compare("") !=0) cout << "The possible Lychrel numbers found in the range are:" << endl << LychrelList << endl << "Total - " << LychrelCount;
cout << endl << endl << "Press ENTER to end the program...";
cin.ignore(numeric_limits<streamsize>::max(), '\n');
string s;
getline(cin,s);
cout <<endl << "Thanks for using!";
return 0;
}
You guys here have helped me a lot to find my own way. Thanks everyone. :)
You're overflowing long long since the last two valid values of num.value and reversenum.value are 7197630720180367016 and 6107630810270367917 which, added together, are way above the maximum size of a long long (9223372036854775807 on my machine). That will yield a negative value and spoil your next call to stoll
std::out_of_range is thrown if the converted value would fall out of the range of the result type or if the underlying function (std::strtol or std::strtoll) sets errno to ERANGE.
(reference)
If you're trying to get the next smallest palindrome, you should use another approach like the one I explained here.
You can find a Live Example here
If you prefer to/must continue with your approach you should either do the addition manually on the strings or use a bigint library (again take a look at here and modify the plusOne() function to your liking)
From http://www.cplusplus.com/reference/string/stoll/
If the value read is out of the range of representable values by a long long, an out_of_range exception is thrown.
The ll data type cant handle the string length. My debugger tells me 196 breaks on the value
std::stoll (__str=\"9605805010994805921-\", __idx=0x0, __base=10)
The long long is too small.
You might want to do the addition on the strings themselves, without resorting to a numeric type.
Related
I'm trying to make a program that prints all the numbers from 100-999. After that you get to choose how many numbers you want to find. Then you type the number's position and it will be outputed.
There is one problem. The string, named str, stops storing at the number 954.
Here's the code:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
//Prints to myFile the numbers from 100 to 999 without a space in between. Like this: 100101102...999
ofstream myFile("numere.txt");
for(int i = 100; i <= 999; i++)
myFile << i;
//Makes the string str to store the line: 100101102103...999. But only stores until 954 (100101102..954)
ifstream myFileRead("numere.txt");
string str;
while(getline(myFileRead, str))
cout << str << endl;
//Ouputs the lenght that should be 2700 but is instead 2565
cout << endl;
cout << "String legth: " << str.size() << endl;
cout << endl;
int n, k;
cout << "Enter how many numbers do you want to find: ";
cin >> n;
for(int i = 1; i <= n; i++){
cout << "Enter number position(it starts from 0) : ";
cin >> k;
cout << "Here's the number on position " << k << ": " << str.at(k);
cout << endl;
}
system("pause>0");
}
Thanks for your attention. I’m looking forward to your reply.
C++ streams are buffered. When you use << to write to a file it is not immediately written to the file.
Try to close or flush the ofstream before you read from it:
myFile.close(); // or...
myFile.flush();
For more details I refer you to flush() and close().
PS: Actually it is rather rare that you need to close a fstream explicitly. You wouldn't need to do it when you used seperate functions for writing and reading:
void write_to_file() {
std::ofstream myFile("numere.txt");
//...
}
void read_from_file() {
std::istream myFile("numere.txt");
//...
}
Because the destructor of ofstream already closes the file.
The function is called as: Perm( "xyz", "abc" ); then it would print:
xyzabc xyzacb xyzbac xyzbca xyzcab xyzcba
The xyz is fixed and has all permutations of abc concatenated to it.
I started a for Loop to deal with the general case, and part of the base case but I am having a hard time figuring out where I am going wrong.
#include <string>
#include <iostream>
using namespace std;
void Perm(string fixedPart, string permPart)
{
if (permPart.length() == 1) {
cout << fixedPart << permPart << endl;
}
else {
for (int i = 0; i < permPart.length() - 1; i++) {
Perm(fixedPart + permPart[i] ,
permPart.substr(0, i) + permPart.substr(i + 1,permPart.length()-1));
}
}
}
int main(){
// Don't touch main!!!
string s;
cout << "Enter a String: ";
cin >> s;
cout << s << endl;
cout << "Perms are: " << endl;
Perm("xyz", s);
}
Problem is not with base case, Just change the for loop condition to
i < permPart.length()
last character also should be swapped with other characters in the permutation
So I've been working on a little program that asks the user for the name/hours studying for a given topic, then does some calculations and displays the results back. Right now, to get the input for, say, 4 topics, I'm doing it this way:
#include <iostream>
using namespace std;
int main()
{
string topic1 = "";
string topic2 = "";
string topic3 = "";
string topic4 = "";
/* could have more topics here */
double hoursStudying1 = 0;
double hoursStudying2 = 0;
double hoursStudying3 = 0;
double hoursStudying4 = 0;
cout << "Topic name: ";
getline(cin, topic1);
cout << "Time studying for " << topic1 << ": ";
cin >> hoursStudying1;
cin.ignore();
cout << "Topic name: ";
getline(cin, topic2);
cout << "Time studying for " << topic2 << ": ";
cin >> hoursStudying2;
cin.ignore();
cout << "Topic name: ";
getline(cin, topic3);
cout << "Time studying for " << topic3 << ": ";
cin >> hoursStudying3;
cin.ignore();
/* calculate stuff here */
/* display the results */
cout << "For " << topic1 << " you spent " << hoursStudying1 << " hours studying" << endl;
/* etc */
return 0;
}
I'm a beginner, but I know there has to be a more efficient way to do this :(. How could I use, for example, a do...while loop or even a for loop to display a set number of prompts for each topic/hours studied (in order) as I'm doing now? I'm not looking for anyone to rewrite my program or anything like that, but rather give me some pointers with their code. Thanks a lot guys!
Edit: thank you so much for all the examples and pointers you've given me. I will play around with them and post some code of my own to let you know how it's working.
You will need to use an array or list, then loop through them. You can have two separate arrays, one to hold the topic names, and the other to hold the hours studies, or you can define a class that includes a topic name and hours studied and then have an array of elements of that class.
Bottom line, you need to learn how to use arrays or collections.
You can use a struct
typedef struct _element {
string topic;
double hoursStudying;
} element;
Then you can define an array of elements like this
element journal[ 4 ];
Now you can think of using loops to handle the array journal.
Try it yourself: write a complete program out of the above hints and let us know...
After doing that, try to transform the struct into a class figuring out what member functions are needed and then implementing them. Again, let us know...
I'd do something like:
cout << "Enter topic name or 'quit'";
while(true)
{
cin<< foo;
if(foo == 'quit')
break;
else
{
//Do stuff with foo
}
}
Obviously you'll want to handle weird input ("qUiT"), but that's the loop structure.
How could I use, for example, a do...while loop or even a for loop to display a set number of prompts for each topic/hours studied (in order) as I'm doing now?
Instead of creating a separate variable for, you should create an array to store your data. After that, use a loop to prompt and receive input. It can be a while-loop or a for-loop. (Generally, use a for-loop when you are certain how many times you want it to iterate. Use a while-loop when the number of times to iterate cannot be determined)
Example:
double hoursStudying[5] = {0};
for(int x=0; x<5; x++){ //5 can be replaced with a variable indicating array size
cout << "Time studying for " << topic << " " << x << ": ";
cin >> hoursStudying[x];
cin.ignore();
}
For displaying output, it will be the same. Just use a loop to iterate through the array values.
Example:
for(int x=0; x<5; x++){
cout << "For " << topic << " " << (x+1) << " you spent "
<< hoursStudying[x]<< " hours studying" << endl;
}
This is proper way to write programs in C++:
File Topic.h:
#pragma once
#include <sstream>
#include <string>
using namespace std;
class Topic {
string name;
double hours;
public:
Topic(string name, double hour);
~Topic();
void setName(const string & _name) {
name = _name;
}
void setHours(double & _hours) {
hours = _hours;
}
void addHours(double & _hours) {
hours += _hours;
}
string getName() const {
return name;
}
double getHours() const {
return hours;
}
string print() const;
};
File Topic.cpp
#include "Topic.h"
Topic::Topic(string name = "", double hour = 0.0) :
name(name), hours(hour) {
}
Topic::~Topic() {
}
string Topic::print() const {
ostringstream output;
output << "For " << name << " you spent " << hours << " hours studying.";
return output.str();
}
File Topics.h:
#pragma once
#include <vector>
#include <sstream>
#include <string>
#include "Topic.h"
using namespace std;
class Topics {
vector<Topic> topics;
public:
Topics();
~Topics();
void add(const Topic & topic) {
topics.push_back(topic);
}
Topic get(const unsigned int & index) const {
return topics[index];
}
string printAll() const;
};
File Topics.cpp:
#include "Topics.h"
Topics::Topics()
{
}
Topics::~Topics()
{
}
string Topics::printAll() const {
ostringstream output;
for (Topic topic : topics) {
output << topic.print() << endl;
}
return output.str();
}
File Source.cpp
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
#include "Topic.h"
#include "Topics.h"
using namespace std;
Topic input() {
string name;
double hours;
cout << "Topic name: ";
cin >> name;
cout << "Time studying for " << name << ": ";
cin >> hours;
cout << endl;
return Topic(name, hours);
}
Topics inputCycle()
{
Topics topics;
int n;
cout << "How many topics you have ?" << endl;
cin >> n;
for (int i = 0; i < n; i++)
topics.add(input());
return topics;
}
void printAll(const Topics & topics) {
cout << topics.printAll() << endl;
}
int main()
{
printAll(inputCycle());
system("PAUSE");
return false;
}
I have a question that might be very simple to many of you however, I have not found an answer to my question.
I have the program below that is working properly. This code turns a number into a floating number and integer.
Let's say you entered 5.4, the program will give you 5.4 for double and 5 for integer.
Now I need to add a throw catch statement to my program in case the user enters a text instead of a number ("If the conversion fails, throw an exception and allow the user to re-enter the value.").
This is the pseudocode of what I need to do.
try {
if(num ==character)
throw;
cout << "\n The number entered " << num << "invalid, please enter again";
}
catch
{
}
and I implemented something like this, however it did not work. I set the 'a' variable character thinking the user has to enter a text in order to get that message. However it did not work and gave some errors.
try
{
char a;
if (num == a)
throw num;
}
catch(int e)
{
cout << "A number of " << a << " is invalid." << endl;
cout << "Please re-enter a number: ";
cin << num
}
I am very new with this "try,throw,catch" terms. I would be happy if you help me through this, thanks.
#include <C:\\CSIS1600\MyCppUtils.cpp>
#include <iostream>
#include <string>
using namespace myNameSpace;
int main()
{
runner("is running");
cout << "Enter a number : ";
string num;
getline(cin, num);
cout<< "double " << getValidDouble(num) << endl;
cout<< "integer " << getValidInt(num) << endl;
system("pause");
return 0;
}
#include<iostream>
#include<string>
using namespace std;
namespace myNameSpace
{
string num;
void runner(string str)
{
cout <<"runner-3() is running.."<<endl;
}
int getValidInt(string n)
{
int valueint;
valueint=atoi(n.c_str());
return valueint;
}
double getValidDouble(string n )
{
double valuedouble;
valuedouble = atof(n.c_str());
return valuedouble;
}
}
You can use Boost to do a lexical cast. If you have valid input (e.g. 2.54), no exception will be thrown, but with invalid input (e.g. 2???54) the bad_lexical cast is thrown:
#include <boost/lexical_cast.hpp>
try
{
double x1 = boost::lexical_cast<double> ("2.54");
double x2 = boost::lexical_cast<double> ("2???54");
cout << x1 << x2 << endl;
}
catch(boost::bad_lexical_cast& e)
{
cout << "Exception caught - " << e.what() << endl;
}
i am in a basic programming class and know practically nothing about programming, we are using c++ and my current project is to pull up the console and do the following
input a letter and output its ascii decimal equivalent
input a number between 33 and 254 and output its letter equivalent
input a lower case letter and output itscapital
input a number of hours and output the number of minutes
input a number greater than 60 and output the number of hours and minutes
this is the work i have so far
#include <iostream>
using namespace std;
void main ()
{
cout<<"Assignment 2"<<endl;
char somechar;
int charval;
int input_number;
char output_letter2;
char input_lower_letter;
char output_upper_letter;
int input_hours;
int output_minutes;
int input_minutes2;
int output_hours2;
int output_remainder_minutes;
cout<<"Enter a letter"<<endl;
cin>>somechar>>endl;
cout<< somechar='a';
int charval = somechar;
printf("%c = %d\n",somechar,charval);
system("pause");
}
any tips and help are deeply appreciated
One crucial lesson (which they never seem to teach in school) is to start with a very simple program, get it working perfectly, then build up, testing at every step.
Your code doesn't compile. Let's strip your code down and start from scratch:
void main()
{
}
This doesn't compile. Fix it:
int main()
{
return(0);
}
Now add some output:
#include <iostream>
using namespace std;
int main()
{
cout << "Assignment 2" << endl;
return(0);
}
So far, so good. Now input:
#include <iostream>
using namespace std;
int main()
{
cout << "Assignment 2" << endl;
char somechar;
cout << "Enter a letter" << endl;
cin >> somechar >> endl;
return(0);
}
This doesn't compile. Fix it.
And so on. See how it works?
#include <iostream>
using namespace std;
int main() {
char a ='a';
cout << a << " => integer: " << (int)(a) << endl;
int i = 98;
cout << i << " => character: " << (char)(i) << endl;
char b='b';
cout << b <<" => lower: " << (char)(b+('a'-'A')) << endl;
char c='c';
cout << c << " => upper: " << (char)(c-('a'-'A')) << endl;
int hours = 15;
cout << hours << " hours => minutes: " << hours * 60 << endl;
int minutes = 75;
cout << minutes << " minutes => hours:minutes: " << minutes/60 << ":" << minutes % 60 << endl;
system("PAUSE");
return 0;
}
For this you can take a look at casting. To cast a character (char) to an integer ASCII value, you have to cast an int on that char value. For example:
#include <iostream>
using namespace std;
int main() {
char myvalue;
cout<<"Enter a character: ";
cin>>myvalue;
cout<<endl<<"The ASCII value is: "<<(int)myvalue<<endl;
return 0;
}
Now because this is homework, I wont finish the steps for you, but it should be pretty straight forward from here.
For more information about casting, I highly suggest: http://www.cplusplus.com/doc/tutorial/typecasting/