finput and stringstream (c++) - c++

We're learning about stringstream and finput in class and I am confused about the values I am getting for this code:
Source Code:
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
using namespace std;
main() {
ifstream finput("input.txt"); // Read File
string line, name; // Declare variable line and name
int value = 0, total = 0, count = 0; // Declare variable value, total, and count
while (!finput.eof()) { // While the end of file has not been reached
getline(finput, line ); // Get the entire first line of the file and set it to line variable
istringstream istr(line); // Convert to parsed string
istr >> name; // first line of str is converted to the name
while (istr >> value) { // while there are remaining integer values to output
total += value; // Add value to total
count++; // add 1 to count
}
cout << name << " " << total << fixed << setprecision(1) << total * 1.0 / count << endl;
}
}
And here is my input file:
Thomas 1
Jack 1 3
Jim 1 2 3
And here is my output:
Thomas 11.0
Jack 51.7
Jim 111.8
Jim 111.8
Process returned 0 (0x0) execution time : 0.016 s
Press any key to continue.
Why am I not getting "Thomas 1", "Jack 2", and "Jim 2"? And why is Jim displaying twice? My professor did not explain very well what exactly stringstream did and how it works.
I would really appreciate the help. Thanks!

1.
You don't initialize the values of total and count so they only grow; declare
int value = 0, total = 0, count = 0;
inside the loop that reads from file.
2.
You don't output space between the printed values; use
cout << name << " " << total << " " << fixed << setprecision(1) << total * 1.0 / count << endl;
when outputting.

Related

Error in code after reading data from file with the help of fstream

While creating a simple stock management system, I encountered some problem after adding a new item in the list. My code will explain better.
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std; // For sake of speed
class INVENTORY
{
char name[10];
int code;
float cost;
public:
void setData();
void getData();
};
void INVENTORY ::setData()
{
std::cout << "Enter Name: ";
std::cin.getline(name, 10);
std::cout << "Enter Code: ";
std::cin >> code;
std::cout << "Enter Cost: ";
std::cin >> cost;
}
void INVENTORY::getData()
{
cout << setiosflags(ios::left) << setw(10) << name << setw(10) << code << setw(5) << cost << '\n';
}
int main()
{
INVENTORY item;
fstream inoutfile;
inoutfile.open("STOCK.DAT", ios::ate | ios::in | ios::out | ios::binary);
inoutfile.seekg(0, ios::beg); // go to beginning.
cout << "CURRENT CONTENTS OF STOCK" << '\n';
while (inoutfile.read((char *)&item, sizeof(item)))
{
item.getData();
}
inoutfile.clear(); // clears the eof state flag.
cout<<'\n'<<inoutfile.good()<<'\n';
/* ADD more items */
cout << "\nAdd an item: \n";
item.setData();
char ch;
cin.get(ch);
inoutfile.write((char *)&item, sizeof(item));
cout<<'\n'<<inoutfile.good()<<'\n';
// Display the appended file
inoutfile.seekg(0);
cout << "CONTENTS OF APPENDED FILE\n";
while (inoutfile.read((char *)&item, sizeof(item)))
{
item.getData();
}
cout<<'\n'<<inoutfile.good()<<'\n';
// Find the number of objects in the file.
int last = inoutfile.tellg();
int n = last / sizeof(item);
cout << "Number of Objects: " << n << endl;
cout << "Total bytes in file: " << last << endl;
/* Modify the details of an item */
cout << "Enter object number to be updated: ";
int object;
cin >> object;
cin.get(ch);
int location = (object - 1) * sizeof(item);
if (inoutfile.eof())
{
inoutfile.clear();
}
inoutfile.seekp(location);
cout << "Enter the new values of objects \n";
item.setData();
cin.get(ch);
inoutfile.write((char *)&item, sizeof item) << flush;
/* SHOW UPDATED FILE */
cout << "Contents of updated file: \n";
while (inoutfile.read((char *)&item, sizeof item))
{
item.getData();
}
inoutfile.close();
return 0;
}
I reused the class from some file, please don't sue me for using namespace std I don't use it usually, but used today for sake of speed.
The 3rd cout<<'\n'<<inoutfile.good()<<'\n'; returns false and I am not able to figure out why this happens. I already have the file STOCK.DAT and there is data already present in it (of the same type). The relevant output:
CURRENT CONTENTS OF STOCK
Apple 5 50
Banana 6 80
1
Add an item:
Enter Name: Pineapple
Enter Code: 8
Enter Cost: 150
1
CONTENTS OF APPENDED FILE
Apple 5 50
Banana 6 80
Pineapple 8 150
0 // something is not good here but what?
Number of Objects: -858993460
Total bytes in file: -1
There are more elements in output but I showed you the relevant output, tellg returns false, so there is definitely something wrong and I can't figure it out.
I will explain what is happening over here:
I made a class named INVENTORY and made a few members and member functions in it.
Then in the main function, I made a fstream object and opened a file named STOCK.DAT, with a few additional flags.
Then I point the get pointer to the beginning (both pointers move together for a fstream object).
The file is in binary so I print out what's already present in the file.
Then I use clear() to remove eof flag and check whether everything is right, which will result true here.
Then I add another item to the end of file and check whether everything is good, true over here also.
Then I set the get pointer to beginning to print all the data in the file again and now everything is not good and I am not able to figure it out.
I found a solution. After reaching eof if you try to do inoutfile.tellg() it will return -1. Instead use inoutfile.clear() to clear the eof tag and then use inoutfile.tellg().

C++ Vector is printing with unexpected result

I am making a random username generator and I am having issues with printing numbers after the randomly selected vector item.
Code:
#include <iostream>
#include <cassert>
#include <vector>
#include <fstream>
using namespace std;
int main () {
// Initialize
srand (time(NULL));
int length = 0, quantity = 0, random = 0;
// Prompt & Introduce user
cout << "Random Username Generator!" << endl;
cout << "Enter word length, 0 for random: ";
cin >> length;
cout << "How many words?: ";
cin >> quantity;
// Read in dictionary textfile
ifstream fin;
fin.open( "CSW_2019.txt" );
assert( fin.is_open() );
// Initialize vector
vector<string> validWords;
string word = "";
// Loop to build validWords vector
while ( !fin.eof() ) {
getline(fin, word);
if ( word.length()-1 == length || length == 0 ) {
validWords.push_back(word);
}
}
// Loop to randomly display words and 1-2 digits following
for ( int i = 0; i < quantity; i++ ) {
// Random in-range value
random = rand() % validWords.size();
// Print random word
cout << validWords[random] << flush;
// Print number between 0 and 99
cout << random % 100 << endl;
}
// Close file because I wasn't raised in a barn
fin.close();
}
Output:
Random Username Generator!
Enter word length, 0 for random: 4
How many words?: 4
92IN
24RE
92PS
31OR
My question is NOT about how to print a c++ vector, because it is simple. My question is seeking understanding for the strange printing output.
Here is an example of output that does not implement the line cout << random % 100 << endl; and changes the above << flush; to << endl; instead.
Output (not implementing numbers):
Random Username Generator!
Enter word length, 0 for random: 4
How many words?: 4
DOLT
RAYS
MOLE
BELT
Any and all help is appreciated, thank you all in advance.

program is misinterpreting input intended to populate entries in an array

How can I get 3 numbers at once from a user in the command prompt so that I can perform a dot-product operation on it with an existing array? For example:
suppose in advance, I define
int myArray[3] = {1,2,3};
Now a user enters natural numbers in the format "i,j,k".
The program spits out
myArray[0]*userArray[0] + myArray[1]*userArray[1] + myArray[2]*userArray[2]
that is,
1*a + 2*b + 3*c
I was able to do exactly this with predefined arrays, easily. However, something is going terribly wrong when I try to identify the user input as pieces of an array. The program thinks the numbers are different or in a different place, or of a different structure, resulting in negative or humongous answers.
[Part of] My program is below. The goal is the same as the example:
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <limits>
#include <tuple>
int main()
{
int nNumCup = 0, nNumLem = 0, nNumSug = 0, nNumIce = 0;
float fCoH = 20.00, fCostCup25 = 1.99, fCostCup50 = 2.49, fCostCup100 = 2.99;
int arrnStoreInput01A[3];
std::cout << "Go to Cups \n \n";
std::cout << "Cups are availible in packs of 25, 50 and 100. \n"
"Please enter three numbers in \"i,j,k\" format for the \n"
"respective amounts of each of the following three products \n"
"you want to buy: \n \n"
"A) 25-pack of cups for " << fCostCup25 << "\n"
"B) 50-pack of cups for " << fCostCup50 << "\n"
"C) 100-pack of cups for " << fCostCup100 << "\n \n"
"For example, type \"0,4,0\" to purchase 4 packages of 50 cups or \n"
"type \"3,2,1\" to buy 3 packages of 25 cups, 2 packages of 50 cups \n"
"and 1 package of 100 cups. \n \n";
//This is where the user inputs "i,j,k". I entered "3,2,1" in the command prompt.
std::cin >> arrnStoreInput01A[0] >> arrnStoreInput01A[1] >> arrnStoreInput01A[2];
float arrnCostCup[3] = { fCostCup25,fCostCup50,fCostCup100 };
float fStoreInput01AdotfCoH = arrnStoreInput01A[0] * arrnCostCup[0]
+ arrnStoreInput01A[1] * arrnCostCup[1]
+ arrnStoreInput01A[2] * arrnCostCup[2];
int arrnQuantCup[3] = { 25,50,100 };
if (fStoreInput01AdotfCoH <= fCoH){
fCoH = fCoH - fStoreInput01AdotfCoH;
nNumCup = nNumCup + arrnStoreInput01A[0] * arrnQuantCup[0]
+ arrnStoreInput01A[1] * arrnQuantCup[1]
+ arrnStoreInput01A[2] * arrnQuantCup[2];
}
else
std::cout << "Not enough cash on hand.";
std::cout << "you have " << nNumCup << " cups! \n";
std::cout << "you have " << fCoH << " left in cash!";
//Inspecting what the program thinks the user-inputed array is
//(next lines) reveals that it is interpreting "3,2,1"
//erroneously as 3 -858993460 -858993460
for (auto const value : arrnStoreInput01A)
{
std::cout << value << ' ';
}
return 0;
}
I am also attaching a picture of the command prompt output because that is very illustrative and arguably easier to interpret (see top of post).
use a for loop to store the user input on the array. When the user finishes, then you do the operation. Something like this:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> userInput ;
std::vector<int> predefinedArray{1,2,3};
for(int i=0;i<3;i++)
{
int tmp;
std::cout<< "Introduce input numer " <<i<<": " ;
std::cin >> tmp;
userInput.push_back(tmp);
}
std::cout<<userInput[0]*predefinedArray[0]+
userInput[1]*predefinedArray[1]+
userInput[2]*predefinedArray[2]<<std::endl;
return 0;
}
I would recomend you to use std::vector as I did on the above code.
Have a look at how operator>> works. It reads integers up to the comma (or anything not an integer). You will have to remove the comma from the input stream to get the next number.
You could use ignore:
std::cin >> arrnStoreInput01A[0];
std::cin.ignore(1,',');
std::cin >> arrnStoreInput01A[1];
std::cin.ignore(1,',');
std::cin >> arrnStoreInput01A[2];

Unhandled Memory Exception

I'm working on a program that reads a set of data based on patient's ID numbers and their blood pressure readings. The program will then add all the readings together and come up with an average. It'll then display that average. This is my program so far:
#include <iostream>
#include <string>
#include <conio.h>
#include <fstream>
using namespace std;
int main()
{
//Initialize Required Variables For Program
int patientCount;
string id;
string rHowMany; //String To Read From File
int howMany;
int howManyCount;
int avg = 0;
int avg2;
string line;
int number_lines = 0;
ifstream reader ("data.txt"); //Open The Data File To Be Read From
patientCount = 0;
while (getline(reader, line))
{
number_lines += 1;
}
//getline(reader, id); //Get the patients ID
//getline(reader, rHowMany); //Get How Many BP Records The Patient Has
for (number_lines; number_lines > 0; number_lines--)
{
reader >> id;
reader >> rHowMany;
howMany = stoi(rHowMany);
howManyCount = howMany;
patientCount += 1;
cout << "Patient ID: " + id;
for (howManyCount; howManyCount > 0; howManyCount--)
{
reader >> avg2;
avg = avg + avg2;
}
}
cout << avg;
cout << "\n";
cout << howMany;
avg = avg / howMany;
cout << "\n";
cout << avg;
_getch();
return 0;
}
When I run the program I get this error:
Unhandled exception at at 0x756DB727 in Blood Pressure.exe: Microsoft C++ exception: std::invalid_argument at memory location 0x0042F794.
I'm not quite sure what that means, but it opens up a list of code I've never seen before. Like I said I'm not sure why it's throwing this error, or what the error means, but if someone could help me, I would appreciate it.
This line:
cout << "Patient ID: " + id;
Is flawed. You are trying to append id to "Patient ID: ", but that is not what is happening.
The string literal "Patient ID: " is actually a pointer to a sequence of characters (that is, an array). When you use the plus sign, you are performing pointer arithmetic between the memory address of the character sequence and id. If id is larger than the length of the string, this will probably lead to your program trying to access an invalid location.
To fix this, simply print id after the sequence by making two separate calls to the << operator:
cout << "Patient ID: " << id; // no +

Use ifstream to read a text file with random generated numbers in columns and find the minimum and maximum from the list?

I am creating a school project but seems lost at the moment. Can someone help me figure out my problem? Here's what's going on:
I have a program that outputs a random generated numbers in a text file using ofstream. It is generated with a format of two columns (one column is SalePrice & the second column RegularPrice). My problem is creating a code that will do the following:
Create a function that will read the text file generated by the first program
Find the average of the second column ONLY! (Regular Price) then outputs it in the screen
Find the minimum and maximum of the second column ONLY! (Regular Price) then outputs it in the screen
Please help! I need help how to code the ifstream part, I am new to C++ and have tried all the solutions in many books but doesn't seem to work for my needs? :-( Any help will be greatly appreciated! Thanks in advance!
Here's just the section of my code (not the entirety), it is not giving me an error . . . it is simply not giving me anything:
float SalePrice[userInput];
float RegularPrice;
string cPrice;
string readFile;
int count = 0;
ifstream inputFile;
inputFile.open(fileName);
inputFile >> RegularPrice;
// To get you all the lines and place the line from myfile into the line variable
while(!inputFile.eof() && getline(inputFile, readFile))
{
if (count < userInput)
{
inputFile >> readFile;
readFile += cPrice; // Saves the line in STRING.
//display the line we gathered:
cout << cPrice << endl;
}
++count;
}
avgRPrice = RegularPrice / userInput;
cout << endl;
cout << fixed << setprecision (2);
cout << "The average of all the Regular Prices in the file is: " << avgRPrice << endl;
cout << "The minimum Regular Price in the file is: " << minRPrice << endl;
cout << "The maximum Regular Price in the file is: " << maxRPrice << endl;
EDITED:
Here's my current code for finding the max & min:
int maxRPrice(float RPrice[])
{
if (RPrice > maxRPrice)
maxRPrice = RPrice;
return maxRPrice;
}
int minRPrice(float RPrice[])
{
if (RPrice < minRPrice)
minRPrice = RPrice;
return minRPrice;
}
Here is an improved version of your code which works perfectly for me:
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
const int userInput = 2;
float SalePrice[userInput]; //Make an array
float RegularPrice[userInput]; //Make an array
string readFile;
ifstream inputFile;
inputFile.open("yourFile.txt");
if(!inputFile){ //Check wether the file is open
cout<<"Couldn't open file!" << endl;
return -1;
}
// To get you all the lines and place the line from myfile into the line variable
for(int count = 0; !inputFile.eof() && (count < userInput) ; ++count) //Why are you using a while-loop if you need to count the iterations
{
//
inputFile >> SalePrice[count] >> RegularPrice[count]; //loads column SalePrice/RegularPrice into the array at position 'count'
}
float sumRegularPrice = 0;
for(int i=0; i < userInput; i++)
sumRegularPrice += RegularPrice[i];
float avgRPrice = sumRegularPrice / userInput;
cout << endl;
cout << fixed;
cout << "The average of all the Regular Prices in the file is: " << avgRPrice << endl;
//cout << "The minimum Regular Price in the file is: " << minRPrice << endl;
//cout << "The maximum Regular Price in the file is: " << maxRPrice << endl;
system("pause");
return 0;
}
Why are you loading RegularPrice only once? As far as I got your explanation about the file format (you said one column is SalePrice & the second column RegularPrice), every line might have this content:
3.44 5.99
To get the min and max price you can simply write two functions.
With this input:
3.44 5.99
5.54 8.99
I get this output (in the console):
The average of all the Regular Prices in the file is: 7.490000
If you have some questions don't hesitate to ask me.