file only saves one time data when use in loop - c++

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;
}

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

C++ using a variable from an external file

I am new to C++ but I like it so far.
Recently I have been making better and better builds of a console application that is just like a sign in thing, however you would give the password string and the username string in the same session.
I am trying to make it so that you open the application and checks for a certain file, and if it is not there it will create it and ask you to give it a value. I'm hoping this would make it so that I could have a user created password and username that is already set, rather than a couple of strings that already have a value but are not user created.
My code for my best version (its not great code) also not gonna post all of it just the part where they create the pass.
#include "stdafx.h"
#include "iostream"
#include "string"
#include "windows.h"
using namespace std;
int main() {
string user;
string pass;
string entry;
cout << "Make your username\n";
cin >> user;
cout << "Make your password\n";
cin >> pass;
return 0;
}
There is much more to this code (about 80 lines) but I don't feel like most of that information is needed.
Use std::ifstream to manage the file
std::ifstream f("path_to_file");
if (f.fail()) {
// we can't us the file (doesn't exist, incorrect permissions, etc.)
// instead, ask the user to enter their credentials
} else {
// read the file and extract necessary information
}

Storing Arrays of Structs in external files in 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;

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.

enhancing a program - complete failure

good day everyone.
im having some trouble trying to figure out how to enhance my program.
here's the question:
Write a program to compute numeric grades for a course. The course records are in a file that will serve as the input file. The input file is in exactly the following format: Each line contains a student’s last name, then one space, then the student’s first name, then one space, then ten quiz scores all on one line. The quiz scores are whole numbers and are separated by one space. Your program will take its input from this file and send its output to a second file. The data in the output file will be the same as the data in the input file except that there will be one additional number (of type double) at the end of each line. This number will be the average of the student’s ten quiz scores. If this is being done as a class assignment, obtain the file names from your instructor. Use at least one function that has file streams as all or some of its arguments.
i managed to do the first part successfully. below is the code:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
using namespace std;
int main()
{
fstream infile("grades.txt",ios::in);
if(!infile){cerr<<"file could not be found!";exit(1);}
fstream outfile("average.txt",ios::out);
if(!outfile){cerr<<"file could not be created!";exit(1);}
char fname[20];
char lname[20];
int grades[10];
char c;
int x;
cout<<"how many students?";
cin>>x;
for(int k=0;k<x;k++)
{
infile>>fname;
infile>>lname;
for(int i=0;i<10;i++)
infile>>grades[i];
outfile<<fname<<" "<<lname<<" ";
double sum=0;
for(int j=0;j<10;j++)
{
outfile<<grades[j]<<" ";
sum+=grades[j];
}
double avg=0;
avg=sum/10;
outfile<<avg<<endl;
}
system("pause");
return 0;
}
im not able to do part (a) of the second part. i tried initializing the grades[10] array to zeros, but im not getting any correct output. any help? thank you.
Enhance the program you wrote for (Problem 10) in all the following
ways.
a-The list of quiz scores on each line will contain ten of fewer quiz
scores. (If there are fewer than ten quiz scores, that means
that the student missed one or more quizzes.) The average score is
still the sum of the quiz scores divided by 10. This amounts to
giving the student a 0 for any missed quiz.
b-The output file will contain a line (or lines) at the beginning of
the file explaining the output. Use formatting instructions to
make the layout neat and easy to read. c- After placing the desired
output in an output file, your program will close all files and then
copy the contents of the “output” file to the “input” file so
that the net effect is to change the contents of the input file.
Use at least two functions that have file streams as all or some of
their arguments. If this is being done as a class assignment,
obtain the file names from your instruction.
here's how my code looks now
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
using namespace std;
int main()
{
fstream infile("grades.txt",ios::in);
if(!infile){cerr<<"file could not be found!";exit(1);}
fstream outfile("average.txt",ios::out);
if(!outfile){cerr<<"file could not be created!";exit(1);}
char fname[20];
char lname[20];
int grades;
int sum=0;
int linecount=0;
char c;
while(!infile.eof())
{
infile>>lname;
infile>>fname;
outfile<<lname<<" "<<fname<<" ";
for(int i=0;i<10;i++){if(infile>>grades)outfile<<grades<<" ";else {outfile<<"0 ";break;} sum+=grades;}
outfile<<double(sum/10.0);
}
system("pause");
return 0;
}
but im getting just a black space when i run the program. im not able to fix the loop to read from all the lines of the file.
As of the first part: Your code doesn't exactly solve the problem as given. The problem as given doesn't say you enter a number of students, but you should process all students in the file, no matter how many they are. Also, you neglected the part: "Use at least one function that has file streams as all or some of its arguments."
Anyways, I'd advise you to read the file line by line, and then process each line individually using ostringstream. That way, detecting that no more grades follow works the same way as detecting that no more students follow in part 1.
Hint: Look at the stream error status, especially fail, and use a while loop in part 1, and break in part 2.