Ok so my project is a program that analyses a .txt file that has a bunch of DNA strands of varying lengths. I got it all to work in 3 functions but my teacher wants us to us oo programming. So i put my code in a class and broke it up into different functions. Now, however my variables seem to randomly change their value and I don't know why.
I ran a bunch of tests with my "sum" variable (but it is not the only one doing this) and it calculates the correct value in the function but if I cout the value of "sum" back in my main, the value is changed to a ridiculous number.
Here is the code: it is not my whole program just where the problem variable is and how it is used.
If this isnt enough code to show the problem i can add more i just didnt want to make it cluttered.
DNAProcessing.cpp
void DNAProcessing::CalcSumAndMean()
{
int lineLength = 0;
int lineCounter = 0;
int wholeFileStringLen = 0;
double sum = 0;
double mean = 0;
string wholeFileString = "";
string line;
bool filefail = false;
ifstream DNAFile;
DNAFile.open(nameoffile.c_str());
if(DNAFile.fail())
{
filefail = true;
return;
}
else
{
cout << "\nYour data was processed\n" << endl;
}
while(DNAFile >> line)
{
//cout << line << endl;
lineCounter += 1;
lineLength = line.length();
sum += lineLength;
wholeFileString += line;
}
cout << "sum: " << sum << endl; // with my test .txt file this outputs 736
mean = (sum / lineCounter);
wholeFileStringLen = wholeFileString.length();
cout << "sum: " << sum << endl; // with my test .txt file this outputs 736
}
main.cpp
int main()
{
srand(time(0));
bool noexit = true;
string yesorno;
string filename;
while(noexit == true)
{
cout << "Would you like to process a list of DNA strings? (y/n)" << endl;
cin >> yesorno;
if((yesorno == "y") || (yesorno == "Y" ))
{
cout << "please input the name of the file you wish to process." << endl;
cin >> filename;
DNAProcessing DNAStrandFile(filename);
DNAStrandFile.CalcSumAndMean();
cout << "sum: " << DNAStrandFile.sum << endl; //for some reason sum turns into 3.18337e-314 and i have no clue why
if (DNAStrandFile.filefail == false)
{
cout << "sum: " << DNAStrandFile.sum << endl; // same here
DNAStrandFile.CalcNucleobaseRelProb();
DNAStrandFile.CalcBigramRelProb();
DNAStrandFile.CalcVarianceAndStndDev();
DNAStrandFile.CalcNormRand();
DNAStrandFile.PrintData();
DNAStrandFile.PrintNewList();
}
else
{
cerr << "No file found" << endl;
}
}
else if((yesorno == "n") || (yesorno == "N"))
{
noexit = false;
}
else{}
}
}
output while passing my test .txt file into this program.
sum: 736
sum: 736
sum: 3.18337e-314
sum: 3.18337e-314
Since sum is declared as double, it's value of 0 may not be stored exactly as zero, for all practical purposes, value of 3.18337e-314 can be considered as zero. You may define a threshold value
double epsilon = 0.00001 ; // depending on precision
and if sum < epsilon, sum = 0.0 (not needed though)
In your example, you have used sum as a local variable as well, either don't declare local variable, just use the member variable or declare the local variable as different name to avoid confusions
The value of a local variable is valid within the scope of the function,thats why you are getting correct answer inside method.
But no value is returned back,therefore garbage value is printed in the main.
Try sending the variable in the method by reference, then their exact value will be available in main also. Try it.
Related
C++ Code
Basically i am trying to take input from a file and store the data in variables, But i am unable to do that because each time i compile this code it compiles successfully but gives a runtime error.(Right Now i have just Data of 3 Students, so i set the condition to run the loop 3 times).
The variable "Name" will get the name from the file, "sap" will get the roll number, "number" will get the number of subjects the user wants to enter marks of (Max 5), and "marks" will enter marks of those subjects.
Variables "SapFile", "NumberFile", and "MarksFile" will get the string data from the file and store them in their respective format variables as mentioned above.
What it does Exactly is read Data from the file to the variables and also prints them, But when it reaches at "i=3" Then instead of this condition becoming false and terminating the Loop and exiting the Function, it gives a runtime error. [Note: It prints the data of 3 students in the file correctly and then gives Runtime error].
The Error Snap is Attaches as follows,
Runtime Error Image
'''
This is My code
void read_in_variables(void)
{
string SapFile = "";
string NumberFile = "";
string MarksFile = "";
int studentCount = 0;
struct Student
{
string Name = "";
int sap = 0;
int number = 0;
int marks[5] = { 0 };
};
Student S[50];
ifstream outFile;
outFile.open("Students.csv", ios::in);
if (outFile.is_open())
{
for (int i = 0; i<3; i++)
{
if (i == 0)
cin.ignore();
getline(outFile, S[i].Name, ',');
studentCount++;
getline(outFile, SapFile, ',');
S[i].sap = stoi(SapFile);
getline(outFile, NumberFile, ',');
S[i].number = stoi(NumberFile);
cout << i + 1 << ". " << S[i].Name << ", " << S[i].sap << ", " << S[i].number;
for (int j = 0; j < (S[i].number - 1); j++)
{
getline(outFile, MarksFile, ',');
S[i].marks[j] = stoi(MarksFile);
cout << ", " << S[i].marks[j];
}
getline(outFile, MarksFile, '\n');
S[i].marks[S[i].number] = stoi(MarksFile);
cout << ", " << S[i].marks[S[i].number];
cout << endl;
}
outFile.close();
if (studentCount == 0)
cout << "\n\nNo Student Records Present.\n\a\n";
}
else
{
cout << "File not Opened !!! ";
}
}
Moreover, when at first i tried to put "outFile.eof()" in the condition statement then it returns false in the beginning and does not even enters in the loop, and Prints "No Student Records Present." as "StudentCount" has Value 0.
[I have included All the Header Files necessary for this function].
Kindly Help me Solve this issue and make this function work perfectly.
Problem Sample Run
Problem Description (1)
Problem Description (2)
The link above is an image of what the program should do once reading in a text file and outputting it correctly to another file. The two other links are descriptions of the problem itself. My problem is that while most of the logic works, when it comes to printing it out, it skips the first number in the input file. For example, if the input file was:
1 10000
2 5000
3 150000
Right now the output in the file prints:
Store 2: *
Store 3: ***
Again, the image provides a better example of what is to happen. The code should work for any text file given, no matter for the order of the numbers: (ex: 50 10000, 5 5000, so on).
I am not sure why this happening. I'm attaching my code for reference below. I would like to apologize in advance for the lack of comments right now, I'm trying to fix the error first. I have narrowed the error down to the while loop in the main function however. Second, I'm somewhat of a beginner, so please excuse any silly mistakes I've made or if I did things in a more inefficient way. Another note is that I can't change the signatures for the functions, and I have to check the values if they are valid in the readFile() function. I also cannot use arrays, or the pause command, or break and continue. Third, I am pretty new to stack overflow so please do excuse any errors I make. Thank you!
As of now, the code that is commented out, is code I don't plan to use, but if there is a way to achieve the goal using that code and staying within the guidelines, please do let me know. This error is quite a frustrating one! Also, I do have some more error to fix afterwards, but those are minor ones I can fix later. I want to fix this error first. Thank you!
#include <iostream>
#include <iomanip>
#include <cmath>
#include <fstream>
using namespace std;
bool readFile(ifstream&, long long int&, unsigned int&);
void display(ofstream&, long long int, unsigned int);
int main()
{
ifstream inputFile;
ofstream outputFile;
string fileName;
long long int salesData;
unsigned int storeNumber;
cout << "Enter input file name" << endl;
cin >> fileName;
inputFile.open(fileName);
bool fileRead = readFile(inputFile, salesData, storeNumber);
if(fileRead)//inputFile >> storeNumber >> salesData)
{
outputFile.open("saleschart.txt");
outputFile << "SALES BAR CHART" << endl;
outputFile << "(Each * equals 5,000 dollars)" << endl;
while(inputFile >> storeNumber >> salesData)
{
display(outputFile, salesData, storeNumber);
/*
if(storeNumber < 1 || storeNumber > 99)
{
cout << "The store number " << storeNumber << " is not valid" << endl;
}
if(salesData < 0)
{
cout << "The sales value for store " << storeNumber << " is negative" << endl;
}
*/
}
inputFile.close();
outputFile.close();
}
return 0;
/*
while(inputFile >> storeNumber >> salesData)
{
int counter = 1;
for(int i = 1; i <= counter; i++)
{
counter++;
bool fileRead = readFile(inputFile, salesData, storeNumber);
if(fileRead)
{
outputFile.open("saleschart.txt");
outputFile << "SALES BAR CHART" << endl;
outputFile << "(Each * equals 5,000 dollars)" << endl;
display(outputFile, salesData, storeNumber);
}
}
*/
}
bool readFile(ifstream& inputFile, long long int& salesData, unsigned int& storeNumber)
{
if(inputFile)
{
inputFile >> storeNumber >> salesData;
if(storeNumber == NULL)
{
cout << "The file was empty" << endl;
return false;
}
if(storeNumber < 1 || storeNumber > 99)
cout << "The store number " << storeNumber << " is not valid" << endl;
if(salesData < 0)
cout << "The sales value for store " << storeNumber << " is negative" << endl;
else
return true;
}
else
{
cout << "File \"sales.txt\" could not be opened" << endl;
return false;
}
return false;
/*
if(inputFile.eof())
return false;
else
{
inputFile >> storeNumber >> salesData;
return true;
}
*/
}
void display(ofstream& outputFile, long long int salesData, unsigned int storeNumber)
{
outputFile << left << setw(6) << "Store" << right << setw(2) << storeNumber << ": ";
cout<<storeNumber; //DEBUG
for(int i = 0; i < (salesData/5000); i++)
{
outputFile << left << "*";
}
outputFile << endl;
}
It's skipping the first numbers because you read them (and the don't save them) in the function readFile. It's got nothing to do with your while loop which is completely correct. But you can't read the same numbers twice, and you have already read the first numbers by the time you get to your while loop.
Not sure what you are expecting from the function readFile, it looks like you tried to read the file in a separate function but then abandoned it. If you just delete the readFile function your code should work.
OK reading your question again I see that are required to use the readFile function. If that is the case then the correct thing to do is delete the current contents of the readFile function and move the while loop into the readFile function.
You have a few problems, the main is that the readFile function reads the first two values, and then you discard the data it has read.
This discarded data will never be written to the output file.
Also in the readFile function you have the comparison storeNumber == NULL which might be a check if the input failed, but that's not how to do that.
First of all because C++ doesn't have null values, NULL is an old C-compatibility constant for a null pointer.
Secondly, you already have the correct check in the loop where you read the remaining data, where you use the whole input expression inputFile >> storeNumber >> salesData as the condition.
Now to put it all together, you don't need the readFile function at all, instead all you need is the reading loop:
outputFile.open("saleschart.txt");
if (!outputFile)
{
// Failed to open the output file
return 1;
}
inputFile.open(fileName);
while(inputFile >> storeNumber >> salesData)
{
display(outputFile, salesData, storeNumber);
}
I have two string variables that are mixing each others letters after a certain point and I have no idea why.
string dna1 and dna2 is read in from a .txt file like this:
string opfile1(string& dnafile, string& dnaseq1); // function dec
string opfile2(string& dnafile, string& dnaseq2);
int main()
{
string dna1;
string dna2;
string seq1;
string seq2;
order1 = openSecondFile(dna1, seq1);
order2 = openThirdFile(dna2, seq2);
//function calls ^
string opfile1(string& dnafile, string& dnaseq1); // function dec
{
string PName;
string frag;
ifstream in_s;
in_s.open(dnafile.c_str());
if(in_s.fail()) //if file does not exist a fail message will appear
{
cout << "Unable to open input file " << song1File << endl;
exit(EXIT_FAILURE);
}
getline(in_s, frag, '|');
Name = frag.substr(1);
in_s >> dnaseq1;
in_s.clear();
return Name;
}
//func def.
The function opfile2 is the exact same except wherever you see a '1', I replaced it with a '2' to match its variables.
Now when I print these out in my main function they appear like this:
cout << dnaseq1 << endl;
cout << dnaseq2 << endl;
Output:
FDFDAFDAF
DFDAFDATZY
Which is correct! Now, when I try to print them using a for loop this happens:
int columns = dnaseq1Size + 1;
for(int i = 0; i < columns; ++i)
{
if(i == 0)
{
cout << setw(3) << "-" << " ";
}
else
{
cout << setw(3) << dnaseq2.at(i) << " ";
}
}
Output:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::at: __n (which is 9) >= this->size() (which is 9)
- D F D A F D A F Aborted (core dumped)
(it starts printing the other notes)
I have no idea what's happening, can anyone help?
EDIT: I figured out the issue and fixed it. I think the issue had something to do with the fact I was using arrays and a "size" so I switched to a 2D vector and used .size instead and the issue fixed it self.
It's clear enough. Your string has size 9, (FDFDAFDAF for example) but you try and print musicalnotes2.at(9). If your string has size 9 then only 0 to 8 are legal indexes
As said in the comments the suspicious part is when you write
int columns = song2Size + 1;
for(int i = 0; i < columns; ++i)
...
Why do you add one there? That seems to be the problem.
It sounds like looks like your're trying to print out each char from the musicalnotes variables
one way to be able to do it is to wrap it in a function (easier to reuse)
void printNotes(const string &musicalNotes) {
cout << setw(3) << "-" << " ";
for(int i = 0; i < musicalNotes.length(); ++i)
{
cout << setw(3) << musicalNotes.at(i) << " ";
}
cout << endl;
}
int main()
{
//... code up until you wish to print it
printNotes(musicalnotes1);
printNotes(musicalnotes2);
//... if you want something afterward
return 0;
}
Here we replace the int columns = song2Size + 1; with the length of the string, and prior to writing anything from there we write out the -
Example output would be:
- F D F D A F D A F
- D F D A F D A T Z Y
I assume that song2Size would be equal to the musicalnotes2.length(), if that's the case you do write over the strings length and therefor you get your out of bounds error. If it contains 9 chars then it would be at index 0,1...7,8 not to 9
I'm really confused. I have to make this lab for a class and I can't seem to have the search only display one result but all of the months of the year. I also can't seem to figure out why its not displaying the TotalRainfall when I input 0 into the month of the year.
Thank you.
#include <iostream>
#include <fstream>
const int MaxSize = 12; //How many weather lines will be available.
using namespace std;
struct WeatherInformation
{
int Month; //Months of the year
float TotalMonthsRainfall; //Total amount of rainfall
float HighTemp; //The Highest temperature of the month.
float LowTemp; //The Lowest temperature of the month.
float AverageTemp; //The Average temperature of the month.
};
WeatherInformation WeatherArray[MaxSize]; //Declaring a month array of MaxSize
void ReadFile(ifstream& MyinFile, WeatherInformation WeatherArray[]);
void WeatherMonthSearch (WeatherInformation WeatherArray[]);
int main()
{
float TotalRainfall = 0;
int count = 1; //Counts how many times the for loop goes.
int MonthOfWeather; //User input of the month.
char ProgramRedo; //User input if they want to reuse the program.
char exit_char; //User input to exit the program.
ifstream MyinFile; //Variable that uses file.
ReadFile (MyinFile, WeatherArray); //Call ReadFile Function
WeatherMonthSearch (WeatherArray); //Call WeatherMonthSearch Function
MyinFile.close(); //Closes file.
}
//Brett Holmes
//4/30/2013
//PreCondition:You need a file labeled weather.dat
//PostCondition: It puts the file variables into an array.
void ReadFile(ifstream& MyinFile, WeatherInformation WeatherArray[])
{
float TotalRainfall = 0;
char exit_char;
int count = 0;
int Month = 0;
cout << "Your Weather Machine" << endl << endl;
MyinFile.open("weather.dat");
if (!MyinFile)
{ //no
cout << "Can't open input file." << endl; //Tests the right file.
char exit_char; //End Program
cout << "Press any key to exit" << endl;
cin >> exit_char;
}
for(count = 1; count < MaxSize; count++) //Puts the file variables in the array.
{
WeatherArray[count].Month = WeatherArray[count].Month + 1;
MyinFile >> WeatherArray[count].TotalMonthsRainfall;
MyinFile >> WeatherArray[count].HighTemp;
MyinFile >> WeatherArray[count].LowTemp;
(WeatherArray[count].AverageTemp = ((WeatherArray[count].HighTemp + WeatherArray[count].LowTemp)/2));
(TotalRainfall = TotalRainfall + WeatherArray[count].TotalMonthsRainfall);
}
}
//Brett Holmes
//4/30/13
//PreCondition:You need to have the months already put into an array in a struct.
//PostCondition:Outputs the rainfall stats the user puts in then asks to run again.
//Outputs a error message if they type in the month wrong.
void WeatherMonthSearch (WeatherInformation WeatherArray[])
{
float TotalRainfall;
int months;
int MonthOfWeather;
char ProgramRedo;
do
{
bool MonthFound = false;
cout << "Please input the number of the Month. Ex. 1=Jan. 2=Feb. etc \n\n";
cin >> MonthOfWeather;
for(int i = 1; i <= MaxSize; i++)
{
months = WeatherArray[i].Month;
if(months == MonthOfWeather ) //Finds the artist and outputs the results
{
cout << "\nTotal Months Rainfall: " << WeatherArray[i].TotalMonthsRainfall << " \n";
cout << "Highest Temperature: " << WeatherArray[i].HighTemp << " \n";
cout << "Lowest Temperature: " << WeatherArray[i].LowTemp << " \n";
cout << "Average Temperature: " << WeatherArray[i].AverageTemp << " \n";
MonthOfWeather = true;
}
}
if(MonthOfWeather == 0)
{
cout << "The total rainfall for the year is: " << TotalRainfall << ".";
}
if(MonthFound == false)
{
cout << "\nMonth Number error. Month not found. Try again.\n\n";
MonthOfWeather = false;
}
cout << "Would you like to look up another month of weather?\n";
cout << "Enter a 'Y' if yes and 'N' if no.\n";
cin >> ProgramRedo;
}while(ProgramRedo == 'Y');
}
Several obvious problems:
Arrays in C++ is 0-based, so your for loop is off-by-one. In your search function, for(int i = 1; i <= MaxSize; i++) should be for(int i = 0; i < MaxSize; i++). Similarly, in your read function, for(count = 1; count < MaxSize; count++) should be for(count = 0; count < MaxSize; count++) (If you want to skip index 0 because you are using it as a signal value, then you should set MaxSize to 13 and have the loop start at 1.)
Why are you assigning a boolean to MonthOfWeather? Do you mean MonthFound?
You read function is not setting the months correctly. WeatherArray[count].Month = WeatherArray[count].Month + 1; should be WeatherArray[count].Month = count; if you are using a 1-based loop or WeatherArray[count].Month = count + 1; if the loop is 0-based.
You calculated your total rainfall in the read function, but the result is stored in a local variable so it's lost when the read is done. Either make TotalRainfall a global variable or do your calculations in your search function.
There are a lot of redundant variable definitions: for example, your weather data array is a global so there is no reason to actually pass it around; exit_char is declared twice in your read function; the first five lines of your main() declared variables that you never used.
Also, your read function does not actually exit the program on failure - it even still attempts to read from the stream and then call your search function! If error-checking is a requirement, you should either have the read function return a boolean and check that the read function succeeded before calling your search function, or simply call std::exit after that cin >> exit_char;.
So, one problem you have is that you have local variables that appear in multiple places, but appears like you expect them to actually contain the same information.
For example, I see three different TotalRainFall. One in main, which is just there, not used for anything, one in ReadFile which is calculated, and one in WeatherMonthSearch, which is not set to anything.
I suspect you want all three of these to actually do something. One way to achieve that would be to remove the local ones in ReadFile and WeatherMonthSearch, and instead pass in the one from main (as a reference into ReadFile).
There's also a few places where you use variables without initializing them. Make it a habit to initialize EVERYTHING and EVERYWHERE!
Enable warnings in your compiler - if you have any form or reasonably new compiler (gcc or MS Visual Studio of recent vintage), it should tell you at least some of these things.
I wrote the code and it works except the total is wrong. It is supposed to multiply the distanceRate by the rate and add each cost to make the total, but it's not doing that. Any help would be appreciated.
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
//Declare Variables
ifstream inFile;
double packageWeight;
double distance;
double totalCharge = 0;
double rate;
double distanceRate;
int customerNumber;
double shippingCharge;
int packageCount = 0;
inFile.open("shipping.txt");
if(inFile)
{
cout << "Customer Package Shipping" << endl;
cout << "Number Weight Distance" << endl;
while(!inFile.eof())
{
inFile >> customerNumber;
inFile >> packageWeight;
inFile >> distance;
if(0 < packageWeight <= 2)
rate = 1.10;
else if(2 < packageWeight <=6)
rate = 2.20;
else if(6 < packageWeight <= 10)
rate = 3.70;
else if(10 < packageWeight <=20)
rate = 4.80;
else
cout << "Invalid package weight" << endl;
if( 0 < distance <= 500)
distanceRate = 1;
else if( 500 < distance <= 1000)
distanceRate = 2;
else if(1000 < distance <= 1500)
distanceRate = 3;
else if(1500 < distance <= 2000)
distanceRate = 4;
else
cout << "Invalid distance" << endl;
packageCount += customerNumber;
shippingCharge = rate * distanceRate;
totalCharge += shippingCharge;
cout << fixed << setprecision(2) << showpoint;
cout << setw(2) << customerNumber
<< right << setw(14) << packageWeight
<< setw(13) << distance
<< endl;
} //End of while loop
cout << "\nPackage shipped : " << packageCount << endl;
cout << "Total Charge : $" << totalCharge << endl;
inFile.close();
}
else
{
cout << "Could not open file" << endl;
}
system("pause");
return 0;
}
Some issues that I see in the snippet you gave me are as follows:
As pointed out by billz in a comment, your if statements are invalid. The statement if( 0 < distance <= 500) is not doing what you expect, it evaluates from left to right, so you have 0 < distance (lets say that evaluates to true) so then you have true <= 1000 which isn't going to give the results that you think it will. This actually needs to be broken apart into two separate comparisons like distance > 0 && distance < 500.
As I noted in my comment, you're adding the customer number to the package count, this will most likely always give a wrong value for package count. If your customer numbers are 1, 2, 3, 4 then you claim the package count is 10 when it's actually only 4 (forgive me if I misunderstood the purpose of this field).
You have no default value for distanceRate but you still use it in an operation (possibly uninitialized) which will give unexpected results (as you are seeing). In your else, you should actually give it a dummy value that way you guarantee that it will always be set. You also do reset it, so if it gets set to 4, and then next distance fails the tests and enters the else, you have another calculation on the variable as 4 instead of it's default value. You should initialize any variable that you plan to use unless you have explicit reason not to give it a value at initialization, and anytime you use a variable in a loop you should reset it's value at the start of the loop.
Additional Note (EDIT)
I wouldn't recommend using system("pause"); as it does a lot more behind the scenes than you would want in a simple pause, a better approach I've seen used is:
#include <iostream>
#include <conio.h>
using namespace std;
int main() {
cout << "Press any key to continue!";
_getch();
cout << "Finished";
return 0;
}
EDIT 2
If statments can contain a single line or a code block to execute.
Single line:
if (someValueIsTrue)
executeThisFunction();
Code block:
if (someValueIsTrue) {
executeThisFunction();
alsoThisFunction();
}
Anytime you need to execute more than one statement in an if/else/while/for/do...while/etc... you'll need a code block. I imagine (based on your explanation) that you did:
if (blah)
// ....
else
distanceRate = 0;
cout << "Invalid Distance";
And the compiler only sees that you have the distanceRate = 0 nested in the loop, the cout statement is actually not part of the else but part of the previous block of code. You need to use a code block here.
!inFile.eof() // incorrect
inFile.good() // correct
read on eof() it doesn't do what you might think it does.
if( 0 < distance <= 500) // all the if statements are incorrect
if(distance>0 && distance<=500) // correct
The way you wrote the if condition, it does not do what you think it does.