C++ File Output Garbage - c++

this is giving me a wicked headache and was hoping I could find some help. The program is supposed to read in a program of 19 integers, then output the smallest (2nd integer) and largest (5th integer) to the screen. However, all my results yield garbage.
#include iostream>
#include <fstream>
#include <cstdlib>
using std::ifstream;
using std::ofstream;
using std::cout;
using std::endl;
//the goal of this program is to read in numbers from a file, then output the
//highest number and the lowest number to the screen
int main() {
ifstream fileInput;
int nOne, nTwo, nThree, nFour, nFive, nSix, nSeven, nEight, nNine, nTen, //there are 19 numbers in the file
nEleven, nTwelve, nThirteen, nFourteen, nFifteen, nSixteen, nSeventeen,
nEighteen, nNineteen;
cout << "Opening File" << endl;
fileInput.open("Lab12A.txt"); //the file is opened
if (fileInput.fail())
{
cout << "Input file opening failed. \n"; //the fail check doesnt pop up, so the file has been opened.
exit(1);
}
fileInput >> nOne >> nTwo >> nThree >> nFour >> nFive >> nSix >> nSeven >> nEight
>> nNine >> nTen >> nEleven >> nTwelve >> nThirteen >> nFourteen >> nFifteen //this is where they should be extracted
>> nSixteen >> nSeventeen >> nEighteen >> nNineteen;
cout << "The highest number is " << nTwo << endl;
cout << "The lowest number is " << nFive << endl;
fileInput.close();
system("pause");
return 0;
}

I wished to add only a comment but since I can't do that, I leave it as an answer.
I have copied your file and created a text file to try to reproduce your issue. At first everything went well (No issue at all). But with comment from Daniel Schepler, I changed file encoding to UTF8-BOM (You can do that easily from Notepad++ Encoding menu) and tried again. I got same values you posted. I can't give more explanation to exactly how values are to be interpreted but I wish someone with more experience enlighten us here.

First I wanted to thank everyone who looked at and commented on this I greatly appreciate it, the issue was ultimately pinned down to needing a full path to the .txt file as opposed to the relative path I initially posted. For what ever reason, my compiler couldn't recognize the file without it. Seems like a silly mistake but I'm relatively new to this so those are sure to squeak by. Thanks again everyone!

You can use class std::vector pushing the values then sorting the container and finally print the second and fifth elements:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
int main(){
std::ifstream in("test.txt");
std::vector<int> vecInt;
int value;
while(in >> value)
vecInt.push_back(value);
in.close();
std::sort(vecInt.begin(), vecInt.end());
// second value is at index 1 and fifth value is at index 4
for(auto i(0); i != vecInt.size(); ++i)
if(i == 1 || i == 4)
std::cout << vecInt[i] << std::endl;
std::cout << std::endl << std::endl;
return 0;
}
I am not sure about what you mean with "largest fifth integer".

Related

Is there a way to read one specific row of info from a .txt file?

so im new to c++ and i have a project that i am currently doing in school however im stuck on how to get an entire row of info from a user input selection.
here is what my txt file looks like
1 Home Work 5
2 Work Home 5
3 Home School 6
4 School Home 6
5 Work School 8
6 School Work 8
so basically if they input/ cin option 3 but how do i print and obtain the values in row 3 to display and compute later on?
heres my code
#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdlib.h>
#include <string>
#include <cstdlib>
#include <Windows.h>
#include <cmath>
void bookingmenu();
void confirmedbooking(double calc);
double calc;
using namespace std;
int main()
{
ifstream inFile;
string PUP, Dropoff, others, otherstwo;
double distance = 0, calc;
string ON;
int sel;
char choice;
inFile.open("blist.txt");
if (!inFile)
cout << "Error, unable to open text file.\n" << endl;
else
cout << left << fixed << setprecision(2);//how many dp
cout << left << setw(25) << "Option Number" << left << setw(25) << "Pick Up Point" << "Dropoff Point" << endl; //display column header
while (!inFile.eof())
{
inFile >> ON >> PUP >> Dropoff;
if (inFile.fail()) break;
cout << left << setw(25) << ON << left << setw(25) << PUP << Dropoff << endl;
}
cout << "Please select an option for your trip: ";
cin >> sel;
//(im stuck after here)
cout << "You have selection option number " << ON << " and your pickup point is " << PUP << " and your dropoff point is " << Dropoff << endl;
system("pause");
return 0;
}
Make a list of things you need to do:
read file (almost done)
print options in file (done)
put data somewhere we can look it up later (not done)
get option from user (done)
look up option (not done)
print selected option (almost done)
Fixing point 1
The current code reads three fields from the row of data. There are 4 fields. The fourth field needs to be removed from the stream.
int unused;
while (inFile >> ON >> PUP >> Dropoff >> unused) // read unused field into junk variable
{
//print
}
Implementing point 3
Define a structure that can store the data
struct record
{
string PUP;
string Dropoff;
};
Option number will be likely used as the key for looking up the structure, so it doesn't need to be in the structure.
Next we need a container to store these records
If the file is guaranteed to be start with a predictable option number and be listed in a continuous sequential order, we can use a std::vector to store the records. If the list is predictable, sequentially ordered and of known size we can use std::array If not, use an associative table to map the option number to the record. We're not given any guarantees of ordering or size, so I'll demonstrate with std::map
record in;
map<int, record> records; // convenient data structure for look-up
int ON;
int unused; // need to read and dum that last field on the line
while (inFile >> ON >> in.PUP >> in.Dropoff >> unused)
{
records[ON] = in; // store row in datastructure at the option number.
}
If you're smart, you will read the file and print the menu at the same time. Otherwise you're reading the file twice or unnecessary looping through the container of records.
Implementing point 5
Look up the record in the container. If std::map is used, that can be as simple as
record & out = records.at(sel);
at will throw an exception if the option is not in the list. You can either catch and handle the exception or let the program crash.
Fixing point 6
We use the reference to the record to update the existing code to use the correct record.

How can I add items to the output file?

I am a newbie to C++ and I've got my first assignment. We've got a text file that contains 5 employee names, wages, and hours worked.
And this is my code so that my program could read it.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>
using namespace std;
int main()
{
ifstream input;
ofstream output;
string name;
int h;
float w;
int numEployee = 0;
double maxPay, minPay, avgPay;
int gross, adjGross;
//input/output file document path
input.open("/Users/jmduller/Documents/xcode/Lab1/Lab1/Employees.txt");
output.open("/Users/jmduller/Documents/xcode/Lab1/Lab1/Employeesoutput.txt");
//checks if the input file is working
if (input.fail())
{
cout << "Input file failed to open." << endl;
system("pause");
exit(0);
}
//checks if output file is working
if (output.fail())
{
cout << "Output file failed to open." << endl;
system("pause");
exit(0);
}
//prints the name, wage, hours worked of the employees to the output file
while (input >> name >> w >> h)
{
output << setw(5) << name << setw(5) << w << setw(5) << h << endl;
}
system("pause");
return 0;
}
It's reading it properly and giving me the output file that I want but there are missing items. The complete output file should be have the number of employees, max pay, min pay, avg pay, gross pay, and adjusted gross.
Can anyone help me point to the right direction?
Thanks
What you got to do is use some conditions and statements inside your while loop statement (which is reading from the file). Increment your 'numEmployee' variable everytime the loop executes(counts number of entries).
compare the 'w' read to check if it is lower than than the minPay(initialized to something very large) then update minPay otherwise if higher than maxPay(intialized to the least value possible) update maxPay.
Also, add the 'w' to another variable sumPay(initialized to zero) in loop and at the end divide it by numEmployee and you are done.
Just output them into the file before return statement.

C++ Reading text file with delimiter into struct array

I am trying to read data from a text file formatted similarly to this:
knife, object, 0
bag, object, 15
kitchen, room, 400
Into an array composed of structures. Here is what I have so far, but it only reads the first element then returns garbage.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct itemlist
{
string type;
string selltype;
int price;
int diditsell=0;
};
int main()
{
string filename;
cout << "Please enter a file name. " << endl;
cin >> filename;
ifstream in(filename);
itemlist c[100];
for (int i=0;i<100;i++)
{
in >> c[i].type >> c[i].selltype >> c[i].price;
cout << c[i].type << endl;
cout << c[i].selltype << endl;
cout << c[i].price << endl;
}
}
I have tried to find examples that specifically suit what I am trying to do but implementing them has not fixed the problem. Any help would be greatly appreciated.
The crux of the visible problem is that with
for (int i=0;i<100;i++)
the entire 100 element array will be printed out whether there was data in the file to be loaded into the array or not.
Probably the easiest way to do this is with a std::vector. It's a dynamically sized array. As you add to it it gets bigger so you don't have to worry about it overflowing. We'll get back to it at the end.
The next thing you have to do is make sure you're reading the file successfully. Streams can be tested to see if they are valid.
if (in)
{
cout << "in is good!" << endl;
}
and the >> operator returns a reference to the stream so you can
if (in >> data)
{
cout << "data is good!" << endl;
}
If the stream is still good after reading data, you know that at the very least the file read something into data that was of the correct type or could be converted into the correct type. You owe it to yourself to check the value read after reading it in to make sure the user didn't typo or go out of their way to crash the program. If you want to loop through a lot of stuff, like a file, you wind up with something like this:
while (in >> c[i].type >> c[i].selltype >> c[i].price)
If any of the reads failed the the stream will return false when tested and the loop will exit.
Looking at your source data you have spaces and commas to deal with. >> only knows how to deal with spaces unless you're going to do a lot of extra work. What you will read in is
knife,
object,
0
and we don't want the comma. Fortunately, it's the last character so dealing with it is easy. A C++11 std::string can be used like a stack and you can just pop the unwanted character off:
c[i].type.pop_back();
c[i].selltype.pop_back();
All together, this gives us a loop that looks like
ifstream in(filename);
itemlist c[100];
int i = 0;
while (in >> c[i].type >> c[i].selltype >> c[i].price)
{
c[i].type.pop_back();
c[i].selltype.pop_back();
cout << c[i].type << endl;
cout << c[i].selltype << endl;
cout << c[i].price << endl;
i++;
}
but this can overrun the end of the 100 element array, so we need to change the while loop slightly:
while (i < 100 && in >> c[i].type >> c[i].selltype >> c[i].price )
If i is greater than or equal to 100, the i < 100 case fails and the loop exits without even trying in >> c[i].type >> c[i].selltype >> c[i].price and writing into the non-existent array slot.
Remember to keep the value of i around because arrays are dumb. They don't know how full they are.
But with a vector you don't need i to count or to keep track of how full it is and you don't need to worry about overflowing the array until you run your computer out of RAM. What we do need is one temporary variable to read into and we're good to go.
vector<itemlist> c;
itemlist temp;
while (in >> temp.type >> temp.selltype >> temp.price)
{
temp.type.pop_back();
temp.selltype.pop_back();
cout << temp.type << endl;
cout << temp.selltype << endl;
cout << temp.price << endl;
c.push_back(temp);
}
I had the same problem.
A debug showed that it was reading the first array element but skipping to the second element and outputting the info. from the first element.
This was fixed by making it read the first element twice.
For example see below.
I had other input in the array for the player also.
After that line was added everything worked great.
I had to do that for every array that I read.
I looked at the text file it was reading from and sure enough
there is a blank line before the start of every array.
I do not know why the program writing the file did that.
I did not put a blank line before the array.
Note: Instead of having it read the first array element twice,
you could probably have it read a blank line instead.
for (int i = 0; i < PLAYER; i++)
{
getline(teamRosterIn, playerName[i]);
cout << playerName[i] << endl;
getline(teamRosterIn, playerName[i]);
cout << playerName[i] << endl;
}

Converting string to number when using getline()

I've picked up a book on C++ and I'm basically at the very beginning of it (just started). For some of the problems I had to solve within the book I used the input stream cin the following way -->
cin >> insterVariableNameHere;
But then I did some research and found out the cin can cause a lot of problems, and so found out about the function getline() within the header file sstream.
I'm just having some trouble trying to wrap my head around what's happening in the following code. I don't see anything that uses the extraction operator (>>) to store the number value in. Its (my problem) further explained in the comments I left.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
// Program that allows a user to change the value stored in an element in an array
int main()
{
string input = "";
const int ARRAY_LENGTH = 5;
int MyNumbers[ARRAY_LENGTH] = { 0 };
// WHERE THE CONFUSION STARTS
cout << "Enter index of the element to be changed: ";
int nElementIndex = 0;
while (true) {
getline(cin, input); // Okay so here its extracting data from the input stream cin and storing it in input
stringstream myStream(input); // I have no idea whats happening here, probably where it converts string to number
if (myStream >> nElementIndex) // In no preceding line does it actually extract anything from input and store it in nElementIndex ?
break; // Stops the loop
cout << "Invalid number, try again" << endl;
}
// WHERE THE CONFUSION ENDS
cout << "Enter new value for element " << nElementIndex + 1 << " at index " << nElementIndex << ":";
cin >> MyNumbers[nElementIndex];
cout << "\nThe new value for element " << nElementIndex + 1 << " is " << MyNumbers[nElementIndex] << "\n";
cin.get();
return 0;
}
stringstream myStream(input): Creates a new stream that uses the string in input as "input stream" so to speak.
if(myStream >> nElementIndex) {...): Extracts number from the stringstream created using the line above into nElementIndex and executes ... because the expression returns myStream, which should be non-zero.
You were probably confused by using the extraction as the condition in the if statement. The above should be equivalent to:
myStream>>nElementIndex; // extract nElement Index from myStream
if(myStream)
{
....
}
What you probably wanted was
myStream>>nElementIndex; // extract nElement Index from myStream
if(nElementIndex)
{
....
}

Using Arrays for test results

Okay, so I know that you guys aren't my own personal programmers but I was wondering if you could help me out a bit here. I work as a teachers assistant while I'm going to school. I know a bit of C++ and was trying to make a basic program to check answers with.
The first part of the program works fine to test the answers against the key, however the second part is what I'm having issues with. I'm trying to find how many students answered what question so I don't have to count them by hand, but I cannot seem to get this down.
What I really need is to be able to print them out like so:
question A B C D E
1 1 12 3 5 7
and so on.
I know I'm probably going to need a nested for loop, but I've been banging my head on this all night. Any help would be appreciated.
#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
void main(){
int numstud=0, numcorrect, i;
string key, id, responses;
ifstream keyfin, studfin;
keyfin.open("answers.dat");
studfin.open("tests.dat");
keyfin >> key;
studfin >> id >> responses;
cout << setw(5) << "Student-Id's" << setw(20) << "# Correct" << endl << endl;
while(!studfin.eof())
{
numstud++;
numcorrect=0;
for(i=0; i<20; i++){
if(responses[i] == key[i])
{
numcorrect++;
}
}
cout << id << setw(20) <<numcorrect << endl;
studfin >> id >> responses;
}
studfin >> id >> responses;
int col[20][5]={0}, j=0;
char ch;
studfin >> id >> responses;
cout << "Question" << setw(10) << "A" << setw(5) << "B" << setw(5) << "C" << setw (5) << "D" << setw(5) << "E";
while (!studfin.eof())
{
for(i=0; i<responses.length(); i++)
{
col[i++][responses[i-'a'] ++];
}
}
}
You have the general idea as far as implementing an histogram of the responses. However there are a few things wrong with the line col[i++][responses[i-'a'] ++].
First assuming responses are lower case, you probably intended responses[i]-'a' rather than responses[i-'a'], to convert the letter grade to a 0,1,2,3,4 index.
Then, it's the content of the table you want to increment, not row and column indices. That is col[i][responses[i]-'a']++.
As a side note, you don't need a second while (!studfin.eof()) loop to update the histogram. You can keep updating it as you are checking answers against the key (and you should not use a second loop unless you reset the input stream that has reached end-of-file by the end of the first loop).