Template for handling different type of input - c++

I was looking at this SO post on writing template for reading any type of user input.
I wrote template below. But problem starts when string input is given in place of character or floating point number is given in place of integer. When floating number is given as input to the integer, only data before the decimal point gets assigned to the variable. For example: When we assign 6.7 to integer, 6 gets assigned, but .7 is left in input buffer and . gets automatically assigned to next character without waiting for user input. How do we handle this? I cannot call std::cin.clear() unless there is something in input buffer to clear. Calling std::cin.clear() when correct data is entered causes indefinite wait for some character.
#include <iostream>
#include <limits>
using namespace std;
template <typename myType>
void getInput(myType &data, const string& promptMessage)
{
std::cout<<promptMessage;
std::cin>>data;
while(std::cin.fail())
{
std::cin.clear();
cin.ignore(std::numeric_limits<int>::max(),'\n');
cout<<"Entered Invalid data, Re-Enter: \n";
std::cin>>data;
}
}
void getInput(string &data, const string& promptMessage)
{
std::cout<<promptMessage;
getline(std::cin,data);
}
int main(void)
{
int myInt;
//cout<<"Enter an Integer : ";
getInput(myInt, "Enter the Integer Data: ");
cout<<"Integer Value read = "<<myInt<<endl;
char myChar;
getInput(myChar, "Enter single Character: ");
cout<<"Character read = "<<myChar<<endl;
return(0);
}
Edit2:
After looking at replies, updated the template function below. Able to handle floating point or integer. But I am not able to handle characters and strings in the sample template function. I can definitely go for overloaded function, but I guess that defeats the purpose.
#include <iostream>
#include <limits>
#include <type_traits>
#include <stdlib.h>
#include <string>
template <typename myType>
void getInput(myType &data, const string& promptMessage)
{
string str;
char *ret;
uint8_t status=0;
std::cout<<promptMessage;
while(!status)
{
do
{
std::getline(std::cin,str);
}
while(str.empty());
if(std::is_integral <myType>::value)
{
data = strtoll(str.c_str(),&ret,10);
if(*ret=='\0')
{
status=1;
}
else
{
std::cout<<"Invalid data, Please re-enter"<<endl;
}
}
/** Check for floating point data */
else if(std::is_floating_point <myType>::value)
{
data = strtold(str.c_str(),&ret);
if(*ret=='\0')
{
status=1;
}
else
{
std::cout<<"Invalid data, Please re-enter"<<endl;
}
}
else
{
// Need to see how to assign string type to template type
// Otherwise we still need to handle this else part
}
}
}
int main(void)
{
int myInt;
//cout<<"Enter an Integer : ";
getInput<int>(myInt, "Enter the Integer Data: ");
cout<<"Integer Value read = "<<myInt<<endl;
long long myLong;
//cout<<"Enter an Integer : ";
getInput<long long>(myLong, "Enter the long long Data: ");
cout<<"Long Long Value read = "<<myLong<<endl;
char myChar;
getInput <char> (myChar, "Enter single Character: ");
cout<<"Character read = "<<myChar<<endl;
double dbl;
getInput <double> (dbl, "Enter double value: ");
cout<<"double value = "<<dbl<<endl;
string myArr;
getInput(myArr, "Enter the string ");
cout<<"String read = "<<myArr<<endl;
}
The output is here.

When we assign 6.7 to integer, 6 gets assigned, but .7 is left in input buffer
>> reads an integer and stops when the next character cannot be a part of an integer. Said character could be a space character, or a newline character, or a decimal point character. >> doesn't care, it assumes nothing about how you want to process it. Perhaps after inputting an integer you will want to input a character and then another integer. Or a string. '.7' is a perfectly good input in either case.
If you want to e.g. read a line and make sure an integer is the only thing on that line, you need to these things yourself:
read a line
extract an integer from the line
verify there's nothing else there except probably white space
One way to handle such input would be this:
template <typename myType>
void getInput(myType &data, const std::string& promptMessage)
{
std::cout<<promptMessage;
std::string line;
std::getline(std::cin, line);
if (!std::cin)
throw std::runtime_error("End of file or IO error");
std::stringstream ss(line);
while (!(ss >> data) || !(ss >> std::ws) || !ss.eof())
{
std::cout<<"Entered Invalid data, Re-Enter: ";
std::getline(std::cin, line);
std::stringstream ss2(line);
std::swap(ss, ss2);
}
}
If you need specialised handling for char (for example you don't want to skip white space) you overload your function for char just like you have done for std::string.

Related

Why is this cin reading jammed?

I've singled out a failure on my program that prevents me from assigning a value to the variable addAntonymAnswer1. I've tried running cin.clear() before the statement to get the thing read my yes/no answer, but the code just won't respond.
The program bit that's failing is located inside void dictionaryMenu(vector <WordInfo> &wordInfoVector) and reads
cin.clear();
cout<<">";
cin>>addAntonymAnswer1;
// cin reading STUCK, why!?
to get to that point of the program the user has to choose to add a word, and then add a synonym.
The input for running the program is:
dictionary.txt
1 cute
2 hello
3 ugly
4 easy
5 difficult
6 tired
7 beautiful
synonyms
1 7
7 1
3 2
antonyms
1 3
3 1 7
4 5
5 4
7 3
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
class WordInfo{
public:
WordInfo(){}
WordInfo(string newWord){
word=newWord;
}
~WordInfo() { }
int id() const {return myId;}
void readWords(istream &in)
{
in>>myId>>word;
}
vector <int> & getSynonyms () {
return mySynonyms;
}
vector <int> & getAntonyms() {
return myAntonyms;
}
string getWord() {
return word;
}
void dictionaryMenu (vector <WordInfo> &wordInfoVector){
cout<<endl<<"Would you like to add a word?"<<endl;
cout<<"(yes/no)"<<endl;
cout<<">";
string addWordAnswer;
cin>>addWordAnswer;
if (addWordAnswer=="yes")
// case if the guy wants to add a word
{
cout<<endl;
cout<<"Please, write the word "<<endl;
string newWord;
cout<<">";
cin>>newWord;
cout<<endl;
WordInfo newWordInfo (newWord);
int newWordId = wordInfoVector.size() +1;
newWordInfo.myId=newWordId;
cout<<"The id of "<<newWordInfo.word<<" is "<<newWordInfo.myId<<endl<<endl;
wordInfoVector.push_back(newWordInfo);
cout<<"Would you like to define which words on the existing dictionary are" <<endl
<<"synonyms of "<<newWordInfo.word<<"?"<<endl;
cout<<"(yes/no)"<<endl;
string addSynonymAnswer, addAntonymAnswer1, addAntonymAnswer2;
cout<<">";
cin>>addSynonymAnswer;
if (addSynonymAnswer=="yes")
{
cout<<endl;
cout<<"Please write on a single line the ids for the synonyms of "
<<newWordInfo.word<<endl<<"starting with its id, which is "<<newWordInfo.myId<<endl<<endl;
cout<<"For example, to define that the synonym of the word 'cute', which has an id 1, is"
<<"'beautiful', which has an id 7, you should write: 1 7"<<endl<<endl;
cout<<"In the case of "<<newWordInfo.word<<" you should start with "<<newWordInfo.myId<<endl;
cin.clear();
string lineOfSyns;
cout<<">";
cin>>lineOfSyns;
newWordInfo.pushSynonyms(lineOfSyns, wordInfoVector);
cin.clear();
cout<<"Would you like to define which words on the existing dictionary are" <<endl
<<"antonyms of "<<newWordInfo.word<<"?"<<endl;
//##HERE THE CIN READING OF addAntonymAnswer1 FAILS, WHY?
cin.clear();
cout<<">";
cin>>addAntonymAnswer1;
// cin reading STUCK, why!?
if (addAntonymAnswer1=="yes"){ }
else if (addAntonymAnswer1=="no"){
// END DICTIONARY MENU
}
}
else if (addSynonymAnswer=="no"){
cout<<"Would you like to define which words on the existing dictionary are" <<endl
<<"antonyms of "<<newWordInfo.word<<"?"<<endl;
cout<<">";
cin>>addAntonymAnswer2;
if (addAntonymAnswer2=="yes"){ }
else if (addAntonymAnswer2=="no"){
// END DICTIONARY MENU
}
}
} // if addWordAnswer == "no"
else if (addWordAnswer=="no"){
// ######RETURN TO MAIN MENU############
}
}
void pushSynonyms (string synline, vector<WordInfo> &wordInfoVector){
stringstream synstream(synline);
vector<int> synsAux;
// synsAux tiene la línea de sinónimos
int num;
while (synstream >> num) {synsAux.push_back(num);}
int wordInfoVectorIndex;
int synsAuxCopyIndex;
if (synsAux.size()>=2){ // takes away the runtime Error
for (wordInfoVectorIndex=0; wordInfoVectorIndex <wordInfoVector.size(); wordInfoVectorIndex++)
{
if (synsAux[0]==wordInfoVector[wordInfoVectorIndex].id()){
// this is the line that's generating a Runtime Error, Why?
for (synsAuxCopyIndex=1; synsAuxCopyIndex<synsAux.size(); synsAuxCopyIndex++){
// won't run yet
wordInfoVector[wordInfoVectorIndex].mySynonyms.push_back(synsAux[synsAuxCopyIndex]);
}
}
}
}// end if size()>=2
} // end pushSynonyms
void pushAntonyms (string antline, vector <WordInfo> &wordInfoVector)
{
stringstream antstream(antline);
vector<int> antsAux;
int num;
while (antstream >> num) antsAux.push_back(num);
int wordInfoVectorIndex;
int antsAuxCopyIndex;
if (antsAux.size()>=2){ // takes away the runtime Error
for (wordInfoVectorIndex=0; wordInfoVectorIndex <wordInfoVector.size(); wordInfoVectorIndex++)
{
if (antsAux[0]==wordInfoVector[wordInfoVectorIndex].id()){
// this is the line that's generating a Runtime Error, Why?
for (antsAuxCopyIndex=1; antsAuxCopyIndex<antsAux.size(); antsAuxCopyIndex++){
// won't run yet
wordInfoVector[wordInfoVectorIndex].myAntonyms.push_back(antsAux[antsAuxCopyIndex]);
}
}
}
}// end if size()>=2
}
//--dictionary output function
void printWords (ostream &out)
{
out<<myId<< " "<<word;
}
//--equals operator for String
bool operator == (const string &aString)const
{
return word ==aString;
}
//--less than operator
bool operator <(const WordInfo &otherWordInfo) const
{ return word<otherWordInfo.word;}
//--more than operator
bool operator > (const WordInfo &otherWordInfo)const
{return word>otherWordInfo.word;}
public:
vector<int> mySynonyms;
vector <int> myAntonyms;
string word;
int myId;
};
//--Definition of input operator for WordInfo
istream & operator >>(istream &in, WordInfo &word)
{
word.readWords(in);
}
//--Definition of output operator
ostream & operator <<(ostream &out, WordInfo &word)
{
word.printWords(out);
}
int main() {
string wordFile;
cout<<"enter name of dictionary file: "<<endl;
getline (cin,wordFile);
ifstream inStream (wordFile.data());
if(!inStream.is_open())
{
cerr<<"cannot open "<<wordFile<<endl;
exit(1);
}
vector <WordInfo> wordInfoVector;
WordInfo aword;
while (inStream >>aword && (!(aword=="synonyms")))
{
wordInfoVector.push_back(aword);
}
inStream.clear();
vector <int> intVector;
string synLine;
while (getline(inStream, synLine)&&(synLine!=("antonyms"))){
aword.pushSynonyms(synLine, wordInfoVector);
}
int theIndex;
string antLine;
while (getline(inStream,antLine)){
aword.pushAntonyms(antLine, wordInfoVector);
}
cout<<endl<<"the words on the dictionary are: "<<endl;
int h=0;
while (h<wordInfoVector.size()){
cout<<wordInfoVector[h]<<endl;
h++;
}
aword.dictionaryMenu(wordInfoVector);
system("PAUSE");
return 0;
}
cin.clear() doesn't clear the standard input. What it does is clearing error bits, like eofbit, failbit and others, and sets the stream into a good state. Maybe you expected it to clear out anything in it? If the user typed
yes no
Just before, and you
cin >> someStringVariable;
It will read up to no and the stream will still contain
no
The call to clear then clears any error bits being active. Then, your
cin>>addAntonymAnswer1;
Will read the no that wasn't eaten by the previous read, and the action immediately returns, not waiting for new input. What you should do is doing a clear followed by an ignore, up to the next newline. You tell it the amount of characters it should ignore maximally. That amount should be the highest number possible:
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Doing that will make the stream empty, and a following read will wait for you to type something in.
Another problem arises if you have got a cin >> followed by a getline: The cin will leave any whitespace (also newlines) after its read token, but getline will stop reading after it hits such a newline. I see you have put clear after nearly everything. So i want to show you when you need it and when not. You don't need it when you sequence multiple cin >>. Assume you have in your buffer: "foo\nbar\n". Then you do the following reads
cin >> a; // 1
cin >> b; // 2
After the first, your buffer will contain "\nbar\n". That is, the newline is still in. The second cin>> will first skip all whitespace and newlines, so that it can cope with \n being at the front of bar. Now, you can also sequence multiple getline calls:
getline(cin, a);
getline(cin, b);
Getline will throw away the \n that it reads at the line end, but won't ignore newlines or whitespace at the begin. So, after the first getline, the buffer contains "bar\n". The second getline will correctly read "bar\n" too. Now, let's consider the case where you need the clear/ignore:
cin >> a;
getline(cin, b);
The first will leave the stream as "\nbar\n". The getline then will see immediately the \n at the begin, and will think it read an empty line. Thus, it will immediately continue and not wait for anything, leaving the stream as "bar\n". So, if you have a getline after a cin>> you should first execute the clear/ignore sequence, to clear out the newline. But between getline or cin>>'s, you should not do it.
It is "stuck" because it is waiting for input. cin is attached to the standard input handle for the program, you have to type something and hit enter.
cin >> ... reads from standard input until it finds a whitespace character. When you enter, say, 8 5 for the list of synonyms, 8 gets read into lineOfSyns and nothing more. When the program reaches cin >> addAntonymAnswer1, 5 gets read into addAntonymsAnswer1. Your program behaves unexpectedly since it expects yes or no but it got 5.
Look at using cin.getline() instead of >>. See, for example, sections 18.2 and 18.3 of this page.
In your program you ask the user:
Please write on a single line the ids for the synonyms of test
starting with its id, which is 8
For example, to define that the synonym of the word 'cute', which has an id 1, i
s'beautiful', which has an id 7, you should write: 1 7
In the case of test you should start with 8
Then you attempt to read in the line the user typed with
cin>>lineOfSyns;
However, this only reads up to the first whitespace. So the 2nd number typed in by the user is still in the cin buffer when the
cin>>addAntonymAnswer1;
line is executed, so that data gets read into the addAntonymAnswer1 string. The user never gets an opportunity to type in 'yes' or 'no' and your tests for those values fail.
You should consider changing to using the string overload for getline() to do your reads:
getline( cin, stringvar);
This would probably be better than using cin.getline(), as that does not have an overload that takes string - with that member function, you need to read into an array of chars, which is far less flexible than reading into a string.

How to store Integers from a string without using the getline function. C++

Sorry to ask, but I been looking everywhere to find a way to extract the integers from this set of strings:
{(1,2),(1,5),(2,1),(2,3),(3,2),(3,4),(4,3),(4,5),(5,1),(5,4)}
I don't really need the homework done, if you could link me to an example, I'll appreciate it.
thank you in advanced.
If you just want to access the integers from a line like that, one way is to simply continue reading integers while you can.
If, for some reason, you find an integer read failing (because there's a { in the input stream, for example), just skip over that single character and keep going.
Sample code for this is:
#include <iostream>
int main() {
int intVal; // for getting int
char charVal; // for skipping chars
while (true) {
while (! (std::cin >> intVal)) { // while no integer available
std::cin.clear(); // clear fail bit and
if (! (std::cin >> charVal)) { // skip the offending char.
return 0; // if no char left, end of file.
}
}
std::cout << intVal << '\n'; // print int and carry on
}
return 0;
}
A transcript follows:
pax> echo '{(314159,271828),(42,-1)}' | ./testprog
314159
271828
42
-1

Using istringstream() to distinguish between “0” and non-numerical string

I am trying to make a program to play poker. When betting the player should enter an integer number as their new bet. To prevent errors when someone mistypes and enters a string the code is intended to take in a string, check if it is a number, and if it is not then ask the player to enter a valid bet.
The code below is my attempt at making a function to do that using the istringstream function to convert the string betstring to an int.
istringstream returns 0 if the string has no number in it. betstring is an invalid entry if it is a number less than 0 or if it contains no numbers. If betstring is "0" this is a valid bet.
If betstring is mixed letters and numbers (e.g. j96kp) then this "j96kp" is assumed to indicate a bet of 96 for simplicity so it is valid.
The problem comes when I enter a betstring equal to "0". The code interprets this as an invalid bet. I have checked the logic operators and I do not understand why the code does not take "0" to be a valid bet.
Can anybody spot where the problem is arising?
#include <stdlib.h>
#include <stdio.h>
#include <sstream>
#include <string>
using namespace std;
int requestBet()
{
int newbet;
string betstring;
int validbet = 0;
while(!validbet)
{ //loop until a valid bet is entered
cin >> betstring;
validbet = 1; //assume bet is valid then test this
istringstream(betstring) >> newbet;
if(((newbet == 0) && (betstring.at(0) != 0)) || (newbet < 0))
{
cout << "Enter a valid bet" << endl;
validbet = 0;
}
}
return newbet;
}
int main()
{
int number;
cout << "Enter your bet" << endl;
number = requestBet();
return 0;
}
betstring.at(0) != 0 does not do what you probably expect it to do. You want to compare characters, that is, see if the first character is '0', so you have to put that in there. As it is, your code sees whether the fist char has the numerical value zero (which would be '\0').
... the player should enter an integer number as their new bet. To prevent errors when someone mistypes and enters a string the code is intended to take in a string, check if it is a number, and if it is not then ask the player to enter a valid bet.
Something like the following will work for you.
template <class T>
T StringToValue(const std::string& str) {
std::istringstream iss(str);
T value; iss >> value;
// Use fail(), not bad()
if (iss.fail())
throw std::runtime_error("'" + str +"' is not a value");
return value;
}
You can use it like:
string betstring;
cin >> betstring;
int bet;
bet = StringToValue<int>(betstring);
If the string is not a presentation of type T (int, float, etc), then a runtime_error is thrown.
If you switch to bad(), then the function will return 0 when it encounters something that would throw under fail().

c++ ifstream only reading in one string need both read in

I have small amount of data in a file that looks like
New Mexico
50.9 10
this repeats with every state and whenever i hit states with two words for their title my program says pretty much says ooops we'll put first word in your string but the second one has no storage for it. With that it discontinues taking the rest of the data once that double worded title is encountered. Is there a way to take both words and put them in one string when reading my file in?
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
using namespace std;
struct AccountsDataBase{
string stateName;
double miles;
int rests;
};
#define MAX 80
AccountsDataBase * account = new AccountsDataBase[MAX];
int readIn(ifstream& file){
int count=0;
file >> account[count].stateName;
file >> account[count].miles;
file >> account[count].rests;
while( !file.eof() && count<MAX){
count++;
file >> account[count].stateName;
file >> account[count].miles;
file >> account[count].rests;
}
return count;
}
int main(){
ifstream file;
file.open("input.txt"); //opens data account records text
if ( !file.fail() ) {
int cnt = readIn(file);
delete[] account;
}
return 0;
}
Your question is certainly vague. However, here's one way of doing that:
std::ifstream ifile("filename_and_path"); //Requires <fstream>
//check to see if the file is open or not:
if (!ifile.is_open()) {
std::cerr << "Something went wrong!" << std::endl;
exit(1);//stop program execution. Requires <cstdlib>
}
std::string temp;
std::string state;
std::vector <std::string> tokens; //Requires <vector>
//std::getline requires: <string>
while(std::getline(ifile, temp)) {
std::istringstream iss(temp);//initialize the stream to the contents of the line
//keep parsing over the stream into tokens separated by ' ' (space) characters
while(std::getline(iss, temp, ' ')) {
//store all the tokens:
tokens.push_back(temp);
}
//UPDATED to read ALL states. (I misread the question.)
//we know that the last two parameters are always numbers, so use this
//to our advantage:
//if an even number, then we have two words, get and concatenate them:
if (tokens.size() % 2 == 0) {
state = tokens[0] + " " + tokens[1];
}
else {
//this is an odd number of parameters. This means that this is a state
//with one word (e.g.: Maryland)
state = tokens[0];
}
//this is the end of one line, might as well print out the state name:
std::cout << state << std::endl;
state.clear();//empty the string for the next iteration
tokens.clear();//empty the tokens for the next iteration
}
You can use std::vector to store all std::string tokens in each line then use iterator to read the value. This solution shall work for general state names with any length not just one with two-word like New Mexico as long as the last two tokens of each line in the file represents double and int value.
int readin(const ifstream& file)
{
...
string val;
vector<string> v;
while (val = file.get() )
{
v.push_back(val);
}
//assign concatentaion from element 1st to nth-2
for(vector<string>::iterator it = v.begin(), it != v.end()-2;it++)
account[count].stateName += *it + " ";
//assign element nth -2
account[count].miles = atof(*(v.end()-2).c_str());
//assign element nth -1
account[count].rests = atoi(*(v.end()-1).c_str());
...
}
ok everyone i asked my teacher for the answer and she said all i had to do was use getline() ;,D cracking me up i was about to apply 20 lines of code to solve a one line C function.

C++ - Trying to create a function that reads data from a file into an array of structs?

I've looked at a couple similar questions but I still can't seem to come close to understanding this. I get the basic idea for structs and array but I'm so lost for actually creating a function to read data from a file into an array of structs. Hoping someone could help me out. :(
We have to:
Write a function, InputPlayerData that will read the data from the input file of unknown >length into the array of structs
A. The data in the input file contains the following information about each player
name
position
number (Player's number on her jersey)
at bats (The number of times a player is at bat)
hits (The number of hits while at bat)
bases taken (The number of bases run after a hit)
B. Sample lines of data from the input file:
i. The data for the first player:
MarTee Apple is the player’s name
Catcher is the player’s position
17 is her jersey number
20 is the number of times at bat
7 is the number of hits
20 is the number of bases taken
So, that's what it looks like. I tried to start the function and the program actually runs but I don't get the output. The cursor just blinks. Any help would be so much appreciated.
struct playerRecordType
{
string name;
string position;
int number;
int atBats;
int hits;
int basesTaken;
int ranking;
double battingAverage;
double sluggingAverage;
};
int InputPlayerData(ifstream& inFile, playerRecordType player[MAX]);
int main(void)
{
ifstream inFile;
ofstream outFile;
//open the files
inFile.open("SoftballData.txt");
outFile.open("SoftballResults.txt");
playerRecordType player[MAX];
int length = InputPlayerData(inFile, player);
outFile << length;
return 0;
}
int InputPlayerData(ifstream& inFile, playerRecordType player[])
{
int index;
//initialize i
index = 0;
//primer for the loop
getline(inFile, player[index].name);
//while not end-of-file to process the file data
while(!inFile.eof())
{
inFile >> player[index].name >> player[index].position
>> player[index].number >> player[index].atBats
>> player[index].hits >> player[index].basesTaken;
index++;
}
First, this:
while(!inFile.eof())
is wrong. Read this article for why this is so.
Next, your loop body and initial entrance is incorrect. You do this:
//primer for the loop
getline(inFile, player[index].name);
in an apparent attempt to load the first player's name, then proceed in the loop body to do this:
inFile >> player[index].name >> player[index].position
>> player[index].number >> player[index].atBats
>> player[index].hits >> player[index].basesTaken;
Note the player's name line is read twice. This will throw off the remaining data of this record, with the last element, basesTaken attempting to extract (and fail) to pull an integer from the second player's name. The result is the stream will be placed in an error state, but has not yet reached EOF. Therefore, adding insult to injury the incorrect while-loop condition discussed previously will never be true, the loop will execute again, and due to the error state, fail all extractions, looping again, not yet eof, etc...
I would hazard to guess this is what you're trying to do:
#include <iostream>
#include <fstream>
#include <string>
struct playerRecordType
{
std::string name;
std::string position;
int number;
int atBats;
int hits;
int basesTaken;
int ranking;
double battingAverage;
double sluggingAverage;
};
inline std::istream& operator >>(std::istream& inp, playerRecordType& player)
{
if (std::getline(inp, player.name) &&
std::getline(inp, player.position) &&
(inp >> player.number >> player.atBats >> player.hits >> player.basesTaken))
{
if (player.atBats > 0)
{
player.battingAverage = static_cast<double>(player.hits)/
static_cast<double>(player.atBats);
player.sluggingAverage = static_cast<double>(player.basesTaken)/
static_cast<double>(player.atBats);
}
else
{
player.battingAverage = 0;
player.sluggingAverage = 0;
}
};
return inp;
}
template<std::size_t N>
std::size_t InputPlayerData(std::istream& inp, playerRecordType (&players)[N])
{
std::size_t x = 0;
for (; x < N && inp >> players[x]; ++x);
return x;
}
#define MAX (100)
int main()
{
std::ifstream inFile("SoftballData.txt");
playerRecordType players[MAX];
std::size_t length = InputPlayerData(inFile, players);
std::cout << length << '\n';
return 0;
}
I leave the output side of this little quest into the deep blue code as an exercise for you. Best of luck.
like 0x499602D2 user commented - your InputPlayerData() method is not returning any value.

Resources