C++ pass empty vector of structs to a function - c++

I am trying to pass an empty vector of structures to a function which will read from a file and it will return the number of records read -- it will be an integer.
I initialize the vector of structures in main and when I attempt to pass it to the function as I would regularly do it:
int read_records(vector<player> player_info)
It gives me a "player is undefined" error. I have found a way to go around it as you will see in my code below but logic leads me to believe that there should be a way to pass the empty vector without having to fill in the first subscript.
The code is below. Please note that the read function is not yet complete as I am still wondering about the vector of structs.
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <fstream>
using namespace std;
//function prototypes
int read_records(struct player* player_info);
/*
* Define a struct called player that will consist
* of the variables that are needed to read in each
* record for the players. 2 strings for the first
* and last names and 1 integer to hold the statistics
*/
struct player
{
string first;
string last;
int stats;
};
int main(void)
{
int sort_by, records_read;
vector<player> player_info(1);
player * point = &player_info[0];
cout << "Welcome to Baseball player statistics program!" << endl;
cout << "How should the information be sorted?" << endl;
cout << "Enter 1 for First Name" << endl;
cout << "Enter 2 for Last Name" << endl;
cout << "Enter 3 for Points" << endl;
cout << "Enter your selection: ";
cin >> sort_by;
//read the records into the array
records_read = read_records(point);
system("Pause");
return 0;
}
int read_records(struct player* player_info)
{
//declare the inputstream
ifstream inputfile;
//open the file
inputfile.open("points.txt");
//handle problem if the file fails to open for reading
if (inputfile.fail())
{
cout << "The player file has failed to open!" << endl;
exit(EXIT_FAILURE);
}
else
{
cout << "The player file has been read successfully!" << endl;
}
return 5;
}

Define the type player before you attempt to declare functions that need to know about that type.
struct player
{
string first;
string last;
int stats;
};
int read_records(vector<player> player_info);
Your workaround was successful because naming player in struct player* acts as a [forward] declaration, in a way that naming it in vector<player> does not. (The whys and wherefores of this are too broad for this answer and are covered elsewhere on SO and in your C++ book.)
As an aside, I doubt you want to take that vector by value.

Why don't you put struct player definition before int read_records(vector<player> player_info).

Related

C++ executes blanks after class creation

I'm trying to learn C++ to help my sibling with their assignment. So I'm attempting the assignment. It's a simple program to load a dictionary test file with words, their type, and definition to an array of Word type objects. I was able to get started with a normal string array instead of an object array as requested. But as soon as I defined the Word class and the array the code builds without an issue. When I try to run the code the cursor simply blinks for a few seconds and returns to the normal terminal.
Am I doing something wrong with my Class constructor ??
#include <fstream>
#include <string>
using namespace std;
class Word {
public:
string WordEntry;
string Type;
string Definition;
//constructor
Word(string word, string type, string definition){
WordEntry=word;
Type=type;
Definition=definition;
}
};
int main(){
cout << "Test1";
Word *wordArray[318555];
int count=0;
string word, type, definition,blank;
cout << "TEST" << count << "\n";
ifstream file("dictionary2021 (1).txt");
if (file.is_open()){
cout << "File dictionary2021.txt has been opened \n";
while (!file.eof()){
getline(file,word);
getline(file,type);
getline(file,definition);
getline(file,blank);
wordArray[count]= new Word(word,type,definition);
count++;
}
file.close();
cout << "File dictionary2021.txt has " << count/3 << " entries\n";
}
cout << "TEST" << count << endl;
cout << cc;
int selection;
string input;
cout << "Function List - Please hit Enter after your selection \n";
cout << " 1. Word Search \n 2. Repetitive z search \n 3. Wild Card Search\n";
cout << "Selection:";
cin >> selection;
if(selection=1){
cout << "Enter word:\n";
cin >> input;
string str("a");
for (int i = 0; i < 12; i+3)
{
cout << "1";
if (input.compare(str)== 0)
{
cout << wordArray[i+1];
return 0;
}
cout << "2";
}
}
}```
Word* wordArray[318555]; is a huge value and we're talking about 2548440 bytes (or roughly 2.4MB). This might be too large for a single stack frame and can easily be inefficient.
What I suggest is to use std::vector to store the word array and use std::vector<>::push_back() method to insert data to it.
Note: In your code snippet your not deallocating the Word object pointers once everything is done. Either explicitly delete those pointers using delete or use a smart pointer like std::unique_ptr.

C++: Program crashes when I try to access a private class string variable. Why is this, and what can I do to fix it?

I am writing a bank account program that provides a menu system for the user, which allows them to choose between 4 options: A) Add a customer, B) Print all customer data, C) Update customer data, and D) Exit program. Each option performs separate tasks. The option I am focused on for this question is Option A.
Option A is supposed to generate a new bank account object and ask the user to input the account holder name, the initial deposit for the account (how much money to start with for the new account), and the interest rate. It then needs to set these values to the correct private values in the bankAccount class for any given object.
Code for main.cpp before Option B (there is a little more code after this, hence the lack of backward brackets at the end, but I want to try and keep this more concise):
#include <iostream>
#include <string>
#include <cstdlib>
#include "header.h"
#include "implementation.cpp"
using namespace std;
int main()
{
//array of bankAccount class objects (up to 20)
bankAccount account[20];
string menuInput = ""; //used for menu loop input
string accNameInput = ""; //used for account customer name user input
float depositInput = 0; //used for initial deposit input
float interestInput = 0; //used for initial interest input
// int customerCount = 0; //used to compare to static int to determine # of customers in memory
int static i = 0;
//while loop keeps user in the menu until they choose to exit program
while (true)
{
cout << endl << "Enter a letter option below: "
<< endl << endl << "A: Add a customer" << endl << "B: Print all customer data available"
<< endl << "C: Update customer data" << endl << "D: End program" << endl << endl;
cin >> menuInput;
//Option A: Add a customer
if (menuInput == "A" || menuInput == "a")
{
//checking for max customer limit
if (i > 19)
{
cout << endl << "Cannot add customer; Max customer capacity reached." << endl;
}
else //
{
///Creates a new customer account and asks for new customer name,
///initial deposit amount, & interest
cout << endl << "Bank account #" << (i + 1) << " created." << endl;
bankAccount account[i]; //new bank account object created
//time to set the name for our new customer...
cout << endl << "Enter customer name for account #" << (i + 1) << ": " << endl;
cin >> accNameInput;
//setting initial deposit amount
cout << endl << "Enter initial deposit amount for account #" << (i + 1) << ": " << endl;
cin >> depositInput;
//setting initial interest rate
cout << endl << "Enter interest rate (without % sign): " << endl;
cin >> interestInput;
account[i].setInterestRate(interestInput);
account[i].setBalance(depositInput);
account[i].setAccountHolderName(accNameInput);
//increments the account number counter
i++;
}
}
The problem persists with setAccountHolderName() found on the last line here:
account[i].setInterestRate(interestInput);
account[i].setBalance(depositInput);
account[i].setAccountHolderName(accNameInput);
When I call the class functions setInterestRate and setBalance to set the input values to their respective private class variables, the program proceeds like normal and takes the user back to the main menu as it should. But calling setAccountHolderName crashes the program and returns this value: -1073741819 (0xC0000005).
I'll include some code from the header and implementation files below to show how I have accountHolderName code programmed in:
header.h (includes accountHolderName get/set functions):
///Name of file: header.h
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
#include <iostream>
#include <string>
using namespace std;
class bankAccount
{
//private data values
string accountHolderName;
int accountNumber;
//static int accCounter; //keeps track of account numbers
float balance;
float interestRate;
public:
//Default constructor
bankAccount();
///Getters/setters for all private member variables
//accountNumber
int getAccountNumber();
void setAccountNumber(int accNum);
//accountHolderName
string getAccountHolderName();
void setAccountHolderName(string accName);
implementation.cpp (includes accountHolderName implementation):
///Name of file: implementation.cpp
#include <iostream>
#include <string>
#include "header.h"
using namespace std;
//static int definition (guess you have to define static members here?)
//int bankAccount::accCounter;
//Default constructor
bankAccount::bankAccount()
{
accountHolderName = "";
accountNumber = 0;
// accCounter = 0;
balance = 0;
interestRate = 0;
}
///Getters/setters for all private member variables
//accountNumber
int bankAccount::getAccountNumber()
{
return accountNumber;
}
void bankAccount::setAccountNumber(int accNum)
{
accountNumber = accNum;
}
//accountHolderName
string bankAccount::getAccountHolderName()
{
return accountHolderName;
}
void bankAccount::setAccountHolderName(string accName)
{
accountHolderName = accName;
}
It seems like messing with the code in certain ways (such as completely deleting the code that comes after Option A's code, commenting out accountHolderName = ""; in the default constructor, etc.) will temporarily allow account[i].setAccountHolderName(accNameInput); to function without crashing the program, but this is incredibly inconsistent and confuses me even more. I'm not sure if the issue has to do with memory or what. I have also tried using cout to see if the input variable accNameInput from main.cpp is getting stored to, which it is.
Sorry if this is simply too much code or explaining; this is my first post and I just wanted to provide a good chunk of my code so you could see the full scale of things. All I am trying to do here is access the bankAccount class private string variable, accountHolderName, and store user input into each new object.
I tried troubleshooting this issue online but couldn't seem to find anything that had a similar issue. I'm not sure what I'm missing; any help or guidance would be incredibly appreciated.
Technically, this line:
bankAccount account[i]; //new bank account object created
Isn't allowed in C++, but some compilers (g++) allow it as an extension since they do formally support variable stack arrays with the C compiler.
Further, that declaration overrides the variable of the same name declared at a higher scope
But then you get to these lines:
account[i].setInterestRate(interestInput);
account[i].setBalance(depositInput);
account[i].setAccountHolderName(accNameInput);
But valid indices of an array range for 0..i-1 So you're already in undefined behavior with your array index out of bounds.
I suspect you really meant this:
bankAccount newAccount; //new bank account object created
...
newAccount.setInterestRate(interestInput);
newAccount.setBalance(depositInput);
newAccount.setAccountHolderName(accNameInput);
account[i] = newAccount;
i++;

Passing array off as reference in c++ without using pointer

I have a quick question regarding an assignment I have to complete for C++. The teacher has required that I include the functions below:
void getPlayerInfo(Player &);
void showInfo(Player);
int getTotalPoints(Player [], int);
But I'm having trouble working on the first function....I'm not sure if I'm calling the array of structures properly. Can someone look it over and see what I'm doing wrong? I fiddled with it a bit and I'm able to call the array and pass off a pointer to the array but the teacher requested the "&" symbol be there so there must be another method I'm unaware of. Please help! Thanks
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
// Structure to hold information about a player
struct Player
{
string name; // to hold the players name
int number; // to hold players number
int points; // to hold the points scored by the player
};
// Function prototypes
void getPlayerInfo(Player &); // function to get the players information from the user
void showInfo(Player); // function to show the table
int main()
{
const int numPlayers = 12; // Constant to hold the number of players
Player team[numPlayers]; // array to hold 12 structures
// Gather information about all 12 players
getPlayerInfo(team);
showInfo(team);
return 0;
}
// Function to get the players info
void getPlayerInfo(Player& team)
{
for (int count = 0; count < 12; count++)
{
cout << "PLAYER #" << (count + 1) << endl;
cout << "----------" << endl;
cout << "Player name: ";
cin.ignore();
getline(cin, team[count].name);
cout << "Player's number: ";
cin >> team[count].number;
cout << "Points scored: ";
cin >> team[count].points;
cout << endl;
}
}
getPlayerInfo() does not accept an array, it accepts a reference to a single Player object.
You need to call getPlayerInfo() for each player in your array. Move your loop outside of getPlayerInfo() and into main().
You've misunderstood the intent of these functions.
Guessing from the information you've provided, getPlayerInfo is intended to get the information of an individual player, and showPlayerInfo is intended to show the information of an individual player.
You're trying to use these functions to do something they aren't intended to do, so it's a good thing that you are having trouble figuring out how to call and how to implement them.
Consider this experience as a object lesson in requirement gathering.

WxWidgets and STL Vector

So, I am new to programing and I have this problem.
I have written a console app in which I can add objects to STL vector.
Some code:
Element.h (Objects of this class I store in Vector)
class Element
{
private:
string speaker_name;
string color_membrane;
string color_main;
string size_main;
string color_terminals;
string size_terminals;
public:
Element();
~Element();
string Get_color_membrane();
string Get_color_main();
string Get_size_main();
string Get_color_terminals();
string Get_size_terminals();
string Get_speaker_name();
void Set_color_membrane(string);
void Set_color_main(string);
void Set_size_main(string);
void Set_color_terminals(string);
void Set_size_terminals(string);
void Set_speaker_name(string);
Doc.cpp (class with vector)
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include "Doc.h"
using namespace std;
vector <Element> MyElements;
void Doc::Add_item(Element const& TempElement)
{
MyElements.push_back(TempElement);
}
App.cpp
Doc doc;
Element TempElement;
cout << "Add new Element" << endl;
cout << "Input NAME of speaker" << endl;
cin >> temp_string;
TempElement.Set_speaker_name(temp_string);
cout << "Input COLOR of membrane" << endl;
cin >> temp_string;
TempElement.Set_color_membrane(temp_string);
cout << "Input COLOR of main body of speaker " << endl;
cin >> temp_string;
TempElement.Set_color_main(temp_string);
cout << "Input stroke SIZE of membrane & main body" << endl;
cin >> temp_string;
TempElement.Set_size_main(temp_string);
cout << "Input COLOR of terminals" << endl;
cin >> temp_string;
TempElement.Set_color_terminals(temp_string);
cout << "Input stroke SIZE of terminals" << endl;
cin >> temp_string;
TempElement.Set_size_terminals(temp_string);
doc.Add_item(TempElement);
The thing is: I am writing a window-based app in WxWidgets.
My project looks like this:
(It's just for testing purposes - it does nothing)
And, now I would like to create a method of making some sort of list of this objects from STL vector (where red arrow points),
It should look more or less like this:
and be able to communicate with STL vector
Thanks in advance for all your help.
~Thermoos
The simplest control you can use to display your items is wxListBox. There is also wxEditableListBox which comes with the built-in buttons, but it doesn't look quite the same, check the editlbox sample showing it in action.

Wondering about scope in C++ with structures and functions

I'm writing a program that allows me to put my name in and pull up different semesters and for me to put grades in and then be able to calculate my class average and GPA, just for my own reference in my courses.
What I am having a problem with is with structures and how they work with a multifunction program. In my courses we have not covered this and I have spent a while now searching for answers and cannot find one. Below is my current code:
using namespace std;
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char gettingName();
class Student{
public:
double semesterClass[20][20]; //first is for semester, second is for which class
char name[20];
int semester;
int numOfCourses;
};
int main(int argc, char **argv)
{
Student info;
gettingName();
cout << "Hi my name is: " << name.info << endl;
return 0;
}
char gettingName()
{
Student info;
char YesNo[5];
char boolean[1] = {'T'};
char yes[3] = {'Y','e','s'};
char yes2[3] = {'Y','E','S'};
char yes3[3] = {'y','e','s'};
char yes4[1] = {'Y'};
char yes5[1] = {'y'};
while(boolean[0] == 'T'){
cout << "What is your name? ";
cin >> info.name;
cout << endl;
cout << "Is your name " << info.name << "?"<<endl; //accepted input will be Y,y,YES,Yes,yes
cin >> YesNo;
//if input does not equal any of the accepted inputs, then loop until it does
if((strcmp(YesNo,yes) == 0) || (strcmp(YesNo,yes2) == 0) || (strcmp(YesNo,yes3) == 0) || (YesNo[0] == yes4[0]) || (YesNo[0] == yes5[0])){
boolean[0] = 'F';
}
}
return 0;
}
My question: how might I go about fixing the scope so that I can call the 'gettingName' function, get the person to input their name, (get it right (that already works)) and then be able to access and print it in the main function?
There are a lot of issues with your code, but I will try to help out the best I can. In general C++ scope for local variables is at the block level. So any time you see a ending bracket }, the scope has ended.
Some specific issues with your code that I noticed:
This line should be: "cout << "Hi my name is: " << info.name <<
endl;", not name.info
The boolean loop can be handled much more efficiently. You should try to list all of the acceptable options in one data structure like an array and then loop through the array.
Lastly when creating a function that doesn't need to return anything,
you can use the type void instead of char. So it could be void gettingName(), instead of char gettingName().
As an example to show you a quick and easy way to do what I think you wanted, I simplified your code a bit. I also decided to use std::string rather than char arrays as they are easier to work with:
class Student{
public:
std::string name;
};
std::string gettingName();
int main()
{
Student Info;
Info.name = gettingName();
cout << "Hi my name is: " << Info.name << endl;
return 0;
}
std::string gettingName()
{
std::string name;
cout << "What is your name? ";
cin >> name;
cout << endl;
return name;
}
Your code not really is object oriented. To fix the scope, you'll have to put gettingName inside your class to make it a member function (which is btw the term to Google for). You will also have to change the implementation which then needs to include the class name for identification:
char Student::gettingName()
{
...
}
From main you'd call it then via
info.gettingName();