Read from the file from different functions - c++

I'm trying to read from the same file from another function but it doesn't work.
I guess the problem is that I'm trying to read from ifstream &input but I don't know the other way to implement that
#include <iostream>
#include <fstream>
using namespace std;
class Student{
public:
char name[40]; // i cant use string
int age;
void Input(ifstream &input)
{
input.getline(name, 40);
input >> age;
}
};
void Read(Student *students, int &numberOfStudents)
{
ifstream input("test.txt");
input >> numberOfStudents;
students = new Student[numberOfStudents];
for (int i = 0; i < numberOfStudents; ++i)
students[i].Input(input);
input.close();
}
int main()
{
int size = 0;
Student *students = NULL;
Read(students, size);
for (int i = 0; i < size; ++i)
cout << students[i].name << endl << students[i].age << endl;
return 0;
}
I made my input file
3
1
2
3
4
5
6
(if the program was working correctly i should've get 1 - name age - 2 etc)
but what i got is no names with ages = 1 2 3 respectively

The program does not work because you define:
void Read(Student *students, int &numberOfStudents)
And then
int size = 0;
Student *students = NULL;
Read(students, size);
The students pointer is passed-by value so Read() can not change the memory address outside the function.
To fix this simply pass the the pointer by-reference:
void Read(Student *& students, int &numberOfStudents)
Lastly as I commented you need to account white space e.g. '\n' line ending
In the file when using >> operator to extract data:
void Input(ifstream &input)
{
input.getline(name, 40);
input >> age;
input.ignore(1);
}
Same for reading the number of students in the file.

Related

Passing an Array built off of a Struct to a Function that Stores Data into Array from a File

In a structs lab assignment that I am doing, the question asks to read statistics about 10 different dinosaurs from a text file and store that information into a struct. I get no errors in the code, however the console is just totally blank.I think i am definitely referencing the array wrong and I have no idea how to fix this.
My code is as follows:
using namespace std;
const int LIST_SIZE = 10;
struct dinosaurInfo {
string dinosaurName;
string dinosaurClass;
string dinosaurHabitat;
double dinosaurSize;
double dinosaurWeight;
int battleRating;
};
void loadData(ifstream& getData, dinosaurInfo *data);
int main()
{
dinosaurInfo data[LIST_SIZE];
ifstream getData;
ofstream giveData;
getData.open("dinosaurRecords.txt");
if (!getData)
{
cout << "Error loading in data." << endl;
}
loadData(getData, data);
getData.close();
system("pause");
return 0;
}
void loadData(ifstream& getData, dinosaurInfo *data)
{
while (!getData.eof())
{
for (int i = 0; i < 10; i++)
{
getline(getData, data[i].dinosaurName);
getline(getData, data[i].dinosaurClass);
getline(getData, data[i].dinosaurHabitat);
cin.ignore();
getData >> data[i].dinosaurSize;
getData >> data[i].dinosaurWeight;
getData >> data[i].battleRating;
}
}
The text file is formatted as follows: (dinosaurname class habitat height weight battle rating).
screenshot of the file below
May someone please help me fix this?
The root problem is use of getline to read the string elements.
getline(getData, data[i].dinosaurName);
getline(getData, data[i].dinosaurClass);
getline(getData, data[i].dinosaurHabitat);
Since these are tokens separated by space, use the >> operator instead to read them.
getData >> data[i].dinosaurName;
getData >> data[i].dinosaurClass;
getData >> data[i].dinosaurHabitat;
Also, avoid use of
while (!getData.eof()) { ... }
See Why is iostream::eof inside a loop condition considered wrong? for details.
A cleaned up version of you function would be:
void loadData(ifstream& getData, dinosaurInfo *data)
{
// Stop when 10 records are read.
// Also, stop reading when getData is an error state.
for (int i = 0; i < 10 && getData; i++)
{
getData >> data[i].dinosaurName;
getData >> data[i].dinosaurClass;
getData >> data[i].dinosaurHabitat;
getData >> data[i].dinosaurSize;
getData >> data[i].dinosaurWeight;
getData >> data[i].battleRating;
}
}

C++ Storing Items in Array and Setting each Token

My name is Faith and I am a beginner programmer in C++. I am working on a project where I have to read in two file and be able to separate the items in each file to its own variable. The first file has two pieces of information separated by "," and the second has three pieces of information. So far, I think I've done well with reading the files and getting each line in the file. Also I've separated each item by "," now I am trying to store those items in its on variable. Please Help! I've tried starting this project over multiple times and this is the only method I know how to implement to do this.
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdlib.h>
using namespace std;
class Manufactuer{
string upcode;
string company_name;
public:
void setupcode(string value){
upcode= value; }
void setcompany_name(string value){
company_name= value; }
string getupcode(){ return upcode;}
string getcompany_name(){return company_name;}
};
class Products{
string product_num;
string quantity;
string product_name;
public:
void setproduct_num(string value){
product_num= value; }
void setproduct_name(string value){
product_name= value; }
void setquantity(string value){
quantity = value;}
string getproduct_num(){ return product_num;}
string getquantity(){return quantity;}
string getproduct_name(){return product_name;}
};
int main(int argc, const char * argv[]) {
//opens the csv file
std::ifstream mccodesfile;
std::ifstream salesfile;
mccodesfile.open("mccodes.csv");
if(!mccodesfile){// file couldn't be opened
cout<<"Failed: file could not be opened"<<endl<<"Press Enter to Close:";
cin.get();
return 0;
}else
cout<<"Successfully opened file!"<<endl;
salesfile.open("sales.csv");
if(!salesfile){// file couldn't be opened
cout<<"Failed: file could not be opened"<<endl<<"Press Enter to Close:";
cin.get();
return 0;
}else
cout<<"Successfully opened file!"<<endl;
Manufactuer* upccodes;
int count; //how many elements in the array
int size; //how large the array
count = 0;
size = 2;
upccodes= (Manufactuer*)malloc(size*sizeof(Manufactuer)); //Malloc dynamatically reserve memory for variable pointer
string line;
while (getline(mccodesfile,line)) {// Taking every line from the file and putting in the variable line
Manufactuer newcode = Manufactuer(); //creating a upcode object
istringstream ss(line);
string token; //setting up split values
bool haveReadUPCode = false;
while (getline(ss,token,',')){// Separated values by comma
if(!haveReadUPCode){
newcode.setupcode(token);
haveReadUPCode = true;
}else{
newcode.setcompany_name(token);
}
}
if (count == size){
size = size * 2;
upccodes= (Manufactuer*)realloc(upccodes,size*sizeof(Manufactuer)); //Double the size while keeping the same elements
}
upccodes[count++]= newcode;
// cout<<line<<endl;
}
for (int i = 0; i<count; i++){
// cout<<upccodes[i].getcompany_name()<<endl; //Prints Manufactuers name--Works!
}
for (int i=0; i<count; i++) {
// cout<<upccodes[i].getupcode()<<endl; //Prints UPCcodes--Works
}
Products* product;
product= (Products*)malloc(size*sizeof(Products)); //Malloc dynamatically reserve memory for variable pointer
while(getline(salesfile, line)){{// Taking every line from the file and putting in the variable line
Products newProduct = Products(); //creating a product object
istringstream ss(line);
string token; //setting up split values
bool haveReadProduct = false;
while (getline(ss,token,',')){// Separated values by comma
if(!haveReadProduct){
newProduct.setproduct_num(token);
haveReadProduct = true;
} else{
newProduct.setproduct_name(token);
newProduct.setquantity(token);
}
}
if (count == size){
size = size * 2;
product= (Products*)realloc(product,size*sizeof(Products)); //Double the size while keeping the same elements
}
product[count++]= newProduct;
//cout<<line<<endl; //LINES ARE Printing!
}
}
for (int i = 0; i<count; i++){
// cout<<product[i].getproduct_name()<<endl; //Prints Product name--Works
}
for (int i = 0; i<count; i++){
//cout<<product[i].getproduct_num()<<endl; //Prints Product number--Works
}
}

Randomize array using pointers

Im trying to shuffle my deck of cards using pointers. My loops just print out the default value, not cycling through the cards. how do i fix this. shuffle functiuon is at the bottom? I am trying to loop through and increment pointers while replacing my destination pointer with my source pointer. or the dereferenced value. what am i doing wrong?
#include <iostream>
#include <fstream>
#include <ctime>
#include <stdlib.h>
#include <string>
using namespace std;
//global constant(s)
const int maxCards = 52;
//Structs
struct card
{
char suit[8];
char rank[6];
int cvalue;
char location;
};
struct player
{
char name[100];
int total;
};
//Function List
char * strcopy(char destination[], const char source[]);
void shuffle(card* destinationP,card* sourceP);
//program
int main()
{
//begin seeding the time for randomize later
srand(time(NULL));
//declaration of variables
bool gameOn =true;
int choice;
char tempfName[100];
char templName[100];
int count =0;
//create struct array(s)
card deck[52];
card shuffledDeck[52];
player people[4];
//create pointer and set initial value
card * deckPointer = NULL;
card * shuffledDeckPointer= NULL;
player *peoplePointer = NULL;
//
deckPointer = &deck[0]; //assign address of deck to deckPointer
shuffledDeckPointer = &shuffledDeck[0];
peoplePointer = &people[0]; //assign address of people to peoplePointer
//sets default values for the card arrays
for(int i=0;i<52;i++)
{
strcopy(shuffledDeck[i].suit, "suit");
strcopy(shuffledDeck[i].rank,"rank");
shuffledDeck[i].cvalue = 0;
strcopy(deck[i].suit,"suit");
strcopy(deck[i].rank,"rank");
deck[i].cvalue = 0;
}
//set up card file to be read in
ifstream fin;
char finName[12];
//get file name from user
cout << "Enter file name...(cardFile.txt)" << endl;;
cin >> finName;
//open the file
fin.open(finName);
//check if cardFile.txt opens correctly
if(!fin.good())
{
cout << "Error with card file" << endl;
return 0;
}
else
{
card *deckPointer = NULL;
//prime fin
//fin >> deck[i].suit;
//fin >> deck[i].rank;
//fin >> deck[i].cvalue;
while(fin.good())
{
for(deckPointer = &deck[0]; deckPointer < &deck[maxCards];deckPointer++)
{
fin >> (*deckPointer).suit;
fin >> (*deckPointer).rank;
fin >> (*deckPointer).cvalue;
}
}
}
cin.clear();
}
//Functions
//copy string function
char * strcopy(char *destination, const char* source)
{
char *p = destination;
while(*p++ = *source++);
return destination;
}
//Shuffle function
void shuffle(card *destinationP,card *sourceP)
{
int randomNumber = 0;
int count=0;
for(int j=0;j<52;j++)
{
//choose a random number up to 52
randomNumber = rand()%52;
count = 0;
if(count < randomNumber)
{
while(count < randomNumber)
{
*sourceP++;
count++;
}
//check if destination is empty ie will accept
//a card and will not overwrite a card
if((*destinationP).cvalue == 0)
{
// copy unshuffled "deck" to the shuffled "deck"
strcopy((*destinationP).suit, (*sourceP).suit);
strcopy((*destinationP).rank, (*sourceP).rank);
(*destinationP).cvalue = (*sourceP).cvalue;
*destinationP++;
}
}
else
{
if((*destinationP).cvalue == 0)
{
// copy unshuffled "deck" to the shuffled "deck"
strcopy((*destinationP).suit, (*sourceP).suit);
strcopy((*destinationP).rank, (*sourceP).rank);
(*destinationP).cvalue = (*sourceP).cvalue;
*destinationP++;
}
}}}
Just use an std::vector and std::shuffle. Also don't use rand(), use the <random> header instead. And std::string instead of char*.
I prefer the Fisher-Yeats shuffle which Donald Knuth put into his Art of Computer Programming as Algorithm P. Pseudo code can be found at: http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle. Incidentally, for better randomization properties, I would recommend using a Mersenne Twister (http://en.wikipedia.org/wiki/Mersenne_Twister) for which you can find GPLd source in several languages

Read two words into one char array element

I am trying to read in two words from text file into one char array element. I CANNOT USE std::string. I get a seg fault because my loop is looping in a way that goes out of bounds. I cannot copy in the two words. please help me do this!! My loop for card struct works perfectly. I cannot get the "first last" into the people[].name
// deck of cards
// below are initializations
#include
#include
#include
#include
#include
using namespace std;
//globals
const int maxCards = 52;
//Structs
struct card {
char suit[8];
char rank[6];
int cvalue;
char location;
};
struct player {
char name[100];
int total;
card hand[4];
};
//program
int main()
{
//constants
char tempfName[100];
char templName[100];
//create struct array(s)
card deck[52];
card shuffledDeck[52];
player people[4];
//create pointers
card * deckPointer =NULL;
deckPointer = deck;
card * shuffledDeckPointer=NULL;
shuffledDeckPointer = shuffledDeck;
for(int i=0;i<4;i++)
{
strcopy(people[i].name,"first last");
}
//open player names file
ifstream fin2;
string fin2Name;
//get file name from user
cout << "Enter player file name...(Players.txt)" << endl;
getline(cin, fin2Name);
//open file
fin2.open(fin2Name.c_str());
//check if Players.txt opens correctly
if(!fin2.good())
{
cout << "Error with player file!" << endl;
return 0;
}
else
{
int j =0;
fin2 >> people[j].name; //prime file
while(fin2.good())
{
//find the length
int index =0, length=0;
while(tempfName[length] != '\0')
{
length++;
}
//now add space after first name
tempfName[length] = ' ';
length++;
while(templName[index] != '\0')
{
tempfName[length] = templName[index];
length++;
index++;
}
tempfName[length]='\0';
int counter =0;
while(templName[counter] != '\0')
{
people[0].name[counter] = templName[counter];
counter++;
}
}
}
it seems your tempfName is not pointing to a correct object in your while loop in else statement
else
{
int j =0;
fin2 >> people[j].name; //prime file
while(fin2.good())
{
//find the length
int index =0, length=0;
while(tempfName[length] != '\0')
{
length++;
}
You could do some cheating:
char full_name[256]; // Binary quantities are better.
snprintf(full_name, sizeof(full_name),
"%s %s",
first_name, last_name);
You should do more research regarding C-style string functions, like check a good reference book. It should have a chapter about the C-style string functions.
Here are some helpful ones:
strcpy, strcat, strchr, sprintf, strlen

Assigning file data to array of structs

I'm currently attempting to assign a line of data from an input file to an array of structs.
Here is my struct:
struct student
{
int ID;
int hours;
float GPA;
};
student sStudents[MAX_STUDENTS]; // MAX_STUDENTS = 10
Where:
for (int i = 0; !inputFile.eof(); i++)
{
getline(inputFile, dataLine);
cout << dataLine << endl; // Everything outputs perfectly, so I know dataLine is getting the correct information from getline()
//??
}
After an hour of crawling through Google I still don't have an idea of how to get my getline() data into each struct array.
I have tried,
sStudents[i] = dataLine;
sStudents[i] << dataLine;
sStudents.ID = dataLine;
Here is my data file:
1234 31 2.95
9999 45 3.82
2327 60 3.60
2951 68 3.1
5555 98 3.25
1111 120 2.23
2222 29 4.0
At this point I've become frustrated and I'm just not sure what to do. I'm convinced at this point I'm going about it completely incorrectly but not sure how to continue from here. I know that 10 elements of sStudents exist so that's good but how can I get the values from the input file into each .ID, .hours, .GPA? Perhaps getline() is being used incorrectly here?
You can simply do the following:
int ID = 0;
int hours = 0;
float GPA = 0.0;
int i = 0;
ifstream inputFile("data.txt");
while (inputFile >> ID >> hours >> GPA)
{
sStudents[i].ID = ID;
sStudents[i].hours = hours;
sStudents[i].GPA = GPA;
i ++;
}
A suggestion using the Standard Library.
#include<iostream>
#include<fstream>
#include<vector>
// your data structure
struct Student {
int id;
int hours;
float gpa;
};
// overload the input stream operator
bool operator>>(std::istream& is, Student& s) {
return(is>>s.id>>s.hours>>s.gpa);
}
// not necessary (but useful) to overload the output stream operator
std::ostream& operator<<(std::ostream& os, const Student& s) {
os<<s.id<<", "<<s.hours<<", "<<s.gpa;
return os;
}
int main(int argc, char* argv[]) {
// a vector to store all students
std::vector<Student> students;
// the "current" (just-read) student
Student student;
{ // a scope to ensure that fp closes
std::ifstream fp(argv[1], std::ios::in);
while(fp>>student) {
students.push_back(student);
}
}
// now all the students are in the vector
for(auto s:students) {
std::cout<<s<<std::endl;
}
return 0;
}
To get data out of an input stream use the >> operator. So:
int i;
file >> i;
extracts a single integer from the file. By default it is space delimited. Use that and see if you get further.