2

having trouble displaying the decimals after reading the data.

As the title says.. here are some code snippets.

the header for the student obj

class StudentRecordData
{
protected:
   double Marks[MAX_COURSES];
   unsigned int Age;
   unsigned int ID;
   unsigned int CourseCount;
   char FirstName[LEN_FN];
   char LastName[LEN_FN];
   Course  Courses[MAX_COURSES];
};

student header:

class Student : public StudentRecordData {

public:
    double *getMarks();
    unsigned int getAge();
    unsigned int getID();
    unsigned int getCourseCount();
    char *getFirstName();
    char *getLastName();
    Course *getCourses();
    double getAverage();

    int operator < (Student &);
    int operator < (const char &);
};

Student implementation (inherited the above)

#include "Student.h"
#include <iostream>
#include <cstring>
using namespace std;

double *Student::getMarks() {
    return Marks;
}

unsigned int Student::getAge() {
    return Age;
}

unsigned int Student::getID() {
    return ID;
}

unsigned int Student::getCourseCount() {
    return CourseCount;
}

char *Student::getFirstName() {
    return FirstName;
}

char *Student::getLastName() {
    return LastName;
}

Course *Student::getCourses() {
    return Courses;
}

int Student::operator<(Student &s) {
    int ret = 0;

    int LNRet = strcmp(this->getLastName(), s.getLastName());
    int FNRet = strcmp(this->getFirstName(), s.getFirstName());

    if (LNRet < 0) {
        ret = 1;
    } else if (LNRet == 0) {
        if (FNRet < 0) {
            ret = 1;
        }
    }

    return ret;
}

int Student::operator<(const char &s) {
    cout << "in char *!" << endl;
    int ret = 0;

    return ret;
}

double Student::getAverage() {
    double total = 0.00;
    for (int i = 0; i < (getCourseCount()); i++) {
        total = total + getMarks()[i];
    }
    return total / getCourseCount();
}

the main

#include "Course.h"
#include "Student.h"
#include "Node.h"
#include "LinkedList.h"
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;

int main(void) {
    char input[] = "OOP344.dat";
    char output[] = "OUTPUT.txt";
    Student student;
    LinkedList list;
    Node *node;

    // read in file
    ifstream ifile(input, ios::binary);
    while (!ifile.eof()) {
        ifile.read(reinterpret_cast<char *>(&student), sizeof(Student));

        node = new Node(student);
        list.addNode(node);
    }
    ifile.close();

    list.sort();

    // write to file
    ofstream ofile(output);
    if (ofile.is_open()) {

        for (node = list.getFirstNode(); node; node = list.getNextNode(node)) {
            cout << setw(10) << "Last Name" << setw(12) << "First Name" << setw(5) << "Age" << setw(12) << "Student ID" <<
                    setw(15) << "Course"    << setw(7) << "Mark" << endl;
            cout << setw(10) << "=========" << setw(12) << "==========" << setw(5) << "===" << setw(12) << "==========" <<
                    setw(15) << "======"    << setw(7) << "=====" << endl;
            cout << setw(10) << node->getValue().getLastName()
                 << setw(12) << node->getValue().getFirstName()
                 << setw(5) << node->getValue().getAge()
                 << setw(12) << node->getValue().getID()
                 << setw(22) << node->getValue().getAverage()
                 << endl;

                    int sem, sem_prev;

                    for (int i = 0; i < node->getValue().getCourseCount(); i++) {
                        sem = (int)node->getValue().getCourses()[i].Semester;
                        sem_prev = (int)node->getValue().getCourses()[i-1].Semester;

                        if (!(sem == sem_prev)) {
                            cout << setw(45) << "Sem " << (int)node->getValue().getCourses()[i].Semester << ":"
                                 << setw(7) << node->getValue().getCourses()[i].Name
                                 << setw(7) << setprecision(4) << node->getValue().getMarks()[i] << endl;
                        } else {
                            cout << setw(54) << node->getValue().getCourses()[i].Name
                                 << setw(7) << setprecision(4) << node->getValue().getMarks()[i] << endl;
                        }

                    }

                     cout << endl;
        }
    }
    ofile.close();

    return (0);
}

output:

Last Name  First Name  Age  Student ID         Course   Mark
 =========  ==========  ===  ==========         ======  =====
   Sakedad        Roya   25      486503                 74.31
                                         Sem 1: APC100     69
                                                EAC150     92
                                                ICA002     76
                                                IOS110     87
                                                IPC144     99
                                         Sem 2: ULI101     62
                                                DBS201     66
                                                IBC233     94
                                                INT222     58
                                                OOP244     67
                                         Sem 3: DBS301     61
                                                INT322     89
                                                SYS366     52
                                                BAC344     80
                                                OOP344     63
                                         Sem 4: DCN455     74

the problem is in this line near the bottom. it won't display any decimal points. any help is greatly appreciated.

  setprecision(4) << node->getValue().getMarks()[i] 

i can supply any other files which may be helpful. i'm just hoping my mistakes are somewhere in the main.

user1554903
  • 111
  • 1
  • 1
  • 4
  • 3
    If you have to use pastebin to post your code then your pasting way to much information. – Security Hound Apr 01 '13 at 19:25
  • 2
    **[`while (!stream.eof())` is wrong](http://stackoverflow.com/q/5605125/560648)** - which resource instructed you to do that? – Lightness Races in Orbit Apr 01 '13 at 19:29
  • @LightnessRacesinOrbit It was probably an outdated book he read.. – 0x499602D2 Apr 01 '13 at 19:30
  • Could I see the a sample of the output, and the code for the getMarks method? – Alan Apr 01 '13 at 19:37
  • updated with the getMarks and output Alan. thank you in advance. – user1554903 Apr 01 '13 at 19:51
  • that is the real code. i haven't pasted it every file/class though.. – user1554903 Apr 01 '13 at 20:04
  • Please identify where in the main you have the instruction to print 74.31. Logically it should be between `<< setw(12) <getValue().getID()` and the for loop, but it isn't. – Alan Apr 01 '13 at 20:07
  • updated the main alan. i actually made some modifications while asking this question and posted the output of the updated main. here it is: << setw(22) << node->getValue().getAverage() – user1554903 Apr 01 '13 at 20:11
  • @David It's always been wrong, ever since iostreams were invented, so it's not a question of whether the book was outdated or not, but whether the author knew what he was talking about or not. – James Kanze Apr 01 '13 at 20:11
  • If your input works, it is only by chance. You can't just copy bits from a file and expect anything good to happen. You need to know the actual format of the data in the file, and parse it. – James Kanze Apr 01 '13 at 20:14
  • @user1554903 Just to confirm, your marks data does contain at least one mark with a fractional value, right? Otherwise, for example, even with `setprecision(4)` 76.0000 will be outputted as just 76. If you want to force the full number of decimal points you would need to use '<< std::fixed << std::setprecision(4)`. – Alan Apr 01 '13 at 20:15
  • @JamesKanze the binary file and the format were supplied to me and i'm certain they are correct. – user1554903 Apr 01 '13 at 20:19
  • @David: It's _never_ been correct. – Lightness Races in Orbit Apr 01 '13 at 20:56
  • @user1554903 Yes. I'm supposing that this is some sort of homework assignment, and the professor has supplied the input file, and told you to use `istream::read()` on it. It's a technique which doesn't work except in exceptional cases, however. – James Kanze Apr 01 '13 at 22:12

1 Answers1

2

You've given us a lot of code to wade through for a simple formatting issue, but I don't see where you tell the output stream how you want the floating point values formatted. The default formatting is defined so that it will result in something readable for all possible values, but in practice, it's never what you want for any particular set of values (except maybe in log files or for serialization purposes). In your case (and in a lot of smaller programs), you could probably get by with just setting the floating point format to fixed:

ofile.setf( std::ios_base::fixed, std::ios_base::floatfield );

More generally, the best practice would be to define a manipulator for the different semantic values you need: e.g.:

std::ostream&
mark( std::ostream& dest )
{
    dest.setf( std::ios_base::fixed, std::ios_base::floatfield );
    dest.precision( 2 );
    return dest;
}

You can then simply write:

ofile << ... << mark << node->getValue().getMarks()[i] << ...

Note, however, that both the format option and the precision are sticky; they will remain set until changed. In any significant code, it is a good practice to reset them to what they were before.

James Kanze
  • 142,482
  • 15
  • 169
  • 310
  • thanks for your answer. i actually did try using setprecision before and no luck. and i just tried the setf command as you described and it displayed my number with 4 0's (78.0000) at the bottom. so i'm assuming it was the way i read the data in from the file? – user1554903 Apr 01 '13 at 20:16
  • This is pretty much what I just posted in comments above. While @user1554903 used `setprecision`, he didn't use `fixed`. This means that because his marks are actually integer values (despite being held in an array of doubles) std::cout is only displaying the integer version. – Alan Apr 01 '13 at 20:19
  • if there isn't any other glaring problems, i'm going to assume that i was provided integers, in fact. – user1554903 Apr 01 '13 at 20:25
  • @user1554903 From the code I see, you're just stuffing whatever bit patterns happen to be in the file into the doubles. At any rate, the resulting doubles have a value; they are neutral with regards to how you format them for output. – James Kanze Apr 01 '13 at 22:10