0

I'm working on a project for school, and after finishing and testing it, I separated it into a file containing my functions, the main function, and a header file. Both the functions and the header compile fine, but when I compile the main, I get the error which is included at the bottom of this post

Here is the main file:

#include "header.h"
using namespace std;

int main()
{
    bool exit = false;

    int idIn;
    //header

    //creates enumerator for menu
    enum CHOICE {add=1, remove=2, display=3, search=4, results=5, quit=6};
    int input;

    //outputs menu


    //switch case for input
    while (!exit)
    {
        cout << "1: Add" << endl;
        cout << "2: Remove" << endl;
        cout << "3: Display" << endl;
        cout << "4: Search" << endl;
        cout << "5: Results" << endl;
        cout << "6: Quit" << endl;
        cout << "Enter choice: ";
        cin >> input;
        switch (input)
        {
            case add:
                add_student();
                break;
            case remove:
                cout << "Enter the id for the student to remove: ";
                cin >> idIn;
                remove_student(idIn);
                if(!removed)
                {
                    cout << "Student does not exist" << endl;
                }
                break;
            case display:
                //naming the function "Display" causes a compile error
                student_display();
                break;
            case search:
                //naming the function "search" causes a compile error
                cout << "Enter the id for the student to search for: ";
                cin >> idIn;
                student_search(idIn);
                if(!found)
                {
                    cout << "Student does not exist" << endl;
                }
                break;
            case results:
                exportResults();
                cout << "Results exported to file: averages.dat" << endl;
                break;
            case quit:
                cout << "Bye" << endl;
                exit = true;
                break;
            default:
                cout << "INVALID ENTRY" << endl;
                break;
        }
    }

    return 0;
}

Here is the function file:

#include "header.h"
using namespace std;

int getNumber()
{
    ifstream fin;
    fin.open("student.dat");
    if (fin.fail())
    {
        cout<<"File error."<<endl;
        exit(1);
    }
    int count=0;
    string line;
    while(!fin.eof())
    {
        getline(fin, line);
        ++count;
    }

    fin.close();
    return(count);

}

int findMinimum(int grades[], int numgrades)
{
    int minimum = grades[0];
    for(int i = 0; i < numgrades; i++)
    {
        if (grades[i] < minimum)
        {
            minimum = grades[i];
        }
    }
    return minimum;
}

void add_student()
{
    studentFile.open("student.dat", ios_base::app);
    if (studentFile.fail())
    {
        cout<<"File error."<<endl;
        exit(1);
    }

    //declarations
    string first;
    string last;
    student newstudent;
    int input;

    //input student info
    cin.ignore();
    cout << "Last name: ";
    getline(cin, last);
    cout << "First name: ";
    getline(cin,first);
    newstudent.name = last + "," + first;
    cout << "Enter the students id number: ";
    cin >> newstudent.id;
    cout << "Enter the number of tests taken: ";
    cin >> newstudent.numTests;

    //inputs testgrades for student
    newstudent.tests = new int[newstudent.numTests];

    for(int i = 0; i < newstudent.numTests; i++)
    {
        cout << "Enter test grade " << i+1 << ": ";
        cin >> newstudent.tests[i];
    }

    //write student info to file
    studentFile << newstudent.name << "," << newstudent.id <<","<< newstudent.numTests << ",";

    //write test grades to file
    for(int i = 0; i < newstudent.numTests; i++)
    {
        studentFile << newstudent.tests[i] << ",";
    }
    studentFile << endl;

    //closes student file
    studentFile.close();
    delete [] newstudent.tests;
}

void remove_student(int id)
{
    int numstudents = getNumber();
    removed = false;
    string intIn;
    string input;
    string first;
    string last;
    //creates dynamic array of students
    student *students;
    students = new student[numstudents];

    //opens students.dat file
    readFile.open("student.dat");
    if (readFile.fail())
    {
        cout<<"File error."<<endl;
        exit(1);
    }

    //cout << "Searching " << numstudents << " students" << endl;

    //scan in student list
    for(int i = 0; i < numstudents; i++)
    {
        student newstudent;

        getline(readFile,input);
        stringstream ss (input);

        getline(ss, first, ',');
        getline(ss, last, ',');
        newstudent.name = first + "," + last;

        getline(ss, intIn, ',');
        newstudent.id = stoi(intIn);

        getline(ss, intIn, ',');
        newstudent.numTests = stoi(intIn);

        newstudent.tests = new int[newstudent.numTests];

        for(int j = 0; j < newstudent.numTests; j++)
        {
            getline(ss, intIn, ',');
            newstudent.tests[j] = stoi(intIn);
        }
        students[i] = newstudent;
    }
    readFile.close();

    studentFile.open("student.dat");
    if (readFile.fail())
    {
        //cout<<"File error on open."<<endl;
        //exit(1);
    }

    for(int i = 0; i < numstudents - 1; i++)
    {
        student out;
        out = students[i];

        if(out.id!=id)
        {
            studentFile << out.name << "," << out.id << "," << out.numTests << ",";

            for(int j = 0; j < out.numTests; j++)
            {
                studentFile << out.tests[j] << ",";
            }

            studentFile << endl;
        }
        else
        {
            removed = true;
        }
    }

    //delete student array
    delete [] students;

    //close open files
    studentFile.close();
}

void student_display()
{
    int numstudents = getNumber();
    string intIn;
    string input;
    string first;
    string last;
    readFile.open("student.dat");
    if (readFile.fail())
    {
        cout<<"File error."<<endl;
        exit(1);
    }

    for(int i = 0; i < numstudents - 1; i++)
    {
        student printStudent;

        getline(readFile,input);
        stringstream ss (input);

        getline(ss, first, ',');
        getline(ss, last, ',');
        printStudent.name = first + "," + last;
        cout << setw(30) << printStudent.name;

        getline(ss, intIn, ',');
        printStudent.id = stoi(intIn);
        cout << setw(15) << printStudent.id;

        getline(ss, intIn, ',');
        printStudent.numTests = stoi(intIn);

        printStudent.tests = new int[printStudent.numTests];

        for(int j = 0; j < printStudent.numTests; j++)
        {
            getline(ss, intIn, ',');
            printStudent.tests[j] = stoi(intIn);
            cout << setw(5) << printStudent.tests[j];
        }
        //students[i] = printStudent;
        cout << endl;
        delete [] printStudent.tests;
    }

    readFile.close();

}

void student_search(int id)
{
    int numstudents = getNumber();
    string intIn;
    string input;
    string first;
    string last;
    found = false;
    readFile.open("student.dat");
    if (readFile.fail())
    {
        cout<<"File error."<<endl;
        exit(1);
    }

    for(int i = 0; i < numstudents - 1; i++)
    {
        student printStudent;

        getline(readFile,input);
        stringstream ss (input);

        getline(ss, first, ',');
        getline(ss, last, ',');
        printStudent.name = first + "," + last;


        getline(ss, intIn, ',');
        printStudent.id = stoi(intIn);
        if(printStudent.id == id)
        {
            cout << printStudent.name;
            cout << setw(15) << printStudent.id;

            getline(ss, intIn, ',');
            printStudent.numTests = stoi(intIn);

            printStudent.tests = new int[printStudent.numTests];

            for(int j = 0; j < printStudent.numTests; j++)
            {
                getline(ss, intIn, ',');
                printStudent.tests[j] = stoi(intIn);
                cout << setw(5) << printStudent.tests[j];
            }
            //students[i] = printStudent;
            cout << endl;
            delete [] printStudent.tests;
            found = true;
        }
    }
    readFile.close();

}

void exportResults()
{
    //decarations.
    int numStudents = getNumber();
    double average;
    double min;
    double sum;
    int calcTests;
    string intIn;
    string input;
    string first;
    string last;

    //opens export file
    expFile.open("averages.dat");
    if(readFile.fail())
    {
        cout << "File error" << endl;
        exit(1);
    }

    //opens read file
    readFile.open("student.dat");
    if (readFile.fail())
    {
        cout<<"File error."<<endl;
        exit(1);
    }

    //scans student file and copys ids and average grade to the export file
    for(int i = 0; i < numStudents - 1; i++)
    {
        //sets values
        sum = 0;
        min = 0;
        //reads student info from file
        student printStudent;

        //sets up string stream
        getline(readFile,input);
        stringstream ss (input);

        //gets name (not saved here)
        getline(ss, first, ',');
        getline(ss, last, ',');
        printStudent.name = first + "," + last;

        //reads and prints id to exp file
        getline(ss, intIn, ',');
        printStudent.id = stoi(intIn);
        expFile << printStudent.id;

        //gets number of tests
        getline(ss, intIn, ',');
        printStudent.numTests = stoi(intIn);
        calcTests = printStudent.numTests;

        //copys grades to new array for the find minimum function
        int grades[printStudent.numTests];
        for(int j = 0; j < printStudent.numTests; j++)
        {
            getline(ss, intIn, ',');
            grades[j] = stoi(intIn);
            //ads grade to sum
            sum += grades[j];
        }
        //gets minimum from getminimum function
        min = findMinimum(grades, calcTests);

        //drop lowest test grade;
        sum -= min;

        //calc average
        average = sum/(printStudent.numTests-1);

        //print grade
        expFile << setprecision(1) << fixed << setw(7) << average << endl;
    }


    //closes files
    readFile.close();
    expFile.close();
}


Here is the header file:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <iomanip>

using namespace std;

const int TESTS = 5;
ofstream studentFile;
ifstream readFile;
ofstream expFile;
bool removed;
bool found;

struct student
{
    string name;
    int numTests;
    int id;
    int *tests;
    double averageScore;
};

int getNumber();

int findMinimum(int, int);

void add_student();

void remove_student(int);

void student_display();

void student_search(int);

void exportResults();

//int main();

When I compile the main function, I get the following error:

g++ Project2_main.cpp
/tmp/ccKi3gpQ.o: In function `.L4':
cwh0114Project2_main.cpp:(.text+0x26a): undefined reference to `add_student()'
/tmp/ccKi3gpQ.o: In function `.L6':
cwh0114Project2_main.cpp:(.text+0x2aa): undefined reference to `remove_student(int)'
/tmp/ccKi3gpQ.o: In function `.L7':
cwh0114Project2_main.cpp:(.text+0x2f7): undefined reference to `student_display()'
/tmp/ccKi3gpQ.o: In function `.L8':
cwh0114Project2_main.cpp:(.text+0x337): undefined reference to `student_search(int)'
/tmp/ccKi3gpQ.o: In function `.L9':
cwh0114Project2_main.cpp:(.text+0x384): undefined reference to `exportResults()'
collect2: error: ld returned 1 exit status
  • 5
    Well, you don't have a definition for those functions - only the declarations. What would you expect to happen if you call `add_student()`? What function do you expect it to call? – Ted Lyngmo Nov 19 '21 at 00:33
  • @Ted Ghostbusters! DUH! – user4581301 Nov 19 '21 at 00:37
  • @user4581301 :-) Of course, silly me! – Ted Lyngmo Nov 19 '21 at 00:38
  • your header has _declarations_, saying "This function exists somewhere. You'll see it when you compile it. I promise." The compiler trusts you and builds code as if those symbols would exist. The linker builds the executable tries to resolve those symbols and fails. You did actually write implementations for those functions in a .cpp file, right? If so, compile and link it in. Otherwise, what would you _expect_ to happen when those are called? Compilers aren't psychic. – Chris Uzdavinis Nov 19 '21 at 00:38
  • Sorry, I forgot to include the function file, it's there now. – Cameron Haynes Nov 19 '21 at 01:02
  • Please add the build command. Odds are very high that you've neglected to pass the function file to the compiler or linker either by omitting it from the command line or not adding it to the build automation tool you're using. – user4581301 Nov 19 '21 at 01:09
  • I'm just using g++ to compile them each individualy. We haven't been tought any other meathod so far. – Cameron Haynes Nov 19 '21 at 01:38
  • Syntax matters. Please add the exact build instructions used to the question because the answer will be in (or more likely accidentally omitted from) the instructions. – user4581301 Nov 19 '21 at 06:59
  • I've added the command above the error message – Cameron Haynes Nov 19 '21 at 17:14

0 Answers0