Storing Arrays of Structs in external files in C++ - c++

So I'm working on a homework assignment for my CS162 class which requires me to make a program that allows the user to input their class plan for college. The user inputs classes they have taken, are currently taken, and/or plan on taking, with the categories of: department/class number, class name, term/year, whether or not the class is required for their major, and any additional comments. Then, the program is supposed to store this invermation with external data files so that the classes are stored and won't be lost. The program should be able to store up to 60 classes in memory.
I know how to create arrays of strucs and I know the basics behind external files, but I guess I'm having trouble combining the two (I'm a newbie here, so sorry if this is really basic!)
Here's what I have so far:
struct college_class
{
char dept_classnumber;
char class_name;
char term_year;
char is_required;
char comments;
char grade;
}
college_class[60]
int main()
{
int n;
char again;
for(n=0;n<60;n++)
{
do
{
cout<<"Enter department and class number (e.g. CS162): ";
getline (cin,college_class[n].dept_classnumber);
cout<<"Enter class name (e.g. Intro to Computer Science): ";
getline (cin,college_class[n].class_name);
cout<<"Enter the term and year the class was/will be taken: ";
getline (cin, college_class[n],term_year;
cout<<"Enter whether or not this class is required for your major: ";
getline (cin,college_class[n],is_required);
cout<<"Enter any additional comments here: ";
getline (cin, college_class[n],comments);
cout<<"Would you like to enter another class?(y/n)";
cin>>again;
}
while(again == 'y' || again == 'Y' && i<60)
}
Is this the right direction in terms of getting the user input? My other question is, how do you incorporate the external file into this so that everything the user inputs is stored into the file? Sorry if this is a little vague, and I'm obviously not looking for my homework to be done for me - I'm just looking for a little direction to get started here.
I know that writing on a text file looks like this, for example:
ofstream my file ("example");
if(myfile.is_open()))
{
myfile <<"blah blah blah. \n";
myfile.close();
}
...I'm just not sure how to make this work for arrays of structs.

There are multiple things wrong with you code.
First of all, you have to create a variable for your college_class array.
Eg.:
college_class myCollegeClass[60]
and use that when asking input
getline (cin, myCollegeClass[n].term_year;)
you accidentally used commas on some lines there, watch out for that
Furthermore, a char can only hold one character, which won't be enough if you want to hold the full class name, use strings in your struct.
struct college_class
{
string class_name;
...
}
You used a nested loop there, which will repeat your questions 60 times, regardless if you said you didn't want to input anything else.
I'd suggest
int i=0;
char again = 'y';
while(again != 'n' && again != 'N' && i<60)
{
...
i++
}
As for the file, after you have your inputs, just loop though your myCollegeClass array and write the data to the file. Eg.:
myfile << myCollegeClass[i].class_name;

Related

searching a name in the csv file on C++

I am a young programmer who is trying to learn c++. i have a working csv.file. but i want to search for a specific number assigned to the name and then displays the name of what i'm looking for. i have the file here:
1,Bulbasaur,grass
2,Ivysaur, grass
3,Venusaur, grass
4,Charmander, fire
5,Charmeleon, fire
6,Charizard, fire
7,Squirtle, water
8,Wartortle, water
9,Blastoise, water
Code
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream ip("pokedex.csv");
string pokedexnum[9];
string pokemonName[9];
string pokemonType[9];
cout<<"please enter a pokemon number:"<<" ";
cin>>pokemonType[0];
while (ip.good()){
getline( ip, pokedexnum[0]);
getline( ip, pokemonName[0]);
getline( ip, pokemonType[0]);
}
cout<<"the pokemon that is:"<< " "<<pokedexnum[0]<< "is the pokemon called:"<< pokemonName[0];
ifstream close("pokedex.csv");
return 0;
}
when it runs
please enter a pokemon number: 1
the pokemon that is: is the pokemon called:8,Wartortle, water
could you please point out what i am doing wrong?
Among the issues in this code:
You're not using std::getline correctly for comma-separated data. The result is each pass is consuming three lines from your input file; not three values from each line.
You're also not using ip.good() correctly as a while-condition.
You're retaining your test value in the array, which will be overwritten on the first iteration pass, so it is lost.
You're ignoring potential IO failures with each std::getline invoke.
You're overwriting slot-0 in your arrays with each loop iteration.
Minor, ifstream close("pokedex.csv"); clearly isn't doing what you think it is. That just creates another fstream object called close on the given file name.
The later may be intentional for now, but clearly broken in the near future.
In reality, you don't need arrays for any of this. All you're doing is reading lines, and seem to want to test the input number against that of the CSV data first column, reporting the line that you find, then ending this.
So do that:
Read the input value to search for.
Open the file for scanning.
Enumerate the file one line at a time.
For each line from (3), use a string stream to break the line into the comma separated values.
Test the id value against the input from (1). If the same, report the result and break the loop; you're done.
The result is something like this:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdlib>
int main()
{
std::cout<<"please enter a pokemon number: ";
long num;
if (std::cin >> num && num > 0)
{
std::ifstream ip("pokedex.csv");
std::string line;
while (std::getline(ip, line))
{
std::istringstream iss(line);
std::string id, name, skill;
if (std::getline(iss, id, ',') &&
std::getline(iss, name, ',') &&
std::getline(iss, skill))
{
char *endp = nullptr;
long n = std::strtol(id.c_str(), &endp, 10);
if (id.c_str() != endp && n == num)
{
std::cout << "The pokemon that is: " << num << " is called: " << name << '\n';
break;
}
}
}
}
}
Admittedly untested, but it should work.
Whether you want to store the items in arrays at this point is entirely up to you, but it isn't needed to solve the somewhat abstract problem you seem to be attempting, namely finding the matching line and reporting the name from said-same. If you still want to store them in arrays, I suggest you craft a structure to do so, something like:
struct Pokemon
{
int id;
std::string name;
std::string skill;
};
and have a single array of those, rather than three arbitrary arrays that must be kept in sync.
Four issues jump out at me:
You store the user's input into pokemonType, but then also use pokemonType for reading data from your CSV file. The file input is going to overwrite the user input.
Your file input loop always references index 0. All of the lines from your data file are going into element 0. That's the main reason that even if the user inputs 1, the output is from the last line of the data file.
Your file reading loop is structured like you want to put one part of each data line into a different array, but what you've written actually reads three lines on every iteration, storing those lines into the three different arrays.
This isn't affecting your output, but the code ifstream close("pokedex.csv"); is written like you want to close the file stream you opened, but I do believe what this line actually does is create a new ifstream called close, and opens pokedex.csv attached to it. In other words, it's just like your other line ifstream ip("pokedex.csv"); but with close as the variable name instead of ip.
You are going to want to look into something called "string tokenization". Start with some web searches, apply what you read about to your code, and of course if you hit another snag, post a new question here to Stack Overflow, showing (as you did here) what you tried and in what way it isn't working.
Elaborating on #3, here's what how your data file is being read:
at the end of the 1st iteration of the file-reading loop, ...
pokedexnum[0] is "1,Bulbasaur,grass"
pokemonName[0] is "2,Ivysaur, grass"
pokemonType[0] is "3,Venusaur, grass"
at the end of the 2nd iteration of the file-reading loop, ...
pokedexnum[0] is "4,Charmander, fire"
pokemonName[0] is "5,Charmeleon, fire"
pokemonType[0] is "6,Charizard, fire"
at the end of the 3rd iteration of the file-reading loop, ...
pokedexnum[0] is "7,Squirtle, water"
pokemonName[0] is "8,Wartortle, water"
pokemonType[0] is "9,Blastoise, water"
And that's why
<< "is the pokemon called:"<< pokemonName[0];
outputs
is the pokemon called:8,Wartortle, water

file only saves one time data when use in loop

I have made a code in which data is taken from one whole file and only part of it is stored in the other file. But when I put it in loop it does not work has it should and I am having trouble locating the error can someone guide me where I am doing mistake.
Here is the things what my below written code does:
Takes user name from the user and creates the user name file then asks user if he wants to choice how many books from English book shelf he wants to choice.
NOW THE ERROR:
it does not take multiple inputs if user press 2 it only takes 1 input and copies one book no name to user file but does not do it for the next time
I MAY HAVE SOME CLUE MAYBE:
I think it maybe the get-line in using in the code, which may not be working for the second time the loop executes.
I have tried modifying my code in mostly each possible way I could, but I think may be I'm still new to programming field. So my logical thinking may be not so good. That is why I need little guidance only.
#include <fstream>
#include <iostream>
#include <cstring>
using namespace std;
string user;
int main()
{
cout<<"enter your name to create your Libaray file for book record\n";
getline(cin,user);
ofstream outFile(user.c_str(),ios::app); //user named file
string line;
ifstream inFile("English_book_shelf.txt"); //file with books name and
//number(labels)
int count,c;
cout<<"How many books do you want to buy?\n";
cin>>c;
for(int j=0;j<c;j++)
{
cout<<"Enter your choices:\n";
cin>>count;
while(count)
{
getline(inFile, line);
if (--count == 0)
{
outFile << line <<endl;
break;
}
}
}
}
I want my code to take multiple input from the user and store it in the user file.
Like if he want 3 books, the code should run copy 3 books from the book shelf file and copy it in the user file.
If he want 5 books, the code should run copy 5 books from the book shelf file and copy it in the user file and so own.
The line
if (--count == 0)
is the culprit. Simplify your code and you won't have to worry about such silly errors.
while(count >= 0)
{
getline(inFile, line);
outFile << line <<endl;
--count;
}

Compare Two pointer Arrays One of them from .h and one of them from cin

I am newbie.
I have got a school project that there is a header file and it has got 82 usernames. Like
char *usernames[] ={a1,a2,a3,.... a82};
char *passwords[] =[p1,p2,...p82);
And I have finished large amount of my project but still I couldn't write an usefull code for login stage.
My code has to do take username and then asking for password.
For this stage I think basicly that loop:
char *usernamecheck;
char *passwordcheck;
cout<<"Please login. \n Username\n ";
cin >> usernamecheck ;
for(int flag=0;flag<82;flag++)
{
if(usernamecheck==usernames[a]){
passwordcheck==password[a];
}
else {
}
}
cout<<"Please enter your password\n";
....
Then I will compare password taken from user and from header file.
I want to ask that point we didn't see that point on course. I have no idea how can I compare 2 char pointers. I tried to use as string but I have failed.
This:
char *usernamecheck;
...
cin >> usernamecheck ;
is going to be undefined behaviour. There is no memory associated with usernamecheck. You say:
I tried to use as string but i have failed.
So dont use old archaic, methods when there are shiny new c++ ones available:
std::string usernamecheck;
...
cin >> usernamecheck;
bool isUser = usernamecheck == username;
Done.
use std::string, its the bomb.
Live example.

Store Input from Text File into Arrays or Variables?

My Problem:
I am very new to new to programming and trying to write a program in C++, I have a text file. *In the text file is stored is a Students Name, Grade, and Grade Letter. I want them stored as different types in arrays *
I want to store them individually in an array....
ie text file would look like this:
Jill Hamming A 96
Steven Jenning A 94
Tim Sutton B 89
Dillon Crass C 76
Sammy Salsa D 54
Karen Poulk D 49
I would like to store all the First names in one array, last names in another etc. So on and so on.
These arrays will later be assigned to object for the student. There maybe up to 500 students.
So the question:
How to store input from a text document into an array instead of using 500 variables.
ie. Here is my attempt.
int main()
{
/// the input is all different types, strings, ints and chars
string my_First_Name[500], my_Last_Name[500];
int my_grade[500];
char my_letter[500];
ifstream myfile("input.txt");
if (myfile.is_open()){
for (int i = 0; i < 500; i++) {
myfile >> my_First_Name[i] >> my_Last_Name[i] >> my_grade[i] >> my_letter[i];
}
// much later and irrelevent part but just showing because this is what I want to do. where Student Class exsists somewhere else. yet to be programmed.
Student myStudent [500];
myStudent[i].Grades = my_grade[i];
myStudent[i].LetterGrade = my_letter[i];
}
myfile.close();
//Exit
system("pause");
return 0;
}
When I went to print out what I had. I had all negative and weird numbers which means it was not initialized. Where did I go wrong?
When you have multiple arrays of the same size, it is usually as sign of poor design.
The rule of thumb is to have a record (or line of data) represented by a class or structure:
struct Record
{
string first_name;
string last_name;
int grade_value; // Can this go negative?
string grade_text;
};
If you know you are going to have 500, you can create an array for the data:
#define ARRAY_CAPACITY (500)
Record grades[ARRAY_CAPACITY];
This not a great solution, because you waste space if there are less than 500 and perform buffer overrun if you read more than 500.
Thus a better solution is to use std::vector, which allows you to append records as you read them. The std::vector will expand as necessary to contain the records. With an array, you would have to allocate a new array, copy old records to new array, then delete the old array.
Also, a good solution will include methods, inside Record, to read the data members from an input stream. Research "overloading stream extraction operator".
You input loop should look something like:
Record r;
while (input_file >> r)
{
student_grades.push_back(r);
}
You can find this information by searching stackoverflow. A good beginning search is "stackoverflow c++ read file space separated" or "comma separated" or "stackoverflow c++ read file structure".
Reading a record
You could expand the loop to something like this:
std::vector<Record> student_grades;
Record r;
while (input >> r.first_name >> r.last_name >> r.grade_value >> r.grade_text)
{
student_grades.push_back(r);
}
If you are allergic or limited to arrays, you will need to use a counter with the array.
#define MAXIMUM_RECORDS (500)
Record r;
Record grade_book[MAXIMUM_RECORDS];
unsigned int record_count = 0U;
while (input >> r.first_name >> r.last_name >> r.grade_value >> r.grade_text)
{
grade_book[record_count] = r;
++record_count;
if (record_count >= MAXIMUM_RECORDS)
{
break;
}
}
A for loop is not used because we don't know how many records are in the file, only a maximum that the program will read. If the file has 600 records, only 500 will be read.

Arrays of Structures and External Files in C++

poSo, I've made some progress with a question I asked earlier, but I have one more question. I'll copy and paste the description of the assignment from my earlier question: So I'm working on a homework assignment for my CS162 class which requires me to make a program that allows the user to input their class plan for college. The user inputs classes they have taken, are currently taken, and/or plan on taking, with the categories of: department/class number, class name, term/year, whether or not the class is required for their major, and any additional comments. Then, the program is supposed to store this invermation with external data files so that the classes are stored and won't be lost. The program should be able to store up to 60 classes in memory.
Now, I've set up everything correctly (I believe) with my arrays of structures; but what I'm still struggling with is the reading of this information into an external file to be stored. Here's what I have so far:
struct college_class
{
string dept_classnumber;
string class_name;
string term_year;
string is_required;
string comments;
string grade;
}
college_class myCollegeClass[60];
int main()
{
int i=0;'
char again='y';
while(again != 'n' && again != 'N' && i<60)
{
cout<<"Enter department and class number (e.g. "CS162"): ";
getline (cin,my CollegeClass[n].dept_classnumber);
cout<<"Enter class name (e.g. "Intro to Computer Science"): ";
getline (cin,myCollegeClass[n].class_name);
cout<<"Enter the term and year the class was/will be taken: ";
getline (cin, myCollegeClass[n].term_year;
cout<<"Enter whether or not this class is required for your major: ";
getline (cin,myCollegeClass[n].is_required);
cout<<"Enter any additional comments here: ";
getline (cin, myCollegeClass[n].comments);
cout<<"Would you like to enter another class?(y/n)";
cin>>again;
i++;
}
ofstream myfile("classes");
if(myfile.is_open())
{
/*I know that I need to loop through my myCollegeClass here, but I'm not sure how to do it*/
{
myfile<<myCollegeClass[i].dept_classnumber;
myfile<<myCollegeClass[i].class_name;
myfile<<myCollegeClass[i].term_year;
myfile<<myCollegeClass[i].is_required;
myfile<<myCollegeClass[i].comments;
}
}
else cout<<"Unable to open file";
return 0;
}
Can anyone help me with the external file aspect of this? Thanks so much for the help (in advance)
First of all you need to change your variable from n which doesn't apper anywhere to i in your while loop.
From this:
getline (cin,my CollegeClass[n].dept_classnumber);
to this:
getline (cin,my CollegeClass[i].dept_classnumber);
Secondly add a for loop to save every class. The loop should look like this:
for(int j=0;j<i;++j){
myfile<<myCollegeClass[j].dept_classnumber<<endl;
myfile<<myCollegeClass[j].class_name<<endl;
myfile<<myCollegeClass[j].term_year<<endl;
myfile<<myCollegeClass[j].is_required<<endl;
myfile<<myCollegeClass[j].comments<<endl;
}
Don't forget to close the file with:
myfile.close();
Futhermore you should name your variable with names that say for what purpose they are used.
Here you can change i to numberOfClasses it woudl look much better.