How to fix output? - c++

So basically all this program does is read in the data into the array of structs of student_type and all the print_students functions does is output the data i get mostly the correct output but i also get random huge numbers.The file data contains the following info and my code is below how do i fix my output?
Smith
John
123456
3.4
J
1750.4
302
Fairmont St NW
Washington
DC
20059
Smitty
Frank
78910
2.7
F
1940.7
302
Sixth St SW
Washington
DC
20059
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct Address_type
{
int street_no;
string street_name;
string city;
string state;
int zip;
};
struct student_type
{
string lname;
string fname;
int ID;
float GPA;
char classification;
float account_balance;
Address_type student_address;
};
void print_students(student_type[]); // prototypein
int main()
{
ifstream myfile;
student_type students[5];
myfile.open("infile.txt");
string name1, name2, name3;
for (int i = 0; i < 2; i++) {
myfile >> students[i].lname;
myfile >> students[i].fname;
myfile >> students[i].ID;
myfile >> students[i].GPA;
myfile >> students[i].classification;
myfile >> students[i].account_balance;
myfile >> students[i].student_address.street_no;
myfile >> name1 >> name2 >> name3;
students[i].student_address.street_name = name1 + " " + name2 + " " + name3;
myfile >> students[i].student_address.city;
myfile >> students[i].student_address.state;
myfile >> students[i].student_address.zip;
print_students(students);
}
myfile.close();
}
void print_students(student_type students[])
{
for (int i = 0; i < 2; i++) {
cout << students[i].lname << endl;;
cout<< students[i].fname<<endl;
cout<< students[i].ID<<endl;
cout<< students[i].GPA<<endl;
cout<< students[i].classification<<endl;
cout<< students[i].account_balance<<endl;
cout<< students[i].student_address.street_no<<endl;
cout<<students[i].student_address.street_name<<endl;
cout << students[i].student_address.city << endl;
cout << students[i].student_address.state << endl;
cout << students[i].student_address.zip << endl;
}
}

It looks like you're printing all of your student data on the first iteration of the loop. You should hold off until you've loaded all your data.
Additionally, in C++ it's important to use the Standard Library containers and do your best to avoid C-style fixed-length arrays in situations like this where you're reading in from a file of unknown length.
That is use this:
std::vector<student_type> students;
This can be added to with things like push_back on a properly composed student_type record.
Then you can pass that through by reference to any function that needs it, like print_students for example. Right now, for whatever reason, you just assume that there will be three entries in that array (of length five?) and go ahead and dump it out even if it wasn't populated.

Related

How to extract certain numbers from a text file that also contains letters in C++?

I am trying to figure out how to extract values from a text file as a type double so that they can be used in calculations.
I have a text file that is formatted like:
parameter1 parameter2 parameter3
50 0 0.1
And I want to extract only the numbers.
This is one of my attempts (I have been working for hours trying to figure out how to do this).
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
const int MAX = 80;
char buffer[MAX];
string input;
double j;
ifstream param0;
param0.open("param0.txt");
char ch;
while (param0)
{
param0.get(ch);
cout << ch;
}
getline(param0, input);
param0 >> j;
while (param0)
{
cout << j << endl;
getline(param0, input);
param0 >> j;
}
return 0;
}
this code
char ch;
while (param0)
{
param0.get(ch);
cout << ch;
}
runs to the end of the file. All reads after it will return nothing. Either take this loop out or rewind the file param0.rewind()
The basic idea of the code should be:
std::string line;
double p1, p2, p3;
std::string more;
while (std::getline(in, line)) {
std::istringstream iss{line};
if (iss >> p1 >> p2 >> p3 && !(iss >> more)) {
std::printf("p1=%f, p2=%f, p3=%f\n", p1, p2, p3);
} else {
std::printf("invalid line: %s\n", line.c_str());
}
}
In plain words, the code says: a line is valid if it contains three numbers and nothing more.
C++ purists will say that I shouldn't use printf in C++, but I like the separation between formatting and the actual data.
suggestion :
best to check if you open the file correctly.
close the file once you finish with it.
you can just use the >> operator if you reading everything in one line. It doesn't matter if its string or double as long as if you pass the correct storage variable;
string param1;
string param2;
string param3;
double j,k,l;
ifstream file("test.txt",std::ios::in);
if (!file.is_open())
std::cout << "failed to open " << endl;
while (file)
{
file >> param1 >> param2 >>param3; // getting as strings
cout << param1 <<", "<< param2<<", "<< param3<<endl;
file >> j >> k >> l; //getting as doubles
cout << j <<", " << k <<", " << l<<endl;
}
file.close();
return 0;
output
parameter1, parameter2, parameter3
50, 0, 0.1

What is a good way to read in and separate information from this text file?

Let's say I have a text file:
83 71 69 97Joines, William B.
100 85 88 85Henry, Jackson Q.
And I want to store each number in an array of ints, and each full-name into an array of strings (a full name would be Joines, William B for example).
What would be the best way, because I debated whether using while (inputFile >> line) or while (getline(inputFile, line)) would be better. I don't know if it would be easier to read them one word at a time or read them one line at a time. My main problem will be splitting the 97Joines, William B. to 97 and Joines, William B. which I don't understand how to do in C++.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
int counter = 0;
int scores[40];
string names[10];
string filename, line;
ifstream inputFile;
cout << "Please enter the location of the file:\n";
cin >> filename;
inputFile.open(filename);
while (inputFile >> line) {
// if line is numeric values only, do scores[counter] = line;
// if it is alphabet characters only, do names[counter] = line;
//if it is both, find a way to split it // <----- need help figuring out how to do this!
}
inputFile.close();
}
You need to #include <cstdlib> for strtol I am sure there are better ways to do this but this is the only way I know and this is only for 97joines, and 85Henry,
string word; // to get joines,
string str; // for 97
string numword;
inputFile >> numword;
for(int k = 0; k < numword.length(); k++)
{
if(isdigit(numword[k]))
{
str = str + numword[k];
}
else
{
word = word + numword[k];
}
}
int num = strtol(str.c_str(), NULL, 0);
You can, given the file structure you have shown, read it like this:
int a, b, c, d;
std::string name;
for (int i = 0; i < 2; ++i)
{
// read the numbers
inputFile >> a >> b >> c >> d;
// read the name
std::getline(inputFile, name);
// do stuff with the data... we just print it now
std::cout << a << " " << b << " " << c << " " << d << " " << name << std::endl;
}
Since the numbers are space separated it is easy to just use the stream operator. Furthermore, since the name is the last part we can just use std::getline which will read the rest of the line and store it in the variable name.
You can try it here, using std::cin.

What does "no match for 'operator >>'" mean in my code?

I'm trying to look for what is wrong in this fragment of code. It says the error : [Error] no match for 'operator>>' in 'inputData >> Player[i].AthleteType::firstName' for the line:
inputData >> Player[i].firstName;
Can someone tell me what this means? And also if this is the right way to read data from a file that looks like this:
Peter Gab 2653 Kenya 127
Usian Bolt 6534 Jamaica 128
Other Name 2973 Bangladesh -1
Bla Bla 5182 India 129
Some Name 7612 London -1
//this is the structure
struct AthleteType
{
string firstName[SIZE];
string lastName[SIZE];
int athleteNumber[SIZE];
string country[SIZE];
int athleteTime[SIZE];
};
void readInput(int SIZE)
{
AthleteType Player[SIZE];
ifstream inputData("Athlete info.txt");
int noOfRecords=0;
for (int i=0; i < SIZE; i++, noOfRecords++)
{
inputData >> Player[i].firstName;
inputData >> Player[i].lastName;
inputData >> Player[i].athleteNumber;
inputData >> Player[i].country;
inputData >> Player[i].athleteTime;
}
for (int i=0; i < noOfRecords; i++)
{
cout << "First Name: " << Player[i].firstName << endl;
cout << "Last Name: " << Player[i].lastName << endl;
cout << "Athlete Number: " << Player[i].athleteNumber << endl;
cout << "Country: " << Player[i].country << endl;
cout << "Athlete Time: " << Player[i].athleteTime << endl;
cout << endl;
}
}
There are several problems with your attempt. Firstly your struct
struct AthleteType {
string firstName[SIZE];
string lastName[SIZE];
int athleteNumber[SIZE];
string country[SIZE];
int athleteTime[SIZE];
};
Your compiler error is telling you that you can't read into an array of strings, inputData >> firstName[SIZE];. One string at a time is fine of course.
If i peer into my crystal ball, I see that you want to store several athletes. This should be done using a vector.
vector<Athlete> athletes;
And the struct can then be
struct Athlete
{
string firstName;
string lastName;
int athleteNumber;
string country;
int athleteTime;
};
One athlete per object.
When reading from an input file you want to read based on read success.
while(inputData >> athlete){
athletes.push_back(athlete);
}
You can do this by overloading operator>> (istream&, Athlete& ); or you can write a function that does a similar job.
istream& readAthlete(istream& in, Athlete& at){
return in >> at.firstName >> at.lastName >> at.athleteNumber >> ... and so on;
}
Now the read function can be written as
vector<Athlete> readInput(string filename){
vector<Athlete> athletes;
ifstream inputData(filename);
Athlete athlete;
while(readAthlete(inputData, athlete)){
athletes.push_back(athlete);
}
return athletes;
}
This is not tested code, it might work, it might not work, but it should give you a reasonable path forward.

Code outputs nonsense to output file instead of string?

The following code is for a project I have to do where I recieve a text file that has a students first and last name followed by his grades. I then have to convert that into an output file that contains his name followed by his average score. The file I recieve has multiple students in it spereated line by line. The output should look relativly like
Rzam, Look = 0.00
Bambi, Lambi = 40.47
Coop, Jason = 27.31
but mine is merely printing garbage such as
0x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.00
Here is what I have so far:
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
using namespace std;
struct Student
{
string fname;
string lname;
double average;
};
int read(ifstream &fin, Student s[]);
void print(ofstream &fout, Student s[], int amount);
int main()
{
const int size = 10;
ifstream fin;
ofstream fout;
string inputFile;
string outputFile;
Student s[size];
cout << "Enter input filename: ";
cin >> inputFile;
cout << "Enter output filename: ";
cin >> outputFile;
cout << endl;
fin.open(inputFile.c_str());
fout.open(outputFile.c_str());
read(fin , s);
print(fout, s, size);
fin.close();
fout.close();
}
int read(ifstream &fin, Student s[])
{
string line;
string firstName;
string lastName;
double score;
double total;
int i=0;
int totalStudents=0;
Student stu;
while(getline(fin, line)){
istringstream sin;
sin.str(line);
while(sin >> firstName >> lastName){
stu.fname = firstName;
stu.lname = lastName;
while(sin >> score){
total *= score;
i++;
}
stu.average = (total/i);
}
s[totalStudents]=stu;
totalStudents++;
}
return totalStudents;
}
void print(ofstream &fout, Student s[], int amount)
{
ostringstream sout;
for(int i = 0; i<amount; i++)
{
sout << left << setw(20) << s[i].lname << ", " << s[i].fname;
fout << sout << setprecision(2) << fixed << "= " << s[i].average;
}
}
You have a few bugs, which have added up to your issue:
in your print function, you write to a ostringstream and then try to write that to the file stream. Which is fine, but it is printing the address of the ostringstream buffer. So making this change will cause it to print the contents:
fout << sout.str() << setprecision(2) << fixed << "= " << s[i].average;
Note the usage of .str(). Though you don't really need a temporary stream here at all...
You don't place a newline in the output, so it all ends up one line making it hard to read:
so make another change making it look like this:
fout << sout.str() << setprecision(2) << fixed << "= " << s[i].average << '\n';
You need to place the ostringstream sout; inside the loop, so it is reset each time too. Otherwise you will get weirdly compounding output.
You don't use the count of students calculated by your read function! so it always tries to print 10! Do something like this:
int count = read(fin , s);
print(fout, s, count);
If no score is read, I think you'll have a divide by zero. So you should add a check.
You should ensure that no more than size Students are read. Or better yet, just place them in a std::vector and return that from the function. It's simpler and less error prone.
You need to reset i each time you start reading a student, or the later students will get divided by way too much. Each needs to have an independent count.
I don't know if these are the only issues, but certainly it should get you started on the right track :-)

how can I change a file content in c++?

I have this program that changes negative numbers to positive in my file.
It works, but negative numbers in the file don't change.
for example, if I have this numbers in my file : 12 2 -3 -1
when I run the program, the sum of numbers will be 18, but when I open my file again, I see
12 2 -3 -1 . What should I do to see 12 2 3 1 ?
here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string name;
cin >> name;
int number;
int num=0;
ifstream myFile(name, ios::in);
ofstream mine(name, ios::app);
while(myFile >> number)
{
num += (number<0 ? -number : number);
mine << num;
}
cout << "num = " << num << endl;
system("pause");
return 0;
}
Opening the file for reading and writing for the same time is generally not a bad idea. You probably got an I/O error during opening mine, but since you didn't check it, the program ignored your writes silently. Try reading the file contents first (to a vector for example), then close the file for reading and open again for writing (not appending, because that would leave the old contents in the file).
When writing the values back to the file, also write whitespace after the number, otherwise you'll just get a string of digits in the file but you won't know where one begins and another ends.
Your program now doesn't "change negative numbers to positive" but it prints the cumulative sum of absolute values to the file.
Try writing to the standard output first so you won't ruin your file while you are testing. If it works, then change cout to your output stream.
Here is the code.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
using namespace std;
int main()
{
string name;
cin >> name;
int number;
int num=0;
ifstream myFile(name, ios::in);
vector<int> vec;
while(myFile >> number)
{
vec.push_back(abs(number));
}
ofstream mine(name, ios::out);
for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
num += *it;
mine << *it << " ";
}
cout << "num = " << num << endl;
return 0;
}
Opening a read and write file streams for the same file and process at the same time is inviting file corruption. Use ostringstream to store the values read from the file. The values
from the file are read, and the values stored in the ostringstream
buffer. The ifstream object is closed before re-opening the file with
an ofstream object so that the buffer contents can be saved.
Note the ios::app flag has been removed. Otherwise the new values
will append to the existing values.
abs() function is used to write back the absolute values - this
forces all values positive.
#include<sstream>
int main()
{
string name;
cin >> name;
int number;
int num=0;
ifstream myfile(name.c_str(), ios::in);
ostringstream oss;
while (myfile >> number)
{
num += (number<0 ? -number : number);
oss << abs(number) << " ";
}
myfile.close();
ofstream mine(name.c_str());
cout << "num = " << num << endl;
mine << oss.str();
return 0;
}
string name;
cin >> name;
int number=0;
int sum=0;
string outname=name+".pos.txt";
ifstream myFile(name,ifstream::in);
ofstream mine(outname, ofstream::out );
while(myFile >> number)
{
number= (number<0 ? -number : number);
sum+=number;
mine << number<<' ';
}
myFile.close();
mine.close();
cout << "sum = " << sum << endl;
system("pause");