This program reads the lines from the text file "penguins.txt" and copies the data into the "FeedingOutput.dat". It worked fine on a different PC but when I run it on my laptop I get the following errors:
Using Uninitialized Memory 'zFeeding'
Using Uninitialized Memory 'zPercent'
Using Uninitialized Memory 'dFeeding'
Using Uninitialized Memory 'dPercent'
Using Uninitialized Memory 'wFeeding'
Using Uninitialized Memory 'wPercent'
The text file "penguins.txt" looks like this:
Zany A 5 4
Den B 4 8
Windi C 5 2.1
Both the .txt and .dat files are in the same directory as the .cpp files.
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
double zFeeding; //Declaring variables
double dFeeding;
double wFeeding;
double zPercent;
double dPercent;
double wPercent;
double zFeedingNew;
double dFeedingNew;
double wFeedingNew;
char filename[50];
string zName, dName, wName, zID, dID, wID;
ifstream penguinInfo; //Allows input and output for the two different files
ofstream dataOutput;
cout << "Enter filename containing penguins information" << endl; //Asking for user to input file name, then opening that file
cin.getline(filename, 50);
penguinInfo.open(filename);
dataOutput.open("FeedingOutput.dat");
dataOutput << showpoint << fixed << setprecision(2); ////formating the output
//this will set the information from penguins.txt to actual variables.
penguinInfo >> zName, zID, zFeeding, zPercent, dName, dID, dFeeding, dPercent, wName, wID, wFeeding, wPercent;
zFeedingNew = zFeeding + (zFeeding * (zPercent / 100)); //equations for new feeding amounts
dFeedingNew = dFeeding + (dFeeding * (dPercent / 100));
wFeedingNew = wFeeding + (wFeeding * (wPercent / 100));
dataOutput << zName << " " << zID << " " << zFeedingNew << " lbs." << endl; //Outputs data to FeedingOutput.dat for Zany
dataOutput << dName << " " << dID << " " << dFeedingNew << " lbs." << endl; //Outputs data to FeedingOutput.dat for Den
dataOutput << wName << " " << wID << " " << wFeedingNew << " lbs." << endl; //Outputs data to FeedingOutput.dat for Windi
penguinInfo.close(); //close files and requires approval to close the program
dataOutput.close();
system("pause");
return 0;
}
I believe this may be a scope issue but I am very new to c++ so I'm not sure what is wrong.
Given
penguinInfo >> zName, zID, zFeeding, zPercent, dName, dID, dFeeding, dPercent, wName, wID, wFeeding, wPercent;
According to the operator precedence, operator >> has higher precedence than operator, and it's just same as
(penguinInfo >> zName), zID, zFeeding, zPercent, dName, dID, dFeeding, dPercent, wName, wID, wFeeding, wPercent;
i.e. only zName is set as penguinInfo >> zName.
You can change it to
penguinInfo >> zName >> zID >> zFeeding >> zPercent >> dName >> dID >> dFeeding >> dPercent >> wName >> wID >> wFeeding >> wPercent;
The problem is that the comma operator doesn't do what you think it does. It simply discards the left and side, and continues with the right hand side:
In a comma expression E1, E2, the expression E1 is evaluated, its result is discarded (although if it has class type, it won't be destroyed until the end of the containing full expression), and its side effects are completed before evaluation of the expression E2 begins (note that a user-defined operator, cannot guarantee sequencing) (until C++17).
Most importantly, it does not fill all the variables used in the comma expression with anything. Thus, your variables remain uninitialized (since you didn't initialize them above).
What you actually want to do is to chain the >> operator just like you would the << operator. That would look like this instead:
penguinInfo >> zName >> zID >> zFeeding >> zPercent >> dName >> dID >> dFeeding >> dPercent >> wName >> wID >> wFeeding >> wPercent;
Related
I want a "slash" to appear automatically in my hospital management system. As the user inputs their birthdate using my application, the / delimiters should appear automatically as they type.
#include <iostream>
using std::cin;
using std::cout;
int main()
{
char slash;
int dy, mn, yr;
cout << "\nEnter your date of birth (dd/mm/yyyy) : ";
cin >> dy;
cin >> slash;
cin >> mn;
cin >> slash;
cin >> yr;
}
Assuming you want to output "/" after the user types each two characters, like a kind of "template", that's going to be impossible in the general case.
Terminal emulators tend to be line buffered unless the user changes that setting, and you have no way of controlling that. The line buffering means nothing will be sent to your program unless and until the user hits Enter, which right away ruins the effect:
The / was written automatically, but it doesn't look right.
Here's what it might look like if you have full control over the terminal and set it up properly:
And my PuTTY config at the time:
However, I also had to read the data character by character (otherwise C++ doesn't know you're done after two/four digits), ready for conversion to numerics after-the-fact. Yuck!
The code for the above was as follows:
// Requires "stty raw" to disable line buffering
// ("stty cooked" to restore), as well as no line
// buffering on the client end
#include <iostream>
using std::cin;
using std::cout;
using std::flush;
int main()
{
char dy1, dy2;
cout << "\nEnter your date of birth (dd/mm/yyyy) : " << flush;
cin >> dy1 >> dy2;
cout << '/' << flush;
char mn1, mn2;
cin >> mn1 >> mn2;
cout << '/' << flush;
char yr1, yr2, yr3, yr4;
cin >> yr1 >> yr2 >> yr3 >> yr4;
std::cout << "\n" << dy1 << dy2
<< '/' << mn1 << mn2
<< '/' << yr1 << yr2 << yr3 << yr4 << '\n';
// Now create some useful integers from these characters
}
Anyway, to really get this right, you'd need to use a "GUI" library like ncurses that can fully take control of the session for you.
Ultimately, it's not worth it. Just let the user enter the full dd/mm/yyyy then parse it for validity.
We were asked to create a class which did the following:
Input int ecode, char ename and basicpay
Now in class, we had to calculate net_pay = basicpay*11/10
Lastly, we had to output ecode, ename and net_pay.
The question stated that net_pay variable cannot be created, its value only has to be used for output, and that value had to be calculated using a separate member function calc
Here is my code:
// Class employee
#include <iostream>
#include <cstdio>
using std::cin;
using std::cout;
class emp {
int ecode;
char ename[20];
float basic_pay;
public:
void input() {
cin >> ecode;
cin.ignore();
cin.getline( ename, 20); // <-- PROBLEM HERE
cin >> basic_pay;
}
float calc( float x) {
return x+x/10;
}
void output() {
cout << "\n Emp. code: " << ecode;
cout << "\n Emp. name: " << ename;
cout << "\n Emp. basic pay: " << basic_pay;
cout << "\n Emp. net pay: " << calc( basic_pay);
}
};
int main() {
emp e1;
cout << "Enter details of employee:\n";
e1.input();
cout << "\nUpdated Profile:\n";
e1.output();
return 0;
}
Error
I am frustrated from past hour about this problem with cin.getline.
String size < 20
The code is working fine for input string size less than 20, so I don't need cin.ignore(), and if I use it, cin.ignore is removing a first digit of basic_pay:
See images: Both are for small string input. Second one is with cin.ignore()
Notice below: Basic_pay was 1100, but it ignored 1.
String size > 20
If I input a string with char number greater than 20, then the overflowing char goes to float, and creates error. So to counter this, I need a cin.ignore(), but even that is not working!
Question
I am in a dilemma. For one string size, cin.ignore() is problamatic, but for other it has no effect. What to use, what not to use? Both are creating mutual conflict. Help me please!
cin.getline(name, 20) can only get 19 characters (one is reserved for the '\0'), therefore if someone inputs 20 or more, then cin.getline(name, 20) will fail, and the next cin >> basic_pay will fail too since the stream error flags are still set, you need to clear them with cin.clear().
Fix:
#include <limits> // for numeric_limits
if (!cin.getline(ename, 20)) // <-- PROBLEM HERE
{
std::cout << "Name too long, trimmed to: " << ename << std::endl;
// clear the stream error flags and ignore rest of the line
cin.clear();
cin.ignore(std::numeric_limits<int>::max(), '\n');
}
// now this line will not fail
cin >> basic_pay;
Live Demo
Sorry for the simple question, but I couldn't find an already available answer elsewhere.
I am building a fractional calculator that can either add, subtract, divide, or multiply two fractions(e.g 4/3 + 5/2). Firstly however, I need to parse out different elements of the user's input, like the arithmetic operator, and the numerator and denominators of the two fractions and store those elements in order to manipulate them down the line.
I thought of using a series of getline(string) while altering the default delimiter to discard whitespace and / signs. However, when I try to execute my program, there seems to be issues with getline(string).
Might somebody be able to point out my surely amateur mistake? The compiler isn't throwing any errors, so I'm a bit lost on what it might be.
EDIT: I'VE SINCE BEEN ABLE TO RESOLVE THE ISSUE THANKS TO HELP. THANK YOU EVERYONE
#include <string>
#include <iostream>
using namespace std;
int main()
{
string numeratorfirst;
string denominatorfirst;
string arithoperator;
string numeratorsecond;
string denominatorsecond;
cout << "Enter the two fractions and the operator you want to use(IE: 3/4 + 4/6): ";
getline(cin, numeratorfirst, '/');
getline(cin, denominatorfirst, ' ');
getline(cin, arithoperator);
getline(cin, numeratorsecond, '/');
getline(cin, denominatorsecond, ' ');
cout << " " << endl;
cout << "Your fraction is: " << numeratorfirst << "/" << denominatorfirst << " " << arithoperator << " " << numeratorsecond << "/" << denominatorsecond << endl;
system("pause");
return 0;
}
It might be easier using scanf():
int numeratorfirst;
int denominatorfirst;
char arithoperator;
int numeratorsecond;
int denominatorsecond;
cout << "Enter the two fractions and the operator you want to use(IE: 3/4 + 4/6): ";
int tokens = scanf("%d/%d %c %d/%d", &numeratorfirst, &denominatorfirst,
&arithoperator, &numeratorsecond, &denominatorsecond);
if (tokens != 5)
return 1;
This works, and it rejects invalid inputs like "foo/bar + baz/qux".
If you want a "more C++ like" solution, try this:
int numeratorfirst, denominatorfirst, numeratorsecond, denominatorsecond;
char slashfirst, slashsecond;
char arithoperator;
cout << "Enter the two fractions and the operator you want to use(IE: 3/4 + 4/6): ";
cin >> numeratorfirst >> slashfirst >> denominatorfirst >> arithoperator
>> numeratorsecond >> slashsecond >> denominatorsecond;
if (!cin || slashfirst != '/' || slashsecond != '/')
return 1;
I`m trying to divide any number in .5, if dividing the number in .5 and my remain is 0 the number will raises up to the next. But if not, it will down to the next.
When I try to do that I get a issue in the line 39. Somebody can help me.
Thanks
//
// main.cpp
// Promedio
//
// Created by Oscar Espinosa on 3/27/15.
// Copyright (c) 2015 IPN ESIME Ticoman. All rights reserved.
//
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int ed, cv, qa, em, h, poo;
float prom, red;
string nom, ape;
cout << " Introduce tus datos" << endl
<<"Nombre: ";
getline(cin, nom);
cout << "Apellidos: ";
getline(cin, ape);
cout << "Introduce las siguientes calificaciones" << endl
<< "Ecuaciones Diferenciales: ";
cin >> ed ;
cout << "Calculo vectorial: ";
cin >> cv ;
cout << "Quimica apilcada: ";
cin >> qa ;
cout << "Electricidad y magnetismo: ";
cin >> em;
cout << "Humanidades II: ";
cin >> h;
cout << "Programacion orientada a objetos: ";
cin >> poo ;
prom = (ed+cv+qa+em+h+poo)/6.00;
if (prom%.5 == 0) // Semantic issue invalid operands to binary expression ('double' and 'double')
{
ceil(prom);
red = ceil(prom);
}
else
{
floor(prom);
red = floor(prom);
}
cout << nom << " " << ape << " tu promedio es " << prom << " y se redondea a " << red;
return 0;
}
#Oscar Espinosa you cannot use %(modulus) operator with double values So its showing the error invalid operands in expression.. try using the fmod(x,y) function..it will work
Modulo (%) can only be used with integer values.
You can use fmod but if you meant to work on integer values, perhaps such a trick can help:
if (10*static_cast< int >(prom)%5 == 0)
The issue is pretty clear: you don't define var before the if(var==0). In C++, you need to define the variable before its first use. Pay attention to what the compiler is telling you. In case of g++:
error: 'var' was not declared in this scope
which I think it's pretty explicit!
PS: don't modify the code after an answer, as you end up confusing everyone. In the actual code, you are passing 0.5 as the modulus operator argument. That operator takes an int. You need other way of testing whether a float is a multiple of 0.5. In particular, you should also pay attention to roundoff errors.
Hint: a float x is a multiple of 0.5 if and only if 2*x is an integer. So 2*x - floor(2*x) must be close to zero, i.e. abs(2*x - floor(2*x)) < 1e-12 to avoid floating point errors.
See related question: Checking if float is an integer
i need help in how i should write a code for doing a delete line using c++ in linux. what i have in the text file is listed below
description:amount:date
electricity bill:100:25jan2015
telephone bill:100:25jan2015
telephone bill:50:25jan2015
i want to do it so that when the user selects option b to remove the expense that the user input and to prevent the program from deleting duplicate data the user will have to input the amount and date. thank you.
and the temp.txt is used to store what was not deleted before being renamed to Expense.txt so if telephone bill value 100 was removed it would become
electricity bill:100:25jan2015
telephonebill:50:25jan2015
void deleteexpensesdata(string& expense, string& texpense, double& amount, string& date){
int check, x=0;
ifstream Expenses("Expense.txt");
ofstream temp("temp.txt");
cout << "\n";
cout << "Enter Type of Expense you wish to remove" << endl;
cin >> texpense;
while(Expenses >> expense >> amount >> date){
if(texpense!=expense){//if there are expenses with different name, input their data into temp file
temp << expense << ":" << amount << ":" << date <<endl;
}
if(texpense==expense){// if user entered correct name, x=1 for later output message that the user data has been deleted
x=1;
}
}
Expenses.clear();
Expenses.seekg(0, ios::beg);
Expenses.close();
temp.close();
remove("Expense.txt");
rename("temp.txt","Expense.txt");
if(x==0){//x was set to 0 at start, so if it didn't change, it means there is error
cout << "Remove of Expense failed" << endl;
}
else{//if x is not = 0 then remove is successful
cout << "Expenses has been removed" << endl;
}
}
the code that calls the function is below
cout << "Remove Expense.\n";
deleteexpensesdata(expense, texpense, amount, date);
cout << "Expense Date has been delete. \n" << endl;
cin.ignore();
cin.get();
This code below gets the user input and converts the double to string and turns all 3 variable into line with the delimiter ":" as seen in your example input and after u open the file u get the line that does not match into a temp file and rename the file essentially removing it.
double expamt;
string line, expdesc, exptrans;
cout << "Please Enter Expense: \n";
cin >> expdesc;
cout << "Please Enter Amount: \n";
cin >> expamt;
string newamt = static_cast<ostringstream*>( &(ostringstream() << expamt) )->str();
cout << "Date of Transaction: (e.g 20jan2015)\n";
cin >> exptrans;
string input = expdesc + ":" + newamt + ":" + exptrans;
ifstream myfile;
ofstream tempfile;
myfile.open("Expense.txt");
tempfile.open("temp.txt");
while (getline(myfile, line))
{
if (line != input)
tempfile << line;
}
cout << "\nExpense " << expdesc << " has been removed \n" <<endl;
myfile.close();
tempfile.close();
remove("Expense.txt");
rename("temp.txt", "Expense.txt");
First an advice: You should learn to use gdb.
Your code has several logic errors, for instance the line:
Expenses >> expense >> amount >> date
might not be doing what you're expecting to do, since the operator >> don't deal (by default) with character ':' as a separtor or delimiter.
Also, don't use a variable (x) for checking input errors, ifstream and ofstream objects has functions like: ifstream::good, ifstream::fail and ifstream::bad.
However you could user a x for check if any change was made, if not you don't need the file operations:
remove("Expense.txt");
rename("temp.txt","Expense.txt");
Said that, your comment con be readed:
x was set to 0 at start, so if it didn't change, it means there is error
Actually that's wrong, x == 0 also means the condition texpense==expense never got true.
Recomendations
You could use std::iftream::getline and change the delimiter to :.
You could use std::iftream::getline combined with regex and std::regex::search.
I think the first is easier (if : aren't sorrounded by spaces), the second is more elegant as less error prone. Is up to you.