Let me introduce how I got this problem... Well, I know a little bit of FORTRAN, and now I'm learning C++.
While I read the beginnings, I'm (re)creating an old program that I have written in FORTRAN.
It do the calculation part of the topography surveying of a closed polygonal.
Well, I'm reading the book "Programming: Principles and Practice Using C++", and it says that in C++, we'd prefer to let each functions do the minimum number of things. For now, I have something like this (I ignored all the other functions):
int main(){
//Starting the program and reading all variables
try
{
//Program beginning
cout << "Hello. Welcome to the 'Topography Program'\n\n\n";
//Reading all the information needed
reading_is_fundamental();
//Testing the angular tolerance
ang_tolerance_test (number_of_points); } ...there's more subroutines' calls
catch (runtime_error& e)
{
cerr << "error:" << e.what()<<'\n';
return 1;
}
return 0;}
The "reading_is_fundamental()" is the call of a subroutine. There, I read all the information needed. My problem is lying on the second subroutine, "ang_tolerance_test (number_of_points)".
In FORTRAN, I abused too much of global variables, and now, in this book, says that we must avoid global variables.
End of story, I have two questions:
1 - This logic is correct or I misunderstood the book? Should I put some calculations (or at least the reading of the input variable, as they will appear in all the subroutine) in the main function or should I use it only to call my subroutines?
2 - If this is really the way that we should do in C++ (separate each action in one function), can somebody explain me how to grab variables that was written in the first subroutine and send to the others, like the "ang_tolerance_test" one?
Many thanks in advance!
EDIT
The function "reading_is_fundamental()" is where I read all the values by keyboard. I know how to read the values by a text file in FORTRAN and, in this case, it is a great advantage, as there are so many numbers to be read. But, I don't know yet how to do this in C++, so, please, ignore that I'm reading a lot of variables by keyboard, I'm studying it yet! Actually, doesn't really matter the way that I'm reading the variables, the point is that I want those doubles, int and vectors in the others soubroutines...
Well, this is "reading_is_fundamental:
//This subroutine reads all the variables
void reading_is_fundamental (){
cout << "What is the linear tolerance?\n";
double lin_tolerance;
cin >> lin_tolerance;
cout << "\nHow many points did you study?\n";
int number_of_points;
cin >> number_of_points;
cout << "\nWhat's the distance between each point?\n";
vector <double> distances;
for (double dist; cin >> dist;)
distances.push_back(dist);
if (distances.size() != number_of_points) error ("The number of distances must be equal to the number of points");
cout << "\nWhat's each horizontal degree angle?\n";
vector <double> horizontal_degrees;
for (double horizontal_degree; cin >> horizontal_degree;)
horizontal_degrees.push_back(horizontal_degree);
if (horizontal_degrees.size() != number_of_points) error ("The number of angles must be equal to the number of points");
cout << "\nWhat's each horizontal minute angle?\n";
vector <double> horizontal_minutes;
for (double horizontal_minute; cin >> horizontal_minute;)
horizontal_minutes.push_back(horizontal_minute);
if (horizontal_minutes.size() != number_of_pointsint) ("The number of angles must be equal to the number of points");
cout << "\nWhat's each horizontal second angle?\n";
vector <double> horizontal_seconds;
for (double horizontal_second; cin >> horizontal_second;)
horizontal_seconds.push_back(horizontal_second);
if (horizontal_seconds.size() != number_of_points) error ("The number of angles must be equal to the number of points");
cout << "\nWhat's the first azimuth degree?\n";
double first_az_degree;
cin >> first_az_degree;
cout << "\nWhat's the first azimuth minute?\n";
double first_az_minute;
cin >> first_az_minute;
cout << "\nWhat's the first azimuth second?\n";
double first_az_second;
cin >> first_az_second;
cin >> number_of_points;}
One thing that I din't know when I was writting this is if it's correct to put void in this function. My way of thinking is taht I don't want one return, but some variables filed.
The second function is the "ang_tolerance_test()". It is not ready yet, so, I will not copy here. The thing is that when I call this function in main(), I want to put the argument of it one value sent from "reading_is_fundamental()" (that is "number_of_points).
I hope this made my questions more clearly.
Try returning value from reading_is_fundamental function, which you could pass it to other function like:
int number_of_points = reading_is_fundamental();
//Testing the angular tolerance
ang_tolerance_test (number_of_points);
And define function like:
int reading_is_fundamental() {
....
return number;
}
Define a class like:
class Record
{
private:
double lin_tolerance;
int number_of_points;
public:
int getNumberOfPoints() { return number_of_points; }
void setNumberOfPoints(int v) { number_of_points = v; }
double getLinTolerance() { return lin_tolerance; }
void setLinTolerancedouble v) { lin_tolerance = v; }
};
And when you read the values, create an instance of Record, keep populating the values within record and at the end return that value so that you could pass it to ang_tolerance_test. Just similar to int above instead now you will get Record object from the function.
Related
i am trying to make a program to check and list the genders of a number of student, m being fem and l being male.
I'm not sure what's wrong with my code but when i print out the m and l variable they have either really huge.
Have been trying to solve this for hours, your help is greatly appreciated, cheers.
P.S sorry for my bad english.
#include<iostream>
#include<string>
using namespace std;
main()
{
char gender[20];
int jlh,i,j,m,l;
cin>>jlh;
system("cls");
for(i=0;i<jlh;i++)
{ cout<<"Data "<<i+1<<endl;
cout<<"Enter your gender - "<<endl;
cin>>gender[i];
}
m,l=0;
for(i=0;i<jlh;i++){
if(gender[i]=='p'){
m=m+1;
}
else if(gender[i]=='l'){
l=l+1;
}
}
cout<<endl<<l<<endl;
cout<<m;
}
The line
m,l=0;
does not work as you expect. Look up the comma operator, it evaluates the first operand (just m in this case), discards the result, and evaluates and returns the second operand. So only l is set to zero. I would recommend moving the declaration to this line and initializing the variables in one go, like so
int m=0, l=0;
for (int i=0; i<jlh; i++)
...
I would also move the declaration of variables like i to where they are needed, as shown above; there is no need to put all declaration at the beginning of the function.
Then the output
cout<<endl<<l<<endl;
cout<<m;
places the endl before and after the first variable, but not after the second. You should have an endl after the last line of your output, otherwise your console prompt is right after your value. It would improve readability to have something like this:
std::cout << "Number of females: " << m << std::endl;
std::cout << "Number of males: " << l << std::endl;
You should also make sure that not more than 20 values are entered, as your array has this size. But there is not even a need for this (maybe there is in your real code, but not in the MCVE): You can just increment the variables when reading the input, no need to store it in the array. This gets rid off this arbitrary limit. If you really need the values, you should use a std::vector instead of a fixed size array.
It seems like I always come here to ask silly questions, but here it goes. As of right now I am in my first compsci course and we are learning c++. I've had an extremely basic introduction to c before, so I had thought I'd go above and beyond my current assignment. Now I was doing this just to showboat, I felt like if I didn't practice my previous concepts they would eventually fade. Anyways, on to the problem! I was supposed to write some code that allowed the user to input their initials, and a series of exams. Now this was supposed to accomplish three things: average the exams, print out the entered exams, and print out their initials. Well, what was a simple assignment, got turned into a huge mess by yours truly.
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int main()
{
string uInitials;
float avgExam = 0, tExam = 0;
int aExams[10] = {'0'};
int i, nExam = 0, cExam;
cout << "Enter your three initials!";
cin >> uInitials;
do
{
cout << "Enter your exam(s) to be averaged. Enter 0 when complete!\n";
cin >> cExam;
aExams[nExam] = cExam; //I used this before nExam was incremented, in order to get nExam while it was '0' That way the first exam score would be properly saved in the first space
nExam++;
tExam += cExam; //This is just to add all the exams up to later calculate the average
}
while(cExam != 0);
avgExam = tExam/(nExam - 1); //subtracted '1' from nExams to remove the sentinel value from calculations.
cout << "The average for initials: " << uInitials << " is: " << avgExam << endl;
cout << "This average was obtained using the following scores that were entered: \n";
for(i = 0; i < (nExam+1); i++)
{
cout << aExams[i] << endl; //Used a for loop to prevent redundancy
}
return 0;
}
The previous is my code, and the problem is that I'm getting output errors where it adds two '0's when I print out the list of entered exams. Also I feel like I made the whole do{}while() loop one huge clunky mess, so I'd like to refine that as well. If anyone could assist this poor, ignorant, beginner I would greatly appreciate it. Thank you for your time!
Some advice that i can give is for example in the 5th line there is no need
to put the 0 between ' ' and not even need to use the assign = operator.
You can initialize the array like this:
int aExams[10]{0};
Which will initialize all elements to 0,but can't be used for other value.
For example you won't have all the elements with value 1 if you write
int aExams[10]{1};
If your intention to initialize all elements in an array is with value other than 0 you can use fill_n(); function.
fill_n(aExams, 10, 1);
The first argument is the name of the array, the second is up-to which element you want to be initialized with the third argument, and the third is the value you want all elements to have.
Do not leave uninitialized variables like in line 6 with cExam and i variables. Initialize it like cExam=0; (copy-assign initialization) or cExam(0); (direct initialization). The latter calls the constructor for int built-in type.
A negative i see in your do-while loop is that you do not make sure that the user will enter under 10 exams,bad things will happen if the user tries to input 15 exams in an array that can hold only 10.
Just change the while to something more like this:
while( cExam != 0 && (nExam<10) );
You can also write the first two lines of the do-while loop outside the loop.
It is needed only once to tell the user that to stop the loop he/she needs to enter 0. There is no need to tell them this on every iteration plus that you will have a good performance benefit if you put those two lines outside the loop.
Look here how i would write the code and ask if you have any questions.
http://pastebin.com/3BFzrk5C
The problem where it prints out two 0's at the end of your code is a result of the way you wrote your for loop.
Instead of:
for(i = 0; i < (nExam+1); i++)
{
cout << aExams[i] << endl; //Used a for loop to prevent redundancy
}
Use:
for (i = 1; i < (nExam); i++)
{
cout << aExams[i - 1] << endl; //Used a for loop to prevent redundancy
}
I am trying to take a complex number input from the user in a form of a char or string like:
88.90-55.16i or -3.67+5i
and then convert it to float keeping the same format as above. Not (x,y).
char user[100];
vector < float > V;
for (int y = 0; y < 5; y++)
{
cout << "Enter a complex number:" << endl;
cin >> user;
float newfloat = atof(user);
cout << newfloat << endl;
}
Currently its not converting the whole number. Just 88 or -3 from above input examples.
You would need to store the real and imaginary components of the complex number in separate float variables, which may or may not be grouped using a struct/class or std::pair<>. Input should be something like this:
std::cout << "Enter a complex number:\n";
float real, imaginary;
char i;
if (std::cin >> real >> imaginary >> i && i == 'i')
{
...do something with real & imaginary...
}
else
{
std::cerr << "unable to parse input as a complex number\n";
exit(1);
}
(FWIW, this is very obviously related to this earlier question - either the same person using a new username, or someone doing the same assignment. I provide an example program using std::complex<> in my answer there.)
Float is not capable of storing that type of number. A float is designed to hold a single floating point number, i.e. 10.3 or 5.2. Not 1+2i. That is a two-dimensional quantity.
I would recommend you use the complex<float> template for your data type or create your own class. Look here for more: https://msdn.microsoft.com/en-us/library/5de6f0bw.aspx about the complex<float> It comes with built in tools to convert strings to complex types.
I have never used C++ before but I am sure float does not fit your expectations. Imaginary number is not a subset of float so you can't do that.
I guess one possible solution is to write your own imaginary class, or use a build-in one if there is one.
Also write a fromString()/toString() in your custom imaginary class.
This is what I have to do:
A teacher has asked all her students to line up single file according to their first name. For example, in one class Amy will be at the front of the line and Yolanda will be at the end. Write a program that prompts the user to enter the number of students in the class, then loops to read in that many names. Once all the names have been read in it reports which student wourld be at the front of the line and which one would be at the end of the line. You may assume that no two students have the same name. Input Validation: Do not accept a number less than 1 or greater than 25 for the number of students.
This is what I have so far:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
int StudentNum;
cout << "How many student are in the class?\n";
cin >> StudentNum;
char sname[StudentNum + 1][25];
if (StudentNum < 1 || StudentNum > 25)
{
cout << "Please enter a number between 1-25 and try again\n";
return 0;
}
for (int i = 1; i <= StudentNum; i++);
{
cout << "Please enter the name of student #" << i << endl;
cin >> sname[i];
}
for (int output = 0; output <=StudentNum; output++);
{
cout << endl << sname[output] << endl;
}
system ("pause");
return 0;
}
Am I missing something about arrays??
You cannot create such an array because its length has to be known at compile time (i.e., it cannot be the result of an expression such as StudentNum + 1).
You can solve this issue because by the problem definition you know an upper bound for the array size, so you can use that as a compile time constant.
However, this problem can be solved without using an array at all. Read the wording carefully.
Hint for the solution without arrays: Think of the array as a single piece of paper (variable) with all the names written one after another. Not using an array then means that you have to be able to solve the problem without looking at all the names at once. How would you come to the answer if I only allowed you to see the names one by one?
Another hint: The problem is still solvable if there were several trillion students in the class (with unique names no less), i.e. more than could possibly fit in the computer's memory at any one time.
C++ array dimensions must be known at compile time (ie not dependent on user-entered variables at run-time). Use strings instead:
string sname[25];
If you were using something besides char arrays, you could also use a vector.
Think about what the problem statement is actually asking for. Your program only needs to output the first and last names alphabetically. Do you actually need to store all the names to do that?
Just for fun, here's how I would do it. Don't turn this in unless are ready to explain to your teacher how it works.
struct MinMax {
std::string min;
std::string max;
MinMax& operator+(const std::string& kid) {
if( min.empty() || kid < min) min = kid;
if( max.empty() || kid > max) max = kid;
return *this;
}
};
int main() {
int nKids;
std::cout << "How many students? " << std::flush;
std::cin >> nKids;
std::cout << "Enter students' names, followed by EOF\n";
MinMax mm(std::accumulate(
std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string>(),
MinMax()));
std::cout << mm.min << ", " << mm.max << "\n";
}
So I am currently learning C++ and decided to make a program that tests my skills I have learned so far. Now in my code I want to check if the value that the user enters is a double, if it is not a double I will put a if loop and ask them to reenter it. The problem I have is how do I go about checking what type of variable the user enters, ex- if a user enters a char or string, I can output an error message. Here is my code:
//cubes a user entered number
#include <iostream>
using namespace std;
double cube(double n); //function prototype
int main()
{
cout << "Enter the number you want to cube: "; //ask user to input number
double user;
cin >> user; //user entering the number
cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number
return 0;
}
double cube (double n) //function that cubes the number
{
return n*n*n; // cubing the number and returning it
}
Edit: I would have to say I just started and don't have the slightest of clue about your code, but I will check out your link. By the way, I haven't learned how to work with templates yet,I am learning about dealing with data, only Chapter 3 in my C++ Primer Plus 5th edition.
Safe C++ Way
You can define a function for this using std::istringstream:
#include <sstream>
bool is_double(std::string const& str) {
std::istringstream ss(str);
// always keep the scope of variables as close as possible. we see
// 'd' only within the following block.
{
double d;
ss >> d;
}
/* eat up trailing whitespace if there was a double read, and ensure
* there is no character left. the eof bit is set in the case that
* `std::ws` tried to read beyond the stream. */
return (ss && (ss >> std::ws).eof());
}
To assist you in figuring out what it does (some points are simplified):
Creation of a input-stringstream initialized with the string given
Reading a double value out of it using operator>>. This means skipping whitespace and trying to read a double.
If no double could be read, as in abc the stream sets the fail-bit. Note that cases like 3abc will succeed and will not set the fail-bit.
If the fail-bit is set, ss evaluates to a zero value, which means false.
If an double was read, we skip trailing whitespace. If we then are at the end of the stream (note that eof() will return true if we tried to read past the end. std::ws does exactly that), eof will return true. Note this check makes sure that 3abc will not pass our check.
If both cases, right and left of the && evaluate to true, we return true to the caller, signaling the given string is a double.
Similar, you check for int and other types. If you know how to work with templates, you know how to generalize this for other types as well. Incidentally, this is exactly what boost::lexical_cast provides to you. Check it out: http://www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm.
C Way One
This way has advantages (being fast) but also major disadvantages (can't generalized using a template, need to work with raw pointers):
#include <cstdlib>
#include <cctype>
bool is_double(std::string const& s) {
char * endptr;
std::strtod(s.c_str(), &endptr);
if(endptr != s.c_str()) // skip trailing whitespace
while(std::isspace(*endptr)) endptr++;
return (endptr != s.c_str() && *endptr == '\0');
}
strtod will set endptr to the last character processed. Which is in our case the terminating null character. If no conversion was performed, endptr is set to the value of the string given to strtod.
C Way Two
One might thing that std::sscanf does the trick. But it's easy to oversee something. Here is the correct way to do it:
#include <cstdio>
bool is_double(std::string const& s) {
int n;
double d;
return (std::sscanf(s.c_str(), "%lf %n", &d, &n) >= 1 &&
n == static_cast<int>(s.size()));
}
std::sscanf will return the items converted. Although the Standard specifies that %n is not included in that count, several sources contradict each other. It's the best to compare >= to get it right (see the manpage of sscanf). n will be set to the amount of the processed characters. It is compared to the size of the string. The space between the two format specifiers accounts for optional trailing whitespace.
Conclusion
If you are a beginner, read into std::stringstream and do it the C++ way. Best not mess with pointers until you feel good with the general concept of C++.
There is no suitable way to check if a string really contains a double within the standard library. You probably want to use Boost. The following solution is inspired by recipe 3.3 in C++ Cookbook:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
double cube(double n);
int main()
{
while(true)
{
cout << "Enter the number you want to cube: ";
string user;
cin >> user;
try
{
// The following instruction tries to parse a double from the 'user' string.
// If the parsing fails, it raises an exception of type bad_lexical_cast.
// If an exception is raised within a try{ } block, the execution proceeds
// with one of the following catch() blocks
double d = lexical_cast <double> (user);
cout << "The cube of " << d << " is " << cube(d) << "." << endl;
break;
}
catch(bad_lexical_cast &e)
{
// This code is executed if the lexical_cast raised an exception; We
// put an error message and continue with the loop
cout << "The inserted string was not a valid double!" << endl;
}
}
return 0;
}
double cube (double n)
{
return n*n*n;
}
sscanf can do what you want; it returns the number of arguments properly processed. This should get you started:
//cubes a user entered number
#include <iostream>
#include <cstdio>
using namespace std;
double cube(double n); //function prototype
int main()
{
cout << "Enter the number you want to cube: "; //ask user to input number
string user;
cin >> user; //user entering the number
// Convert the number to a double.
double value;
if(sscanf(user.c_str(), "%lf", &value) != 1)
{
cout << "Bad! " << user << " isn't a number!" << endl;
return 1;
}
cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number
return 0;
}
double cube (double n) //function that cubes the number
{
return n*n*n; // cubing the number and returning it
}
Other methods posted in other answers have their advantages and disadvantages. This one has issues with trailing characters and isn't "C++"-y.
I would have to say I just started and don't have the slightest of clue about your code, but I will check out your link. By the way, I haven't learned how to work with templates yet,I am learning about dealing with data, only Chapter 3 in my C++ Primer Plus 5th edition.
You can fall back on C and use strtod
You program reads in a string and then passes it to a function that attempts to convert the string into double.
bool is_double(const char* strIn, double& dblOut) {
char* lastConvert = NULL;
double d = strtod(strIn, &lastConvert);
if(lastConvert == strIn){
return false;
} else {
dblOut = d;
return true;
}
}