CSCI-15 Assignment #1 — Functions and files review (40 points), due September 9, 2013.

Write a program to read the coefficients of a series of quadratic equations from a text file and print the associated roots, or appropriate errors if there are no real roots, to another text file. The coefficients of a quadratic are the a, b and c of an expression of the form ax2 + bx + c, and the roots are the values of x that make the value of the expression 0.

If a == 0, the formula describes a line, and you may ignore any roots (just say it isn’t a quadratic and has no solutions), and if (b2-4ac) < 0 it has only complex roots.

Write a function to read one set of values from the file, using reference parameters to get the values out of the function and the function’s return value to indicate whether or not the function was able to correctly read three values. The data error you must deal with here is too few values on the line, e.g., the line has an a value only and no b or c. You may assume that the last line in the file is the only one with an error (if any error exists), and your function should return an error code to make the program stop processing after this error. This restriction allows you to use stream extraction to read the file, rather than reading lines and parsing them yourself. If you want to try doing this, that’s O.K., but get it working the easy way first.

Write a second function to calculate the roots, taking the coefficients through value parameters and giving back the roots (if they exist) via reference parameters. Use the return value to indicate success at calculating roots (0), no solution (-1) or complex roots (-2). Do not call this function if you have a data error on input.

Write a third function to print a reasonably formatted table (one row per call from the main loop) of the coefficients, and either the roots or (different) messages indicating the various error conditions. It must print appropriate error messages in the cases of a data error on input and either no solution or complex roots from the calculation function. Your table must have a reasonable title line (or lines) with legends describing what things are below it in the columns, and this table's title line must be printed inside the print function. The function must know if it is being called for the first time (or not) to print the title line. You may not pass this information into the print function from main(). The print function MUST do this itself. Always print the coefficients unless you have a read error. You must align the values in the columns in a reasonable way (if you can't align the decimal points in the columns, that's OK). Don't worry about page breaks and new title lines if the output runs beyond one page.

Your main() function will prompt for the file names (hold the names in C-strings), open the input and output files, check for file open errors appropriately, loop over the input file reading coefficients, calculating roots, and printing results to the output file until either end-of-file or error on input, and then close all the files and exit. You may make no assumptions about how many coefficients are in the input file (e.g., you may not hold the values in arrays and process them after reading them all).
You may not use any global variables in this program. Your variables must be declared appropriately within the functions where needed; and passed to other functions as either reference or value parameters as appropriate. Your functions will indicate any problem they encounter by returning a value to main(), where the error must be handled appropriately. Your functions outside main() may do only the task assigned to them, and must do that entire task. For example, you may not check for a == 0 within main and only call the calculation function if a is not zero. Think carefully about what data you need inside each function, and what must be passed around between functions.

Each correct input line will comprise three real values of the form
[optional sign][digits][decimal point][digits], or
[optional sign][digits] if integer.
The last input line might have fewer values. For example, your data file might look like this:

1 1 1
1.2 -2.3 0.4
-2 -3 -4
+0 -2 8.85
2.345           (error — only one data point)

These data are available as in the file quadratic1.txt.

Here is my solution:

#include<iostream>
#include<string>
#include<fstream>
#include<cmath>
using namespace std;

// Read each set of values from the input file.
int quadValues(double &x, double &y, double &z)
{
    ifstream inputFile;
    int value;

    // Indicate whether function read three values.
    while(inputFile >> x >> y >> z)
    {
        cout << x << y << z << endl;
        // Otherwise, print error message.
        if(value < 3)
        {
            return 0;
        }
    }
    return 0;
}

// Calculate the roots
int calcRoots(double a, double b, double c, double &root1, double &root2)
{
    // If a is 0, there is no solution.
    if(a == 0)
    {
        return -1;
    }
    // If discriminant is less than 0, there are complex roots.
    else if((b*b-4*a*c) < 0)
    {
        return -2;
    }
    // Otherwise, return the real numbers.
    else
    {    
        root1 = (-b+sqrt((b*b)-(4*a*c)))/(2*a);
        root2 = (-b+sqrt((b*b)-(4*a*c)))/(2*a);    
        return 0;
    }
}

// Print results on a formatted table
int numTable(double a, double b, double c, double &root1, double &root2)
{
    ofstream outputFile;

    // Write the output to the file.
    outputFile << "a\t" << "     b\t" << "\t  c\t\tRoot 1"
    << "\tRoot 2" << "\tErrors" << endl;
    outputFile << "------------------------------------------------" 
    << "--------------" << endl;
    for(int j = 1; j <=3; j++)
    {
        outputFile << a << " " << b << " " << c << '\t' << root1
        << "\t" << root2 << endl;
    }
    return 0;
}

// Call every function.
int main()
{
    ifstream inputFile;
    ofstream outputFile;
    string fileName;
    double a, b, c, root1, root2, x, y, z;

    // Get the name of the input file from the user.
    cout << "Enter the name of the file: ";
    cin >> fileName;

    // Open the file.
    inputFile.open(fileName.c_str());

    // Open the output file named quadratic table.txt.
    outputFile.open("quadratic result.txt");

    // If successfully opened, process the file data.
    if(inputFile)
    {
        // Read each line until end of file.
        while(!inputFile.eof())
        {
            quadValues(x, y, z);
            calcRoots(a, b, c, root1, root2);
            numTable(a, b, c, root1, root2);
        }
        // Close the file.
        inputFile.close();
    }
    else
    {
        // Display the error message
        cout << "There was an error opening the input file.\n";
    }
    // Close the output file.
    outputFile.close();
    return 0;
}

I can't seem to get any output for this program. Is there anything I need to change in all of my functions?

Edited 3 Years Ago by andrew.mendonca.967: Forgot to add info

andrew.mendonca.967
Deleted Member

You need to pass the ifstream that is opened in main() to the function that needs to read the data.

int quadValues(ifstream& in, double &x, double &y, double &z)

And to the function that prints the results

int numTable(ofstream& out, double a, double b, double c, double &root1, double &root2)

Make sure to change the lines in main() that call those two functions. You can then delete the declarations of ifstream inside quadValue() and the declaration of ofstream in numTable() because they are not used.

Edited 3 Years Ago by Ancient Dragon

Here is my revised solution:

#include<iostream>
#include<iomanip>
#include<string>
#include<fstream>
#include<cmath>
using namespace std;

// Read each set of values from the input file.
int quadValues(ifstream &inputFile, double &x, double &y, double &z)
{
    int value;    
    string fileName;

    // Get the name of the input file from the user.
    cout << "Enter the name of the file: ";
    cin >> fileName;

    // Open the file.
    inputFile.open(fileName.c_str());

    // If successfully opened, process the file data.
    if(inputFile)
    {
        // Read each line until end of file.
        while(!inputFile.eof())
        {
            // Indicate whether function read three values.
            while(inputFile >> x >> y >> z)
            {
                cout << x << y << z << endl;
                // Otherwise, print error message.
                if(value < 3)
                {
                    return 0;
                }
            }
        }
        // Close the file.
        inputFile.close();
    }
    else
    {
        // Display the error message
        cout << "There was an error opening the input file.\n";
    }
    return 0;
}

// Calculate the roots
int calcRoots(double a, double b, double c, double &root1, double &root2)
{
    // If a is 0, there is no solution.
    if(a == 0)
    {
        return -1;
    }
    // If discriminant is less than 0, there are complex roots.
    else if((b*b-4*a*c) < 0)
    {
        return -2;
    }
    // Otherwise, return the real numbers.
    else
    {    
        root1 = (-b+sqrt((b*b)-(4*a*c)))/(2*a);
        root2 = (-b+sqrt((b*b)-(4*a*c)))/(2*a);    
        return 0;
    }
}

// Print results on a formatted table
int numTable(ofstream &outputFile, double a, double b, double c, double &root1, double &root2)
{
    // Open the output file named quadratic table.txt.
    outputFile.open("quadratic result.txt");

    // Write the output to the file.
    outputFile << "a" << setw(14) << "b" << setw(14) << "c" << setw(8)
    << "Root 1" << setw(8) << "Root 2" << setw(8) << "Errors" << endl;
    outputFile << "------------------------------------------------" 
    << "--------------" << endl;
    for(int j = 1; j <=3; j++)
    {
        outputFile << a << setw(8) << b << setw(8) << c << setw(8) << root1
        << setw(8) << root2 << endl;
    }
    return 0;
}

// Call every function.
int main()
{
    ifstream inputFile;
    ofstream outputFile;
    double a, b, c, root1, root2, x, y, z;

    quadValues(inputFile, x, y, z);
    calcRoots(a, b, c, root1, root2);
    numTable(outputFile, a, b, c, root1, root2);

    return 0;
}

Here is my output:

a             b             c  Root 1  Root 2  Errors
--------------------------------------------------------------
3.48985e+2581.78843e-3071.78865e-307-2.33312e+1765.2843e-308
3.48985e+2581.78843e-3071.78865e-307-2.33312e+1765.2843e-308
3.48985e+2581.78843e-3071.78865e-307-2.33312e+1765.2843e-308

Is there anything else I need to fix in my functions in order to get the correct output?

Edited 3 Years Ago by andrew.mendonca.967

The logic for all those functions is a little off. Look at quadFile() and trace in your mind what it is doing. Notice that there is only one instance of the variable x, y and z, yet the function is reading them multiple times without saving the values anywhere. You need to save all the values of x, y and z somewhere in either an array, linked list, or std::vector so that they can be used in the other functions.

Another way to do it without using an array is for quadFile() to read a line from the text file then call the other two functions. main() only calls one function -- quadFile(). Something like this

quadFile()
{
    while( infile >> x >> y >> z)
    {
        double root1,root2;
        CalcRoots(x,y,z,root1,root2);
        numTable(x,y,z,root1,root2);
    }
}

That function also had two while loops -- the one starting on line 25 is not needed because the loop on 28 will read all the values in the file until eof is reached. Delete the while loop that starts on line 25.

Ok. I fixed the quadValues(), numTable(), and main() function. Here is my new solution:

#include<iostream>
#include<iomanip>
#include<string>
#include<fstream>
#include<cmath>
using namespace std;

int quadValues(ifstream&, double&, double&, double&);
int calcRoots(double, double, double, double&, double&);
int numTable(ofstream&, double, double, double, double&, double&);

// Read each set of values from the input file.
int quadValues(ifstream &inputFile, double &x, double &y, double &z)
{
    int value;   
    string fileName;
    double root1, root2;
    ofstream outputFile;

    // Get the name of the input file from the user.
    cout << "Enter the name of the file: ";
    cin >> fileName;

    // Open the file.
    inputFile.open(fileName.c_str());

    // If successfully opened, process the file data.
    if(inputFile)
    {
        // Indicate whether function read three values.
        while(inputFile >> x >> y >> z)
        {
            calcRoots(x, y, z, root1, root2);
            numTable(outputFile, x, y, z, root1, root2);
        }
        // Close the file.
        inputFile.close();
    }
    else
    {
        // Display the error message
        cout << "There was an error opening the input file.\n";
    }
    return 0;
}

// Calculate the roots
int calcRoots(double a, double b, double c, double &root1, double &root2)
{
    // If a is 0, there is no solution.
    if(a == 0)
    {
        return -1;
    }
    // If discriminant is less than 0, there are complex roots.
    else if((b*b-4*a*c) < 0)
    {
        return -2;
    }
    // Otherwise, return the real numbers.
    else
    {    
        root1 = (-b+sqrt((b*b)-(4*a*c)))/(2*a);
        root2 = (-b+sqrt((b*b)-(4*a*c)))/(2*a);    
        return 0;
    }
}

// Print results on a formatted table
int numTable(ofstream &outputFile, double a, double b, double c, double &root1, double &root2)
{
    // Open the output file named quadratic table.txt.
    outputFile.open("quadratic result.txt");

    // Write the output to the file.
    outputFile << "a" << setw(7) << "b" << setw(6) << "c" << setw(14)
    << "Root 1" << setw(12) << "Root 2" << setw(13) << "Errors" << endl;
    outputFile << "------------------------------------------------" 
    << "--------------" << endl;
    outputFile << a << setw(8) << b << setw(8) << c << setw(12) << root1
    << setw(12) << root2 << endl;
    // Close the output file.
    outputFile.close();

    return 0;
}

// Call every function.
int main()
{
    ifstream inputFile;
    double x, y, z;

    quadValues(inputFile, x, y, z);

    return 0;
}

Here is my new output:

a      b     c        Root 1      Root 2       Errors
--------------------------------------------------------------
0      -2    8.85     1.72323     1.72323

It looks like I'm on the right track, but my output is still not quite correct. I still need to print the other four lines. In the first function, I'm not sure how to return an error code if there are few values on the line. Also, if a = 0, the program should return no solution, and if the discriminant is less than 0, the program should return complex roots. Is there anything else I need to add/change?

This question has already been answered. Start a new discussion instead.