problem passing array of struct to a function throwing undefined reference c++ - c++

I'm having issues with passing an array of structures to a function that searches them. I delcare an array of structs outside of main then copy it to a new array of structs inside of main (so I have access to them inside main and can pass them easier). Not sure why it is failing though. Can anyone help me?
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <algorithm>
using namespace std;
const int MAX = 2000000;
const string DFile = "DFile.dms";
const string EFile = "EFile.dms";
const string VFile = "VFile.dms";
struct dogs
{
int did;
int age;
} DFBuffer[MAX];
struct examine
{
int vid;
int did;
int fee;
} EFBuffer[MAX];
struct vet
{
int vid;
int eLevel;
} VFBuffer[MAX];
void readDF(ifstream&);
void readEF(ifstream&);
void readVF(ifstream&);
int getLineCount(ifstream&);
bool dogCompare(dogs lhs, dogs rhs) {return lhs.did < rhs.did;}
bool vetCompare(vet lhs, vet rhs) {return lhs.vid < rhs.vid;}
bool examCompare(examine lhs, examine rhs) {return lhs.vid < rhs.vid;}
void vetExamSeach(struct vet newVetArray[], struct examine newExamArray[],
int, int);
int main()
{
dogs * newDogArray = new dogs[MAX];
examine * newExamArray = new examine[MAX];
vet * newVetArray = new vet[MAX];
ifstream DF, EF, VF;
int dogCount = 0, examCount = 0, vetCount = 0;
DF.open(DFile);
readDF(DF);
EF.open(EFile);
readEF(EF);
VF.open(VFile);
readVF(VF);
DF.open(DFile);
dogCount = getLineCount(DF);
EF.open(EFile);
examCount = getLineCount(EF);
VF.open(VFile);
vetCount = getLineCount(VF);
for(int i = 0; i < dogCount; i++)
newDogArray[i] = DFBuffer[i];
for(int i = 0; i < vetCount; i++)
newVetArray[i] = VFBuffer[i];
for(int i = 0; i < examCount; i++)
newExamArray[i] = EFBuffer[i];
cout << "Sorting...\n";
sort(newDogArray, newDogArray + dogCount, dogCompare);
sort(newExamArray, newExamArray + examCount, examCompare);
sort(newVetArray, newVetArray + vetCount, vetCompare);
cout << "Sorting complete!\n";
vetExamSeach(newVetArray, newExamArray, vetCount, examCount);
return 0;
}
here is the search function. for the sake of this question, im just trying to print what i pass it.
void search(vet newVetArray[], examine newExamArray[], int vCount, int eCount)
{
for(int i = 1; i < vCount; i++)
cout << "in search: " << newVetArray[i].vid << ' ' << newVetArray[i].eLevel << endl;
}
here is the error I'm getting
Here is my files. Not asking you to do my HW just help me solve my issue

When, I run your code, I get the same compilation error of undefined reference for readDf, readEF, readVF, getLineCount and vetExamSeach.
The error is because there is no definition of these functions. There are only just decalarations. When I define them (something random) the errors are gone.
So, define the function(s) and the error(s) would be gone.

Related

StringBuilder Class in C++ not working properly

I'm working on an assignment to create a class called StringBuilder that is used for fast string concatenation. I'm supposed to store strings in a dynamic array and have methods such as Append(string) which adds a new string to the dynamic array. The method I'm currently struggling with is GetString() that creates a single string on the heap that is the length of all the strings in the dynamic array that have been added thus far.
the code I have so far is:
okay my main problem is my GetString() function prints out hello over and over again until I force quit the program in Xcode. I don't understand what inside that method is making that happen.
My header file:
#pragma once
#include <string>
using namespace std;
class StringBuilder
{
public:
StringBuilder();
//~StringBuilder();
void GetString();
void AppendAll(string*, int);
void Length();
void Clear();
void Append(string userString);
void DoubleArray(string*& allWords, int newCapacity);
private:
string* p_array;
int capacity = 5;
};
my .cpp file :
#include "StringBuilder.hpp"
#include <iostream>
#include <string>
using namespace std;
----------
void StringBuilder::Append(string userString)
{
int nextWordPosition = 0;
for(int i=0; i < capacity ; i++)
{
p_array[i] = userString;
cout << p_array[i] << endl;
nextWordPosition +=1;
if(capacity == nextWordPosition)
{
capacity *=2;
DoubleArray(p_array, capacity * 2);
}
}
nextWordPosition++;
}
void StringBuilder::DoubleArray(string*& allWords, int newCapacity)
{
string* p_temp = new string[newCapacity];
for(int i =0; i < newCapacity / 2; i++)
{
p_temp[i] = allWords[i];
}
delete[] allWords;
allWords = p_temp;
}
void StringBuilder:: GetString()
{
for(int i=0; i < capacity ; i++)
{
cout << p_array[i]<< endl;
}
}
my main.cpp file :
#include <iostream>
#include <string>
#include "StringBuilder.hpp"
using namespace std;
int main()
{
string testString = "hello";
string test = "world!";
StringBuilder Builder1;
Builder1.Append(testString);
Builder1.Append(test);
Builder1.GetString();
return 0;
}

Create Multiple Objects in a loop c++

I'm a beginner and was researching to find out if you can grab a name from an array to then put that name as the name of the object in a for loop.
The code a specifically created for this question is represented below:
#include <iostream>
using namespace std;
class YourMum{
public:
string name;
YourMum(string aName){
name = aName;
}
};
int main()
{
string names[5] = {"Jeremy_Clarkson", "Boris_Johnson", "Vladmir_Putin", "Peter_Griffin", "MeAndYourMum"};
for(int i = 0; i < 4; i++) {
YourMum names[i];
cout << names[i].name << endl;
cout << "You are great if you answer my question!";
}
return 0;
}
Okay, it's not clear what you're trying to do, but you've got a few things that aren't a good idea.
First, you defined string names[5] and then inside loop you hid names by making a second variable with the same name. While that's legal, it's a bad practice.
Second, you're using the second one (YourMum names) illegally:
You declared it as length i (using a non-standard feature of the compiler) but then reference element i. The elements of an array of length i range from 0..i-1, so [i] is one element past the end.
And you haven't initialized it anyway.
I'm not really clear what you're trying to do, so I can't even provide example code of how to do it.
The YourMum class you have shown is not default constructible, so YourMum names[size]; will not work. Every object of YourMum needs to be passed a parameter in order to create it. You can use placement-new for that, eg:
#include <iostream>
#include <type_traits>
using namespace std;
class YourMum{
public:
string name;
YourMum(string aName){
name = aName;
}
};
int main()
{
string names[5] = {"Jeremy_Clarkson", "Boris_Johnson", "Vladmir_Putin", "Peter_Griffin", "MeAndYourMum"};
std::aligned_storage<sizeof(YourMum), alignof(YourMum)>::type arr[5];
YourMum *mums = reinterpret_cast<YourMum*>(arr);
for(int i = 0; i < 5; i++) {
new (&mums[i]) YourMum(names[i]);
}
for(int i = 0; i < 5; i++) {
cout << mums[i].name << endl;
cout << "You are great if you answer my question!";
}
for(int i = 0; i < 5; i++) {
mums[i].~YourMum();
}
return 0;
}
Or, you can use std::vector instead:
#include <iostream>
#include <vector>
using namespace std;
class YourMum{
public:
string name;
YourMum(string aName){
name = aName;
}
};
int main()
{
string names[5] = {"Jeremy_Clarkson", "Boris_Johnson", "Vladmir_Putin", "Peter_Griffin", "MeAndYourMum"};
std::vector<YourMum> mums;
mums.reserve(5);
for(int i = 0; i < 5; i++) {
mums.emplace_back(names[i]);
}
for(int i = 0; i < 5; i++) {
cout << mums[i].name << endl;
cout << "You are great if you answer my question!";
}
return 0;
}
First of all, you should rename the name variable to something like _name or name_ for lisibility (to differenciate it from variables that aren't in the class), and you should also use the private section of your class to declare it and use getters/setters functions to edit it. Secondly, in your code you are declaring the object inside a loop, so it will get destroyed as soon as the loop iterates again, so if you want to create n objects in a loop and interact with them after you should either use a container class (like std::vector) or use a default constructor (which is better). Here is an updated version of your code:
#include <iostream>
#include <string>
class YourMum
{
public:
YourMum(void) : _name() { }
YourMum(std::string name) : _name(name) { }
std::string getName(void) const { return _name; }
void setName(std::string name) { _name = name; }
private:
std::string _name;
};
int main()
{
std::string names[5] = { "Jeremy_Clarkson", "Boris_Johnson", "Vladmir_Putin", "Peter_Griffin", "MeAndYourMum" };
YourMum mums[5];
for (int i = 0; i < 5; i++)
{
mums[i].setName(names[i]);
std::cout << mums[i].getName() << std::endl
<< "You are great if you answer my question!" << std::endl;
}
// this way you can still access mums here if you want to
return 0;
}
If you want to access to a class by it's name as index what you can also do is using std::map like this
#include <map>
int main()
{
std::string names[5] = { "Jeremy_Clarkson", "Boris_Johnson", "Vladmir_Putin", "Peter_Griffin", "MeAndYourMum" };
std::map <std::string, YourMum> mums;
for (int i = 0; i < 5; i++)
mums[names[i]] = YourMum(names[i]);
std::cout << mums["Jeremy_Clarkson"].getName() << std::endl;
return 0;
}
Try This
> for(int i = 0; i < 4; i++) {
> YourMum name(names[i]);
>
> cout << name.name << endl;
> cout << "You are great if you answer my question!";
> }

Why the number of grades is 0?

#include<iostream>
#include<string>
using namespace std;
class Student {
public:
const int codeStud;
int noGrades = 0;
int* grades = NULL;
Student(int code) :codeStud(code) {
}
Student(int code, int* grades, int noGrades) :codeStud(code) {
this->noGrades = noGrades;
this->grades = new int[noGrades];
for (int i = 0; i < noGrades; i++)
this->grades[i] = grades[i];
}
Student(const Student&existent):codeStud(existent.codeStud) {
this->noGrades = existent.noGrades;
this->grades = new int[this->noGrades];
for (int i = 0; i < this->noGrades; i++)
this->grades[i] = existent.grades[i];
}
int getCode() {
return this->codeStud;
}
int getNoGrades() {
return this->noGrades;
}
void setGrades(int grades[],int noGrades) {
this->noGrades = noGrades;
this->grades = new int[noGrades];
for (int i = 0; i < noGrades; i++)
this->grades[i] = grades[i];
}
};
void main() {
Student s1(101);
cout<<s1.getNoGrades();
int grades[] = { 10,7,8,10,4 };
Student s2(104, grades, 5);
cout << "\n" << s2.getNoGrades();
Student s3 = s2;
cout << "\n" << s3.getCode();
int grades2[] = { 5,5,4,10 };
s1.setGrades(grades2,4);
cout << "\n" << s1.getNoGrades(); // here is the problem
}
After I changed the grades for student 1 it shows that he has 0 grades, when the output should be 4, the number of these grades: 5,5,4,10.
The rest of output is correct, even when I want to know the number of grades for student 1, which is 0 , and then for student 2, which is 5.
I've changed some things in your code to compile it
#include<iostream>
#include<string>
using namespace std;
class Student {
public:
int codeStud;
int noGrades = 0;
int* grades = NULL;
Student(int code) {
codeStud = code;
}
Student(int code, int* grades, int noGrades) {
this->noGrades = noGrades;
this->grades = new int[noGrades];
for (int i = 0; i < noGrades; i++)
this->grades[i] = grades[i];
}
Student(const Student&existent){
this->noGrades = existent.noGrades;
this->grades = new int[this->noGrades];
for (int i = 0; i < this->noGrades; i++)
this->grades[i] = existent.grades[i];
}
int getCode() {
return this->codeStud;
}
int getNoGrades() {
return this->noGrades;
}
void setGrades(int grades[],int noGrades) {
this->noGrades = noGrades;
this->grades = new int[noGrades];
for (int i = 0; i < noGrades; i++)
this->grades[i] = grades[i];
}
};
int main() {
Student s1(101);
cout<<s1.getNoGrades();
int grades[] = { 10,7,8,10,4 };
Student s2(104, grades, 5);
cout << "\n" << s2.getNoGrades();
Student s3 = s2;
int grades2[] = { 5,5,4,10 };
s1.setGrades(grades2,4);
cout << "\n" << s1.getNoGrades(); // here is the problem
}
and output is:
0
5
4
what is correct, because you don't assign number of grades of s1 anywhere in your code before first printing
Also look for:
https://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c
why void main() is not correct
After I corrected the typo (codStud --> codeStud) your code produced the correct results for me. Before I did that I couldn't even compile it, so my guess would be that your IDE just run the latest working version of it that could be compiled successfully (look for error messages somewhere). That's the reason you got the wrong result, because your changes weren't even in that version.
A couple of note about your code:
In your setGrades function check that grades not pointing to something already. For example, if I call Student(int code, int* grades, int noGrades) and after I call setGrades your code leaks memory because it loses the array that Student(int code, int* grades, int noGrades) allocated before.
You should use vector instead of C-style arrays. It will make your code much more cleaner and less error-prone (see my example).
You could make your getter functions to const (like in my example), so it would be guaranteed that those functions don't change the value of any member of the class (you get a compile error if they do). Other than that, you can make the member variables to private.
Implementation using vectors:
#include <iostream> // cout
#include <vector> // vector
using namespace std;
class Student
{
public:
Student(const int code)
: m_code{code}
{
}
Student(const int code, const std::vector<int>& grades)
: m_code{code},
m_grades{grades}
{
}
// Default copy constructor is sufficient because the class can be copied
// memberwise.
int getCode() const {
return m_code;
}
int getNoGrades() const {
return m_grades.size();
}
void setGrades(const std::vector<int>& grades) {
m_grades = grades;
}
private:
const int m_code;
std::vector<int> m_grades;
};
int main()
{
Student s1(101);
cout << s1.getNoGrades();
Student s2(104, {10, 7, 8, 10, 4});
cout << "\n" << s2.getNoGrades();
Student s3 = s2;
cout << "\n" << s3.getCode();
s1.setGrades({5, 5, 4, 10});
cout << "\n" << s1.getNoGrades();
return 0;
}

how to reverse char array using class member pointer?

im tryin to reverse an array using pointer which is a class member:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
class my_string
{
char* ptr;
int size;
public:
my_string(){};
my_string(char* str) : ptr(str),size(strlen(ptr)){};
char* getstr () {return ptr;};
void reverse();
int find (char);
void print();
};
void my_string::reverse()
{
int size2=size;
for (int i=0;i<(size/2);i++)
{
char tmp=ptr[i];
ptr[i]=ptr[size2-1];
ptr[size2-1]=ptr[i];
size2--;
}
}
int my_string::find(char c)
{
for (int i=0;i<size;i++)
{
if (ptr[i]==c)
return i;
}
return -1;
}
void my_string::print()
{
for (int i=0;i<size;i++)
cout<<ptr[i];
cout<<endl;
}
int main()
{
my_string s1("abcde");
s1.print();
s1.reverse();
s1.print();
}
im not gettin any errors but the reverse function is surely not working.
can someone please explain to me why?
*this is an homework assignment asking me not to use dynamic allocation or strings (for now).
You didn't mention not being able to use standard library algorithms, so
std::reverse(ptr, ptr+size);
You can use standard algorithm std::reverse declared in header <algorithm>.
For example
std::reverse( ptr, ptr + size );
But if you want to do it yourself then the function could look the following way
void my_string::reverse()
{
for ( int i = 0; i < size/2; i++ )
{
char tmp = ptr[i];
ptr[i] = ptr[size-1-i];
ptr[size-1-i] = tmp;
}
}
A test program
#include <iostream>
#include <cstring>
int main()
{
char s[] = "123456789";
char *ptr = s;
int size = std::strlen( ptr );
std::cout << s << std::endl;
for ( int i = 0; i < size/2; i++ )
{
char tmp = ptr[i];
ptr[i] = ptr[size-1-i];
ptr[size-1-i] = tmp;
}
std::cout << s << std::endl;
}
Output is
123456789
987654321

Fail to store values to the list

It seems the attribute test aisbn is successfully storing the data invoking setCode(), setDigit(). But The trouble starts failing while I attempt these values to store into list<test> simul
The list attribute takes the value of digit after setDigit() but the code. How can I put both code and digit into the list attribute? I can't see where the problem is. The code:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <list>
using namespace std;
class test
{
private:
string code;
int digit;
public:
//constructor
test(): code(""), digit(0) { }
//copy constructor
test(const test &other):
digit(other.digit)
{
for(unsigned int i=0; i < code.length(); i++)
code[i] = other.code[i];
}
//set up the private values
void setCode(const string &temp, const int num);
void setCode(const string &temp);
void setDigit(const int &num);
//return the value of the pointer character
const string &getCode() const;
const unsigned int getDigit() const;
};
const string& test::getCode() const
{
return code;
}
const unsigned int test::getDigit() const
{
return digit;
}
void test::setCode(const string &temp, const int num)
{
if((int)code.size() <= num)
{
code.resize(num+1);
}
code[num] = temp[num];
}
void test::setCode(const string &temp)
{
code = temp;
}
void test::setDigit(const int &num)
{
digit = num;
}
int main()
{
const string contents = "dfskr-123";
test aisbn;
list<test> simul;
list<test>::iterator testitr;
testitr = simul.begin();
int count = 0;
cout << contents << '\n';
for(int i=0; i < (int)contents.length(); i++)
{
aisbn.setCode(contents);
aisbn.setDigit(count+1);
simul.push_back(aisbn);
count++;
}
cout << contents << '\n';
/*for(; testitr !=simul.end(); simul++)
{
cout << testitr->getCode() << "\n";
}*/
}
It looks like you are having issues with your for loop, you need to modify your for loop like so:
for(testitr = simul.begin(); testitr !=simul.end(); testitr++)
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^
although, push_back does not invalidate iterators for std::list I think it is more readable to set the iterator where you are using it. Based on your response you also need to modify the copy constructor:
test(const test &other): code(other.code), digit(other.digit) {}
^^^^^^^^^^^^^^^^
how about using the vector
std::vector<test> simul;
for(int i=0; i < (int)contents.length(); i++)
{
aisbn.setCode(contents);
aisbn.setDigit(count+1);
simul.push_back(aisbn);
count++;
}
iterators, pointers and references related to the container are invalidated.
Otherwise, only the last iterator is invalidated.