Reading text files c++ - c++

i am new to c++ and i'm try to write a code that reads integers of a text file and saves each integer in different variables line by line.
I am having problems with the syntax and how to arrange the code. Basically the text file contains 4 integers per line which values are to be read to the a class planet's coordinates and id as shown below. I know the code beloe is incomplete but this is the first time im programming with c++ and need help. please you do not need to explain this using planets or anything. I just need a general understanding
#include <iostream>
#include <fstream>
using namespace std;
class planet{
public :
float x_coordinates;
float y_coordinates;
float z_coordinates;
int id;
};
planet*generate_planet(istream &fin)
{
planet *x= new planet;
fin >> x->id >> x->x_coordinates >> x->y_coordinates >> x->z_coordinates;
return (x);
}
void report_planet( planet &p)
{
cout<<"planet "<<p.id<<" has coordinates (" << p.x_coordinates<<","<< p.y_coordinates<<","<< p.z_coordinates<<")"<<endl;
}
int main()
{
planet p;
planet *x;
ifstream fin("route.txt");
generate_planet(fin);
report_planet(*x);
return 0;
}

You have some errors in your code.
Note that in this line:
fin>>x->id>>x->x_coordinates>>x->y_coordinates>>x->y_coordinates; You write twice to x->y_coordinate instead of x->z_coordinate.
Also, your void report_planet(planet &p) function receives planet & as argument, but you pass it fin which is of time ofstream
Another thing is you're trying to read a file, not write to one, hence the use of ofstream is wrong, you should use ifstream instead.
Does your code even compile?
Good luck.

Related

having a funtion store a string that it makes lowercase and returns it for later use in C++

Ok, i have a program I'm trying to make and the basic thing is to keep me from rewriting the same long 4 lines of code over and over throughout the project, I'm wanting to see if i can get it to take a string from cin and make the whole string lowercase (I'm aware of the transform method, but this is so i don't have to write really length if statements) and return that string to be used as a variable in other parts of the program or other functions.
I don't know if I'd just have to make the function's return the variable itself in the main block or what. I'm pretty new to c++ and coding in general, if its possible id like to include spaces, in the string. Again I'm not too experienced in c++ yet so id like to know if its even possible and if so the best way to do it.
here is what i have so far
int loAns() {
string lAnswer; //Makes the lAnswer, a string used for a long answer that a char wouldn't do properly
cin >> lAnswer; //User enters it
// using transform() function and ::tolower
transform(lAnswer.begin(), lAnswer.end(), lAnswer.begin(), ::tolower); //The transform and ::tolower to make it uniform
cout << lAnswer << endl; //Outputs the lAnswer to console
return 0; //This is where I'm assuming the variable gets put to be used in the rest of the program
}
Your interpretation is correct. Essentially, a function is declared as such:
type name ( parameter1, parameter2, ...)
{
//statements
return <var>;
}
The type is for returning variables back to other programs. In this case, you want to return a std::string, so you function could be like this:
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
string loAns()
{
string lAnswer;
cin >> lAnswer;
transform(lAnswer.begin(), lAnswer.end(), lAnswer.begin(), ::tolower);
return lAnswer;
}
int main()
{
string s = loAns();
cout << s;
}
Result :
xYZabC123
xyzabc123
If you wanted spaces in your string, it's possible to use getline():
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
string loAns()
{
string lAnswer;
getline(cin, lAnswer);
transform(lAnswer.begin(), lAnswer.end(), lAnswer.begin(), ::tolower);
return lAnswer;
}
int main()
{
string s = loAns();
cout << s;
}
Result :
ABc XYZ 123&A
abc xyz 123&a
More info:
Functions : https://en.cppreference.com/w/cpp/language/functions
return : https://en.cppreference.com/w/cpp/language/return
getline() : https://en.cppreference.com/w/cpp/string/basic_string/getline
Ran on Code::Blocks 20.03, Windows 10 64-bit
Also, as #David C. Rankin mentioned below, using namespace std; is not considered a good practice.

Cin can't take input [duplicate]

This question already has answers here:
How to set cin to a member function of a class in C++?
(3 answers)
Closed 2 years ago.
This is my first time using classes and I'm writing a simple program that will take a certain roman numeral and print out the numerical equivalent. However, I'm struggling to code my user input, my cin >> romanObject.getRomanNumeral(); isn't working. I get error E0349 saying no operator ">>" matches these operands. However, when I used just a simple char variable declared in my main function instead it worked fine. Why doesn't my variable in my class work?
#include <iostream>
#include <string>
using namespace std;
class romanType {
public:
void setRomanNumeral(string x) {
romanNumeral = x;
}
string getRomanNumeral() {
return romanNumeral;
}
private:
string romanNumeral;
};
void store();
int main()
{
store();
return 0;
}
void store() // Takes user input.
{
romanType romanObject;
romanObject.setRomanNumeral("Blank");
cout << "Enter one of the following roman numerals" << endl;
cout << "I, V, X, L, C, D, M." << endl;
cin >> romanObject.getRomanNumeral();
}
Why doesn't my variable in my class work?
It works just fine, except that you're not returning it. When you are returning something by value, you are essentially making a temporary copy of the variable. Of course, you can return it by reference:
string &getRomanNumeral() {
return romanNumeral;
}
However, that doesn't really make much sense, since you no longer need setRomanNumberal(), you can simply use getRomanNumberal():
romanObject.getRomanNumeral()="hello world";
The detail that you missed that setting the value of your class member is a part of initializing it by reading its value from std::cin. After you read the string, what do you need to do? You need to set it, so why do you want to use something called getRomanNumeral()? That doesn't make much sense, doesn't that?
So, really, your original approach was the correct one, something along the lines of:
string s;
cin >> s;
romanObject.setRomanNumeral(s);
You're getting the variable, from cin, and you're setting it in your object; you're not getting the existing value of this variable in your object, at any point.

c++ weird characters appear while writing to a file

When i run this code, and open the .dat file in notepad/wordpad it shows some weird characters
#include<iostream>
#include<fstream>
using namespace std;
class Student
{
int rollno;
char name[20];
char div[20];
public:
void accept()
{
cout<<"enter rollno"<<endl;
cin>>rollno;
cout<<"Enter name"<<endl;
cin>>name;
cout<<"Enter div"<<endl;
cin>>div;
}
void write_rec()
{
ofstream f;
f.open("Student.dat",ios::binary|ios::app);
Student s;
s.accept();
f.write((char*)&s,sizeof(s));
f.close();
}
void display()
{
ifstream f;
Student s;
f.open("Student.dat",ios::binary|ios::in);
while(f.read((char*)&s,sizeof(s)))
s.show();
f.close();
}
void show()
{
cout<<rollno<<endl;
cout<<name<<endl;
cout<<div<<endl;
}
};
int main()
{
Student s;
s.write_rec();
s.display();
}
The code is getting compiled and run perfectly but when i open the "Student.dat" file it shows some weird characters
This line:
f.write((char*)&s,sizeof(s));
Is writing the raw binary bytes of your Student object into the file. If that's not the behavior you intended, you'll need to do something else, e.g. translate the member fields of your Student object (in particular the rollno variable, which is an int) into ASCII text strings and write those strings into the file instead.
on both places when you open file:
f.open("Student.dat",ios::binary|ios::app);
and:
f.open("Student.dat",ios::binary|ios::in);
you open as binary. try to remove this option.
as you can see here and here, these are platform specific behaviors.
take a look at this example
EDIT:
and, of course, as Jeremy observed, you have to write meaningful text to your file. on this line:
f.write((char*)&s,sizeof(s));
you are actually writing each byte (as (char*)) of your object. if you understand what you're doing, and that's what you want to observe, than ok. but maybe you should compare both outputs, from this method and from Jeremy's suggestion.

arrays of structures and file I/O

//i have two errors in my code
#include <iostream>
#include<iomanip>
#include<fstream>
using namespace std;
struct PLAYER
{
string first_name;
string last_name;
};
void showFile(fstream&, PLAYER&); // line 13
int main()
{
const int MAX=21;
PLAYER array[MAX];
ifstream inputFile;
inputFile.open("PlayerNames.txt",ios::in);
if(inputFile)
{
showFile(inputFile, array); // line 22
}else
cout<<"\n\nError opening file";
inputFile.close();
return 0;
}
void showFile(fstream &file, PLAYER &array )
{
int index=0;
int p_num=1;
string lname, fname;
file>>lname>>fname;
while(!file.eof())
{
// array[index].last_name=
cout<<lname<<" "<<fname;
//array[index].first_name=fname;
//array[index].player_number=p_num;
index++;
p_num++;
file>>lname>>fname;
}
// cout<<"\n"<<index;
//cout<<lname<<" "<<fname;
}
This program worked finally untill i put it in functions.
I have two errors in this program
line 22 error: invalid intialization of reference type std:: fstream
line 13 error: in passing argument 1 of void showFile(std:: fstream&, PLAYER&)
An ifstream can't be converted to an fstream, only an istream.
In the documentation you can see basic_ifstream is derived from basic_istream, not basic_fstream.
Make your function:
void showFile(istream&, PLAYER&);
This is actually better in many ways. For one it's correct (c: But also it means you can test it with any input stream rather than just a file stream. It is more loosely coupled and programs to the more abstract interface.
You function declaration at line 13 shows you are passing 1 PLAYER object, not an array. If you want to stay with arrays, search StackOverflow for "[C++] pass array function".
I highly recommend using std::vector as it has easier syntax when passing to functions.

Classes and files manipulation in C++ [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
I wrote a code that works fine. I just want extra eyes to highlight every thing that should/could be improved. I have to create a student.dat file, and write data (name, age, gpa of each student) given by a user, then close it, and reopen it for reading then, displaying the gpa of students. The Student is a Class object. I just want to check where I am with the notion of OOP (at least with that problem). I am using Dev-C++. The code is below:
#include <iostream>
#include <conio.h>
#include <fstream>
#include <string>
#include <iomanip>
#define W setw
using namespace std;
class Student
{
private:
char name[40];
int age;
double GPA;
public:
Student(){};
void read();
void show(char* ,int ,double );
int writefile(ofstream &OS);
double getgpa(double*, int );
void readfile();
};
void Student::read(void)
{
int nbrSt=0;
cout<<"Please enter the information of the student: "<<endl;
cout<<"'y' to Continue, Ctrl+Z to exit! "<<endl;
cout<<"Name, Age and GPA:\n";
ofstream OS("student.dat", ios::out);
while (cin>>name>>age>>GPA)
{
//writing in the file
writefile(OS);
nbrSt++; //increment the number of students
cout<<"Name, Age and GPA:\n";
}
OS.close();
}
int Student::writefile(ofstream & OS)
{
OS<<'\n'<<W(10)<<name<<W(6)<<age<<W(10)<<GPA;
return 0;
}
void Student::show(char* Name, int Age, double gpa)
{
cout<<'\n'<<W(10)<<Name<<W(6)<<Age<<W(8)<<gpa<<endl;
}
double Student::getgpa(double* allGPA, int nbrgpa)
{
double sum=0;
int i =0;
for ( i=0;i<nbrgpa; i++)
sum+=allGPA[i];
if(nbrgpa>0)
return sum/nbrgpa;
}
void Student::readfile()
{
char Name[30];
int Age;
double aveGPA, gpa;
int nbrgpa=0;
double allGPA[50];
int i=0;
ifstream IS("Student.dat", ios::in);
cout<<"reading from Binary file"<<endl;
if (IS.is_open())
while(IS>>Name>>Age>>gpa)
{
nbrgpa++;
show(Name, Age, gpa);
allGPA[i]=gpa;
i++;
}
IS.close();
aveGPA=getgpa( allGPA, nbrgpa);
cout<<"Average GPA of students: "<<aveGPA<<endl;
}
int main(void)
{
Student S;
S.read();
S.readfile();
return 0;
}
Student(){};
is illegal syntax
Student(){}
is correct.
void Student::read(void)
is badly designed. Student::read should be a method which reads one student. The reading of multiple stduents and the writing of students should be in other functions or methods.
int Student::writefile(ofstream & OS)
should be
int Student::writefile(ostream & OS)
so it works with all kinds of streams (not just file streams). Obviously you should then rename the method. Just call it write for instance.
double Student::getgpa(double* allGPA, int nbrgpa)
should not be a member of Student, it should be a global function.
Your main issue is object-orientated design. You shouldn't just add everything to the Student class without thinking about what you are doing. Methods in the Student class should be about one student, methods that read or write one Student for instance. Everything else should be in global functions (or in other classes if you add a second class to your program).
I just want extra eyes to highlight every thing that should/could be improved.
#define W setw
Don't do that. You may think it makes code using setw look simpler, but other people looking at your code will have to search for what W resolves to.
using namespace std;
Don't declare using namespace std globally. It's not a big problem in small projects, but it makes the code more difficult to reuse.
The interface of your class is non-standard. Consider reading by creating ostream << student operator and reading by creating 'istream >> student'. This respects the rule of least surprise and enables you to (for example) read a sequence of students using iteration.
You need much better function names:
Your read function writes to a file. It would be a big WTF moment for me to see that in production code. Either change the name, or change the functionality.
Your read function is called on a student instance (Student s; s.read();) but it doesn't work on an instance. It in fact transfers/stores a set of records from cin to a file, and sets the instance it is called on, to the last record. If the reading fails half way through the data (i.e. cin>>name>>age>>GPA gets the name correctly but not the age or GPA) it leaves the instance it is called on, in an invalid state.
Consider moving your code from char name[40]; and double* allGPA, int nbrgpa to std::string and std::vector<double> respectively. Using raw data is error-prone and unnecessarily complicated.
There's a lot more to be said, but I think I've given you enough :-).