I'm trying to print a value found in the "getvalue" void in the "show" void. I get an error:
error: 'Students' was not declared in this scope
#include <iostream>
using namespace std;
int studentNumber=0;
int testNumber=0;
struct Student
{
string name,grade;
int studentNo,*testResults;
double average;
};
void getValue()
{
cout << "Enter the number of students: ";
cin >> studentNumber;
cout << "Enter the number of tests: ";
cin >> testNumber;
Student* Students = new Student[studentNumber];
for(int i=0; i< studentNumber; i++)
{
cout<< "\n" << "Enter the name of the " << i+1 << ". student: ";
cin >> Students[i].name;
cout<< "\n" << "Enter the number of the " << i+1 << ". student: ";
cin >> Students[i].studentNo;
Students[i].testResults = new int[testNumber];
for(int z=0; z<testNumber; z++)
{
cout<< "\n" << "Enter the " << z+1 << ". exam grade of the " << i+1 << ". student: " ;
cin >> Students[i].testResults[z];
}
}
}
void show()
{
for(int i=0; i < studentNumber; i++)
{
cout<< "\n" << Students[i].name;
cout<< "\n" << Students[i].studentNo;
for(int z=0; z<testNumber; z++)
{
cout<< "\n" <<Students[i].testResults[z];
}
}
}
int main()
{
getValue();
show();
}
I'm trying to show the obtained values in another void called "show" but failed. (The general structure of the code that must be in a different void must be another void named "show" in my homework)
You have to pass the value.
It can be done via reference:
// omit
void getValue(Student*& Students) // add reference argument
{
cout << "Enter the number of students: ";
cin >> studentNumber;
cout << "Enter the number of tests: ";
cin >> testNumber;
// don't declare here and use the arugment
Students = new Student[studentNumber];
// omit
}
void show(Student* Students) // add argument (need not be reference)
{
// omit
}
int main()
{
// add variable for arguments and use that
Student* s;
getValue(s);
show(s);
}
Or via global variable:
// omit
// declare variable here (as global)
static Student* Students;
void getValue()
{
cout << "Enter the number of students: ";
cin >> studentNumber;
cout << "Enter the number of tests: ";
cin >> testNumber;
// don't declare here and use the global variable
Students = new Student[studentNumber];
// omit
}
void show()
{
// omit
}
int main()
{
getValue();
show();
}
Instead of raw arrays, it might be good to use std::vector<Student>. It'd be easy to replace:
Student* Students = new Student[studentNumber];
with:
#include <vector>
...
std::vector<Student> Students(studentNumber);
(pretty much everything else should be the same) and then for the actual error you're seeing, since the Students array only exists inside the scope of the getValue() function, you'll need to return it so that show() can the array too. Consider changing the code to something like (assuming you're using the vector):
std::vector<Student> getValue() {
...
return Students;
}
void show(std::vector<Student> Students)
...
}
int main() {
auto Students = getValue();
show(Students);
}
Related
I am trying to make a basket system for a C++ program, and I am stuck with the task of obtaining the price from one vector in a separate class, and copying that price into the new "Basket" Vector. i have tried a number of workaround but I have gotten as far as having it return the error message that the identifier is undefined, even though the vector is public in the class.
the header file :
class Item {
private:
int _ItemNo;
string _category, _description;
double _price;
double _VAT = _price*0.2;
double _subtotal = _price + _VAT;
};
class ItemMenu {
public:
vector<Item> _Items;
ItemMenu();
void displayMenu();
};
//Class for ordering from the menu
class Ordering {
private:
vector<Item> _Basket;
int quantity;
double total;
public:
Ordering();
Ordering(int quantity, double total);
void placeOrder(const vector<Item> &Items);
The implementation file:
ItemMenu::ItemMenu() {
ifstream fin("Menu.txt");
if(fin) {
while(!fin.eof()) {
string _ItemNoTemp;
getline(fin, _ItemNoTemp, ':');
int _ItemNo = stoi(_ItemNoTemp);
string _category;
getline(fin, _category, ':');
string _description;
getline(fin, _description, ':');
string _priceTemp;
getline(fin, _priceTemp);
double _price = stod(_priceTemp);
if(!fin.eof()) {
_Items.push_back(Item(_ItemNo,
_category, _description, _price));
};
fin.peek();
}
fin.close();
}
}
//Method to display the each item
void ItemMenu::displayMenu() {
for(int i = 0; i < _Items.size(); ++i) {
_Items[i].display();
}
cout << endl;
}
Ordering::Ordering() { }
void Ordering::placeOrder() {
int select;
cout << "Please enter an item number: ";
cin >> select;
Item I;
i._subtotal = _Items[select]._subtotal;
_Basket.push_back(i);
}
It is in the ordering class that the basket vector is in, and I am trying to get the subtotal for the items, so that I may calculate the total by summing the values in the vector. This is also where the error saying that _Items is undefined appeared. I am new to programing and haven't really been able to find a clear source for how vectors work between classes depending on where they are declared.
Something like this should work
void Ordering::placeOrder(
const vector<Item>& items ) {
int select;
cout << "Please enter an item number: ";
cin >> select;
cItem i;
i._price = items[ select ]._price;
_Basket.push_back( i );
}
You don't actually pass an ItemMenu object to this function. That's why you are getting an undefined error.
Instead of this
void Ordering::placeOrder() {
int select;
cout << "Please enter an item number: ";
cin >> select;
_Basket.push_back(_Items[select]._subtotal);
}
You would want to do this
void Ordering::placeOrder(ItemMenu yourItemMenuVarible) {
int select;
cout << "Please enter an item number: ";
cin >> select;
_Basket.push_back(_Items[select]._subtotal);
}
then when you call it you would pass it the ItemMenu variable you defined and I think that should fix it.
I would also recommend you not have variables like the vector public, it not a very good practice for security reasons. Learning good habits now will help you in the future. The idea of keeping them private is called Encapsulation here are some sources on the topic
https://www.geeksforgeeks.org/encapsulation-in-c/
https://www.tutorialspoint.com/cplusplus/cpp_data_encapsulation.htm#:~:text=Encapsulation%20is%20an%20Object%20Oriented,from%20outside%20interference%20and%20misuse.&text=This%20means%20that%20they%20can,other%20part%20of%20your%20program.
Thanks for all the help guys i ended up fixing it with your help the code is below.
Header File:
class Ordering {
private:
vector<Item> _Basket;
int quantity;
double total;
public:
Ordering();
Ordering(int quantity, double total);
void placeOrder(vector<Item> Items);
};
Implementation:
Ordering::Ordering() { }
void Ordering::placeOrder(vector<Item> _Items) {
int select;
Item i;
char cont;
do{
cout << "Please enter an item number: ";
cin >> select;
i._ItemNo = _Items[select-1]._ItemNo;
i._description = _Items[select-1]._description;
i._subtotal = _Items[select-1]._subtotal;
_Basket.push_back(i);
cout << i._subtotal;
cout << "Do you want to add another Item? (y/n): ";
cin >> cont;
}while(cont == 'y' || cont == 'Y');
for (int i; i < _Basket.size(); i++) {
cout << _Basket[i]._ItemNo << ':' << _Basket[i]._description
<< ':' << char(156) << _Basket[i]._subtotal << endl;
};
}
Main:
int main() {
cout << "--------------------------------" << endl;
cout << "Billing Program" << endl <<
"--------------------------------" << endl;
Ordering start;
ItemMenu display;
display.displayMenu();
start.placeOrder(display._Items);
}
This program has the user input name/age pairs and then outputs them, using a class.
Here is the code.
#include "std_lib_facilities.h"
class Name_pairs
{
public:
bool test();
void read_names();
void read_ages();
void print();
private:
vector<string>names;
vector<double>ages;
string name;
double age;
};
void Name_pairs::read_names()
{
cout << "Enter name: ";
cin >> name;
names.push_back(name);
cout << endl;
}
void Name_pairs::read_ages()
{
cout << "Enter corresponding age: ";
cin >> age;
ages.push_back(age);
cout << endl;
}
void Name_pairs::print()
{
for(int i = 0; i < names.size() && i < ages.size(); ++i)
cout << names[i] << " , " << ages[i] << endl;
}
bool Name_pairs::test()
{
int i = 0;
if(ages[i] == 0 || names[i] == "0") return false;
else{
++i;
return true;}
}
int main()
{
cout << "Enter names and ages. Use 0 to cancel.\n";
while(Name_pairs::test())
{
Name_pairs::read_names();
Name_pairs::read_ages();
}
Name_pairs::print();
keep_window_open();
}
However, in int main() when I'm trying to call the functions I get "cannot call 'whatever name is' function without object." I'm guessing this is because it's looking for something like variable.test or variable.read_names. How should I go about fixing this?
You need to instantiate an object in order to call its member functions. The member functions need an object to operate on; they can't just be used on their own. The main() function could, for example, look like this:
int main()
{
Name_pairs np;
cout << "Enter names and ages. Use 0 to cancel.\n";
while(np.test())
{
np.read_names();
np.read_ages();
}
np.print();
keep_window_open();
}
If you want to call them like that, you should declare them static.
just add static keyword at the starting of the function return type..
and then you can access the member function of the class without object:)
for ex:
static void Name_pairs::read_names()
{
cout << "Enter name: ";
cin >> name;
names.push_back(name);
cout << endl;
}
You are right - you declared a new use defined type (Name_pairs) and you need variable of that type to use it.
The code should go like this:
Name_pairs np;
np.read_names()
I am trying to do some stuff with C++ and i am new in it :)
I have tried 1 program of class that gets the student details and print the output of it.
#include <iostream>
using namespace std;
#define MAX 10
class student
{
private:
char name[30];
int rollNo;
int total;
float perc;
public:
//member function to get student's details
void getDetails(void);
//member function to print student's details
void putDetails(void);
};
//member function definition, outside of the class
void student::getDetails(void){
cout << "Enter name: " ;
cin >> name;
cout << "Enter roll number: ";
cin >> rollNo;
cout << "Enter total marks outof 500: ";
cin >> total;
perc=(float)total/500*100;
}
//member function definition, outside of the class
void student::putDetails(void) {
cout << "Student details:\n";
cout << "Name:"<< name << ",Roll Number:" << rollNo << ",Total:" << total << ",Percentage:" << perc;
}
int main()
{
student std[MAX]; //array of objects creation
int n,loop;
cout << "Enter total number of students: ";
cin >> n;
for(loop=0;loop< n; loop++){
cout << "Enter details of student " << loop+1 << ":\n";
std[loop].getDetails();
}
cout << endl;
for(loop=0;loop< n; loop++) {
cout << "Details of student " << (loop+1) << ":\n";
std[loop].putDetails();
}
return 0;
}
Its very basic code and works fine and I am able to give inputs and print the output.
Now I want to add new Student object at runtime using Dynamic memory allocation and want to add that object in the existing array of object (So that I can get the highest, lowest marks of any student)
I know I need to use new operator for this.
But I am not sure what could be the best way to write this solution.
Any help will be highly appreciated.
Thanks!
IMO, The best way to do this using dynamic memory is by using std::unique_ptr or std::shared_ptr (it actually depends on the requirement).
Here is one example of usage of unique_ptr:
using StudentPtr = std::unique_ptr<student>;
int main() {
std::vector<StudentPtr> studentDetails;
int n;
cout << "Enter the number of students: ";
cin >> n;
studentDetails.resize(n);
for (auto &s: studentDetails) {
s = StudentPtr(new student);
s->getDetails();
}
return 0;
}
For getting minimum and maximum, you may use min_element and max_element provided by STL respectively.
Recently in my c++ class we have learned about pointers and classes.
I'm trying to make a program that has a class Student, which we will point to give each student a name and test score.
After entering both name and test score, they are sorted and then listed in order of highest to lowest.
I believe all my syntax to be correct, however I am still learning. The problem I am having is that the first time I use my class I get an uninitialized local variable error, any help on how to fix this?
#include "stdafx.h"
#include <iostream>
#include <string>
#include <array>
using namespace std;
class Student {
private:
double score;
string name;
public:
void setScore(double a) {
score = a;
}
double getScore() {
return score;
}
void setName(string b) {
name = b;
}
string getName() {
return name;
}
};
void sorting(Student*, int);
int main()
{
Student *students;
string name;
int score;
int *count;
count = new int;
cout << "How many students? ";
cin >> *count;
while (*count <= 0) {
cout << "ERROR: The number of students must be greater than 0.\n";
cin >> *count;
}
for (int i = 0; i < *count; i++) {
cout << "Please enter the students name: ";
cin >> name;
students[i].setName(name);
cout << "Please enter " << students[i].getName() << "'s score: ";
cin >> score;
while (score < 0) {
cout << "ERROR: Score must be a positive number.\n";
cin >> score;
}
students[i].setScore(score);
}
sorting(students, *count);
for (int i = 0; i < *count; i++) {
cout << students[i].getName() << ": " << students[i].getScore() << endl;
}
system("PAUSE");
return 0;
}
void sorting(Student *s, int size) {
for (int i = 0; i < size; i++) {
for (int j = i; j < size; j++) {
if (s[j].getScore() > s[(j + 1)].getScore()) {
int tmp = s[(j + 1)].getScore();
s[(j + 1)].setScore(s[j].getScore());
s[j].setScore(tmp);
string tmp1 = s[(j + 1)].getName();
s[(j + 1)].setName(s[j].getName());
s[j].setName(tmp1);
}
}
}
}
First off, your Student class can be simplified to this:
struct Student {
double score;
std::string name;
};
Because the accessors do absolutely nothing. I've also added the std:: prefix because using namespace std is considered a bad practice.
Now, instead of using the pointer to store the students, include vector and use that:
std::cout << "How many students? ";
int count;
std::cin >> count;
std::vector<Student> students(count);
The loading routine can also be simplified given the absence of accesors:
for (auto& student : students) {
std::cout << "Please enter the students name: ";
std::cin >> student.name;
std::cout << "Please enter " << student.name << "'s score: ";
std::cin >> student.score;
while (score < 0) {
std::cout << "ERROR: Score must be a positive number.\n";
std::cin >> student.score;
}
}
And actually once you have that, you could just put it in istream& operator>>(istream&, Student&) and reduce it to:
std::copy_n(std::istream_iterator<Student>(std::cin), students.size(), students.begin());
No need now for temporary variables anymore (and even if you want to use them, they should be defined just before the use, so inside of the loop).
The last thing is your sorting routine. First off, there's std::sort that you can use instead if you simply provide a comparator:
std::sort(
begin(students),
end(students),
[](Student const& a, Student const& b) { return b.score < a.score; }
);
If you insist on writing the sorting routine yourself, at least use std::swap.
so I am beginner to C++ and I am trying to make a Class that contains functions for getting Data, calculating average sum and dividing them by how much grades there are(5) and the final function is for displaying the data about the student.Here's what I get in the console : Click for image
I would be happy to get some advice from you guys.
Here is the code :
class Students{
int br;
char Name[30];
int fakn,i;
float grades[5],sum;
char spec[25];
public:
void takingdata();
float avarage();
void displaydata();
};
void Students::takingdata(){
cout << "Enter name of the student: "; cin.getline(Name, 20);
cout << "Enter his faculty number: "; cin >> fakn;
cout << "specialty: "; cin.getline(spec, 10);
cout << "Enter grades : ";
for (i = 0; i < 5; i++){
cout << "Enter his grades(5 classes): "; cin >> grades[i];
}
}
float Students::avarage(){
sum = 0;
br = 0;
for (i = 0; i < 5; i++){
sum = sum + grades[i];
}
return sum / 5;
}
void Students::displaydata(){
cout << "Name of student: " << Name;
cout << "Student faculty number: " << fakn;
cout << "Student specialty: " << spec;
for (i = 0; i < 5; i++){
cout << "His " << i << " grade: " << grades[i];
}
cout << "His avarage grade: " << avarage();
}
void main(){
Students in,out;
in.takingdata();
out.displaydata();
_getch();
}
As a result I want the program to display the entered information about the student.
First of all:
Students in,out;
in.takingdata();
out.displaydata();
How is this supposed to work? You have two objects here, writing into the first and reading from the second.
It should be something like:
Students students;
students.takingdata();
students.displaydata();
Still, it's important to understand what really happens in your version of the code. As we have just established, everything you read from std::cin into in is discarded later on. Which bears the question of what exactly you read from out. Let's look at the relevant portion of your class definition again:
int br;
char Name[30];
int fakn,i;
float grades[5],sum;
char spec[25];
All of these member variables are of so-called primitive type. This means, among other things, that if you don't initialize them explictly, they will be left uninitialized. For example, br does not "start at 0". It is, strictly speaking, nothing until you assign it something.
Any attempt to output these uninitialized values yields undefined behaviour. Undefined behaviour means that the C++ language specification "gives up" and does not say what the resulting program should do.
What often happens in practice in a situation like yours here is that your program reads a more or less random value that happened to be at the location in memory represented by the variable, and prints that one. The dangerous thing about this is that it may seem to work correctly for a long while because the memory location just happens to contain a zero value, luring you into thinking that your program is bug-free, and then it suddenly crashes or prints garbage values.
So the obvious first fix we should apply to your code is making sure that all the member variables are initialized. While we do that, I'll also:
Add #include <iostream> on top.
Add std:: in front of all standard-library features (that's good practice).
Change the illegal void main to int main.
Remove the unnecessary _getch call.
Here's the result afer the first iteration of fixes:
#include <iostream>
class Students{
int br;
char Name[30];
int fakn,i;
float grades[5],sum;
char spec[25];
public:
Students() :
br(0),
Name(),
fakn(0),
i(0),
grades(),
sum(0.0),
spec()
{}
void takingdata();
float avarage();
void displaydata();
};
void Students::takingdata(){
std::cout << "Enter name of the student: "; std::cin.getline(Name, 20);
std::cout << "Enter his faculty number: "; std::cin >> fakn;
std::cout << "specialty: "; std::cin.getline(spec, 10);
std::cout << "Enter grades : ";
for (i = 0; i < 5; i++){
std::cout << "Enter his grades(5 classes): "; std::cin >> grades[i];
}
}
float Students::avarage(){
sum = 0;
br = 0;
for (i = 0; i < 5; i++){
sum = sum + grades[i];
}
return sum / 5;
}
void Students::displaydata(){
std::cout << "Name of student: " << Name;
std::cout << "Student faculty number: " << fakn;
std::cout << "Student specialty: " << spec;
for (i = 0; i < 5; i++){
std::cout << "His " << i << " grade: " << grades[i];
}
std::cout << "His avarage grade: " << avarage();
}
int main(){
Students students;
students.takingdata();
students.displaydata();
}
Note: If you use Visual C++, you should read the following about array-member initialization:
https://msdn.microsoft.com/en-us/library/1ywe7hcy.aspx
But that's not yet very satisfactory. Why should a student's name not be longer than 29 characters (your array consists of a maximum of 29 visible characters plus a terminating '\0' for C-style strings)? And why should it take 30 characters in memory when it turns out to be much shorter?
In fact, what happens if you enter more than 29 characters? Let's give it a try:
Enter name of the student: Long name that does not fit any more in 30 characters
Enter his faculty number: specialty: Enter grades : Enter his grades(5 classes): Enter his grades(5 classes): Enter his grades(5 classes): Enter his grades(5 cl
asses): Enter his grades(5 classes): Name of student: Long name that doesStudent faculty number: 0Student specialty: His 0 grade: 0His 1 grade: 0His 2 grade: 0H
is 3 grade: 0His 4 grade: 0His avarage grade: 0
That's not good. std::istream::getline attempts to write more than 30 characters into a 30-element array. This already yields undefined behaviour. Even if it magically stopped after 30 elements, you'd end up with an array without the terminating '\0', so later outputting code would again leave the array's bounds looking for it. In addition to that, all attempts at reading numbers via std::cin fail because the stream contents after the 30th character cannot be interpreted as numbers, leaving the variables it's supposed to write into in their previous state.
As you can see, reading into a fixed-size char array the way you did is an almost hopeless undertaking. Fortunately, C++ does not force you to keep up with all of that. It offers std::string for dynamically sized strings, and a free-standing std::getline function to read safely into them.
Here's the second iteration of fixes. Note that std::string is not a primitive type, so it knows how to correctly initialize itself. I still added the two variables to the initializer list to be consistent with the other members.
#include <iostream>
#include <string>
class Students{
int br;
std::string Name;
int fakn,i;
float grades[5],sum;
std::string spec;
public:
Students() :
br(0),
Name(),
fakn(0),
i(0),
grades(),
sum(0.0),
spec()
{}
void takingdata();
float avarage();
void displaydata();
};
void Students::takingdata(){
std::cout << "Enter name of the student: "; std::getline(std::cin, Name);
std::cout << "Enter his faculty number: "; std::cin >> fakn;
std::cout << "specialty: "; std::getline(std::cin, spec);
std::cout << "Enter grades : ";
for (i = 0; i < 5; i++){
std::cout << "Enter his grades(5 classes): "; std::cin >> grades[i];
}
}
float Students::avarage(){
sum = 0;
br = 0;
for (i = 0; i < 5; i++){
sum = sum + grades[i];
}
return sum / 5;
}
void Students::displaydata(){
std::cout << "Name of student: " << Name;
std::cout << "Student faculty number: " << fakn;
std::cout << "Student specialty: " << spec;
for (i = 0; i < 5; i++){
std::cout << "His " << i << " grade: " << grades[i];
}
std::cout << "His avarage grade: " << avarage();
}
int main(){
Students students;
students.takingdata();
students.displaydata();
}
The program could take a lot more fixes. For example, you will want to replace the float array with std::vector<float>, and also generally use double instead of float.
In short: You should just use more C++ and less C if you want to program in C++.
#include <iostream>
#include <cstdio>
using namespace std;
class Students {
private:
static const int CLASSES = 5;
static const int NAME = 30;
static const int SPEC = 15;
char name[NAME], spec[SPEC];
int fakn;
float grades[CLASSES],sum;
public:
Students();
void takingdata();
void avarage();
void displaydata();
};
//constructor
Students::Students(){
takingdata();
avarage();
displaydata();
}
//user innput
void Students::takingdata(){
cout << "Enter name of the student: ";
cin.getline(name, NAME);
cout << "Enter his faculty number: ";
cin >> fakn;
cin.ignore();
cout << "specialty: ";
cin.getline(spec, SPEC);
printf("\nEnter Grades (%u classes)\n", CLASSES);
for (int i = 0; i < CLASSES; i++){
printf("Grade 0%u: ", i+1);
cin >> grades[i];
}
}
//calculations
void Students::avarage(){
sum = 0;
for (int i = 0; i < CLASSES; i++){
sum = sum + grades[i];
}
sum /= CLASSES;
}
//display
void Students::displaydata(){
printf("\n\nStudent Name: %s\nFaculty Number: %u\nSpecialty: %s\nGrade Average: %f", name, fakn, spec, sum);
for (int i = 0; i < CLASSES; i++){
printf("\nGrade 0%u: %f", i+1, grades[i]);
}
}
//main
int main(){
//all other functions now called in constructor
Students in;
return 0;
}