I have a file that has 3 columns with many rows. I want to compare the value either increase or decrease for 2 columns. But when I compare, the value always increases even it should be decreased. Any idea how to solve this? This is my coding to compare the value in the file. But I didn't get the desired output. anyone can help me?
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream fromFile;
fromFile.open("data.txt");
{
cout << "There was an error" << endl;
exit(1);
}
else
cout << "No error, file opened successfully" << endl;
fromFile.clear();
fromFile.seekg(0);
for(int i=1; i<=20; i++)
{
int a{}, b {}, c {};
fromFile >> a >> b >> c ;
cout<<" Year : " <<a<<" population : "<<b<<" car : "<<c<< endl;
if ( b < b && c < c )
cout << " population decrease and car production decrease " << endl;
if ( b > b && c > c );
cout << " population increase and car production increase " << endl;
if ( b > b && c < c )
cout << " population increase but car production decrease " << endl;
if ( b < b && c > c );
cout << " population decrease but car production increase " << endl;
}
//CLOSES FILES
fromFile.close();
return 0;
}
There are several problems with your code. I will first mention those and then show a corrected solution (one of many possible variants).
Some issues:
You should not use using namespace std. There are many expanations on stackoverflow with the explanation. Use full qualified names instead
The std::ifstream has a constructor that automatically opens the stream. No need for function open
The stream has an overloaded bool operator. You can simply test the state with if (fromFile)
You forgot the if statement, but have an else statement. So, your program will not compile. And is logically wrong
Because of the missing if the program will always exit immidiately
clear and seekg are not necessary. The filepointer is at the beginning after opening the stream.
You use a loop with fixed hardcoded magic number 20. What if the file has more or less rows? You need to use the condition end-of-file to end the loop
You compare always the variables with itself. Even the compiler will warn you. This cannot work. You need to read a variable, store it somewhere in a different variable, read again from the file and compare the current variable with the previous value. This is your main problem
No need to call the close-function of the stream. The destructor will call it implicitely for you, when the stream variable leaves its scope
You have not enough comparision if statements. Many cases, especially, if values are same than before, will not be handled
So, what do we need to do? I will explain with only one variable now. Let's take the year. We define a variable year and a second varibale previousValueYear. In a loop, we read the value from the file into year. Then, we compare the year variable with the previousValueYear, do the evaluation and show the output. And then, before reading the next value from the file, we copy the current value from year to previousValueYear. Then we can do the correct comparison in the next loop run.
The first comparision is a little bit tricky, because we do not have a previousValueYear. We will add an additional if statement with a boolean flag, to check for this condition.
Please see here the corrected version:
#include <iostream>
#include <fstream>
int main() {
// Open the source file
std::ifstream fromFile("data.txt");
// Check, if we could open the file
if (fromFile) { // bool operator of stream will be called
// OK, file could be opened. Defineour variables
int year{}, population{}, car{};
int previousValueYear{}, previousValuePopulation{}, previousValueCar{};
bool thisIsTheNotFirstLoopRun{};
// Read values in a loop and check, if the input worked
while (fromFile >> year >> population >> car) {
// Show read data
std::cout << "Year: " << year << " \tPopulation: " << population << " \tCar: " << car << '\n';
// In the first loop run, we will not do a comparision (There is only one value and nothing to compare
if (thisIsTheNotFirstLoopRun) {
// Do the comparisons
if ((population < previousValuePopulation) and (car < previousValueCar))
std::cout << "Population decrease and car production decrease\n";
if ((population > previousValuePopulation) and (car > previousValueCar))
std::cout << "Population increase and car production increase\n";
if ((population > previousValuePopulation) and (car < previousValueCar))
std::cout << "Population increase and car production decrease\n";
if ((population < previousValuePopulation) and (car > previousValueCar))
std::cout << "Population decrease and car production increase\n";
}
// Remember current values for next loop run
previousValueYear = year;
previousValuePopulation = population;
previousValueCar = car;
// Now, we will not have any longer the first loop run
thisIsTheNotFirstLoopRun = true;
}
}
else {
// Error, file could not be opened. Show message
std::cerr << "\nError: SourceFile could not be opened\n";
}
return 0;
}
Advanced C++ porgrammers would change a lot. But for now it is OK
Related
Made a while-loop and I'm not getting the result I think I should be getting.
I've done a little debugging and got nothing. Visual Studio 2019 is saying I'm good to go.
int main()
{
double num_enter;
vector<double> nums(0);
while (cin >> num_enter)
{
nums.push_back(num_enter);
sort(nums.begin(), nums.end());
if (num_enter < nums.front())
{
cout << num_enter << " is the smallest one yet.\n" << endl;
}
else if (num_enter > nums.back())
{
cout << num_enter << " is the biggest one yet.\n" << endl;
}
return 0;
}
I want a while(cin>>enter_num) loop to read num_enter and do a vector.push_back(num_enter) followed by the vector sort function and have it out put if the number has been "the smallest yet" or "the biggest yet" but its not working. could you point out what I'm doing wrong? I'm new be gental.
There is only one number in the vector. None of the conditions are met, if you enter one, one is not greater than one or less than one, hence it is not printing anything because you are not handling that case. Add an else block that prints if the numbers are equal then hopefully it will be clear to you why that is happening.
try this
// Example program
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
double num_enter;
vector<double> nums(0);
while (cin >> num_enter) {
nums.push_back(num_enter);
//sort(nums.begin(), nums.end());
// Lets say you entered 1
// 1 < 1 -> false
if (num_enter < nums.front())
{
cout << num_enter << " is the smallest one yet.\n" << endl;
}
// 1 > 1 -> false
else if (num_enter > nums.back())
{
cout << num_enter << " is the biggest one yet.\n" << endl;
}
else // 1 == 1
{
cout << "Numbers are equal" << endl;
}
return 0;
}
}
Syntax of vector:
vector vectorName(size);
vector nums(0)
In your code nums is a vector of size zero.
Vector is a dynamic array.
Array of zero size is meaningless.
Check this link to see different ways of declaring vector.
suppose you code order should be changed, the if-elseif-else block should be put in front of the push_back and sort,
or if you really want to maintain the order, if-elseif-else should be corrected like if(num_enter == nums.front()) ... else if(num_enter == nums.back())... else,
only then you can know if your input number has been the biggest or smallest yet.
And initialize like vector<double>nums(0) is little weird, just using vector<double>nums is fine
As part of a school project, I would like to get an inventory *.txt file into an array in C++ and eventually back to a *.txt file at a later part in the program.
The text file will start out with 10 rows that will represent grocery story items and will include three columns that represent the name, price, and quantity of the items. I have been able to read from the file, even add numbers in front of each row that is displayed. Now, I would like to get the text file into a string array so that the "employee" user can make changes to items one at a time and then I can dump that array back into a *.txt file.
The code below is what I have been trying so far. I can get the count of rows in the file, but can't seem to get the columns counted or the data in the rows displayed. When I run the program, I get what appear to be 10 empty lines after it displays the rows (10) and Cols(0).
The columns in the *.txt file are normally separated by a space. I tried a tab, and tried: while(getline(invFile, lines, '\t'); which just caused the console to display what I am guessing was a memory address and then crashed.
Unfortunately, we have not gotten very far into debugging programs, and from the look of the syllabus, I don't think that will be covered very thoroughly, so I don't know how to troubleshoot any further. I have spent the last couple of hours Google-ing, and have gotten to the point that I actually need to ask for help.
The project involves a lot more than this component, but I really am stuck on this part. I am not asking for someone to do this for me, but if anyone has any idea what I am doing wrong and can point me in the best direction to get a text file into a multi-dimensional array, I would really appreciate it.
Thank you.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <array>
int row = 0;
int col = 0;
using namespace std;
int main()
{
string lines;
int x;
string textArray[2][2];
ifstream invFile;
invFile.open("inventory.txt");
if(invFile.fail()){
cerr << "The file cannot be opened!";
exit(1);
}
cout << "\n" << endl;
while(invFile.good()) {
while(getline(invFile, lines)) {
istringstream streamA(lines);
col = 0;
while(streamA >> x) {
cout << x;
textArray[row][col] = x;
col++;
}
row++;
}
}
invFile.close();
cout << "Rows: " << row << endl;
cout << "Cols: " << col << endl;
cout << "\n" << endl;
for(int i=0; i<row; i++){
for(int j=0; j<col; j++){
cout << "Line: " << i << textArray[i][j] << ".";
}
cout << "\n";
}
return(0);
}
=============================
inventory.txt:
Apples 1.25 20
Oranges 1.75 20
Kiwi 2.50 15
Pineapples 5.50 20
Tomatoes 1.50 20
Onions 2.00 20
Corn 1.80 20
Carrots 2.30 20
Milk 4.50 20
Cheese 2.25 20
I would suggest that you create a struct or class to hold the data. From each line of text, extract the fields appropriately and them to your struct. Then, keep a list of those structs using std::vector.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <array>
#include <vector>
#include <cstdlib>
using namespace std;
struct Row
{
vector<string> columns;
};
int main()
{
string line;
vector<Row> rows;
ifstream invFile;
invFile.open("inventory.txt");
if(invFile.fail()){
cerr << "The file cannot be opened!";
exit(1);
}
cout << "\n" << endl;
while(invFile.good()) {
while(getline(invFile, line))
{
Row row;
istringstream streamA(line);
string col;
while ( streamA >> col )
{
row.columns.push_back(col);
}
rows.push_back(row);
}
}
invFile.close();
cout << "Rows: " << rows.size() << endl;
cout << "Cols: " << rows[0].columns.size() << endl;
cout << "\n" << endl;
for(int i=0; i<rows.size(); i++){
for(int j=0; j<rows[i].columns.size(); j++){
cout << "Line: " << i << " " << rows[i].columns[j] << "\n";
}
cout << "\n";
}
return(0);
}
I'd like to suggest you add some print lines in the important step -- which I think also is a fast&good "debug" method. So that you can find where you wrong easily.
For example in your code, seems textArray wasn't assigned, so add some print nearby:
while(getline(invFile, lines)) {
cout <<"lines: " << lines << endl; //test enter here
istringstream streamA(lines);
col = 0;
while(streamA >> x) {
cout << "x is" << x; //test if enter here
textArray[row][col] = x;
col++;
}
row++;
}
Through the output, the lines is ok but cout << "x is" << x; wasn't printed, which means the while(streamA >>x) condition is false, why?
Go to find the library function called, std::istringstream x is int type but col 1 value is Apples, operator << will return NULL, it's unreasonable assing Apples to an int, till now, found point 1. If have to use int or float to store the numbers, use some convert API like atoi, atof.
After change x from int to string, got segmentation falut, it's obviously that textArray[2][2] is not enough to store all the information. "Out of range" is the reason of segmentation fault, so make a large array to test continue until passed.
There's a couple ways you could do this. The easiest would be to just put something like 3,10 at the top of the file, and then you know three columns and 10 rows. Since your writing this after modification, you would just need to make sure that those numbers get written correctly.
If you want to learn some more advanced methods, then your life will be easier AFTER you learn a bunch more.
If you used a vector, using something like vector< vector<string> > you could just read to a stringstream and then split the line read and put it into the vector
fstream file(...);
string tempString;
vector< vector<string> > list;
// Get a full line
while(getline(file, tempString, '\n'){
// Create a StringStream and store tempString in it for further manipulation
stringstream ss;
ss << tempString;
vector<string> tempVec;
// Get each column from this row
while(getline(ss, tempString, '\t'){
// Put each column into a vector
tempVec.push_back(tempString);
}
// Put the entire vector into our list vector
list.push_back(tempVec);
}
The benefit of this second method is twofold. First, it's very easy. I'm guessing you don't know how it works, but some easy Google searches on keywords you don't know, and you'll find out fast enough. The second is it allows (theoretically) unlimited rows, and unconstrained columns. By that, I mean one row could have 20 columns, one could have 2, and there would be no wasted space.
Note that you should NOT use the skeleton code I showed before researching it. If you don't have at least a general idea of what is happening here, then you'll just cause problems for yourself later on. I'm not going to explain everything here, because other people have done that already. Also, since you're learning this in school, you'll get to these things eventually, so you'll just be getting ahead. The one main constraint would be if your project requires arrays, in which case, my first solution would be the best option.
I am newbie to programming and I am trying to pass an array into a function and add all the elements together and return the sum. The problem is that I am getting a garbage value for the sum. I have researched on how to pass arrays to functions and I do not know if I'm supposed to use a pointer to pass arrays. I am not good with pointers anyways.
Here is my code
#include <cmath>
#include <cstdlib>
using namespace std;
float mean(int);
int sum(int ARRZO[5]);
int total;
int main()
{
int ARRZ[5];
char *inname = "example.txt";
ifstream infile(inname);
if (!infile) {
cout << "There was a problem opening file " << inname << " for reading." << endl;
return 0;
}
cout << "Opened " << inname << " for reading." << endl;
for(int i=0; i<11; i++)
{
while (infile >> ARRZ[i])
{
cout << "Value from file is " << ARRZ[i] << endl;
}
}
total=sum(ARRZ);
cout<<"the sum of the elements in the array is"<<total<<endl;
system("PAUSE");
return 0;
}
int sum(int ARRZO[])
{
int sumz=0;
for (int i=0; i<5; i++)
{
sumz+=ARRZO[i];
cout<<ARRZO[i];
}
cout<<sumz<<endl;
return sumz;
}
You are actually reading all the values from the file in ARRZ[0] because of the inner loop. By the time you get to i=1, you are at the end of the file, and not reading anything.
Remove one loop, and increment i when you have read successfully a value.
I'm not sure what you think this pair of nested loops is supposed to do:
for(int i=0; i<11; i++)
{
while (infile >> ARRZ[i])
{
cout << "Value from file is " << ARRZ[i] << endl;
}
}
But (as #aliexisdm pointed out) the inner loop reads the entire content of the file. What he didn't (at least directly) point out is that you're reading every one of those values into the first element of your array. Then you're getting back to the outer loop, incrementing i, and trying to read the file again -- but since the stream's failbit has been set, all your subsequent attempts at reading are guaranteed to fail.
After that, you add up the 5 items in the array, but since you haven't read anything into 4 of them (and never initialized its contents) you end up with the last item you read from the file + 4 garbage values, giving still further garbage as the result (well, usually anyway -- you really have undefined behavior, so the program could crash and burn instead, but with most current computers, you'll just get some meaningless number).
I, however, would advise changing the program a bit more than just removing one loop and incrementing in the loop that's left. Instead, I'd remove all the (explicit) loops, and make some attempt at making real use of what the standard library provides.
You can read the numbers from the file in one fell swoop:
std::ifstream infile(inname);
std::vector<int> ARRZ ((std::istream_iterator<int>(infile)),
std::istream_iterator<int>());
Then you can sum them all with std::accumulate:
int sum = std::accumulate(ARRZ.begin(), ARRZ.end(), 0);
Finally, you can print out the result:
cout << "The sum of the elements in the array is: " << sum << "\n";
Since, however, you only read the values from the file to add them together, you don't really need to store them at all. You could just add them together and print out the result:
cout << "The sum of the elements in the file is: "
<< std::accumulate(std::istream_iterator<int>(infile),
std::istream_iterator<int>(), 0);
The whole job reduced to one step...
This is what I have to do:
A teacher has asked all her students to line up single file according to their first name. For example, in one class Amy will be at the front of the line and Yolanda will be at the end. Write a program that prompts the user to enter the number of students in the class, then loops to read in that many names. Once all the names have been read in it reports which student wourld be at the front of the line and which one would be at the end of the line. You may assume that no two students have the same name. Input Validation: Do not accept a number less than 1 or greater than 25 for the number of students.
This is what I have so far:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
int StudentNum;
cout << "How many student are in the class?\n";
cin >> StudentNum;
char sname[StudentNum + 1][25];
if (StudentNum < 1 || StudentNum > 25)
{
cout << "Please enter a number between 1-25 and try again\n";
return 0;
}
for (int i = 1; i <= StudentNum; i++);
{
cout << "Please enter the name of student #" << i << endl;
cin >> sname[i];
}
for (int output = 0; output <=StudentNum; output++);
{
cout << endl << sname[output] << endl;
}
system ("pause");
return 0;
}
Am I missing something about arrays??
You cannot create such an array because its length has to be known at compile time (i.e., it cannot be the result of an expression such as StudentNum + 1).
You can solve this issue because by the problem definition you know an upper bound for the array size, so you can use that as a compile time constant.
However, this problem can be solved without using an array at all. Read the wording carefully.
Hint for the solution without arrays: Think of the array as a single piece of paper (variable) with all the names written one after another. Not using an array then means that you have to be able to solve the problem without looking at all the names at once. How would you come to the answer if I only allowed you to see the names one by one?
Another hint: The problem is still solvable if there were several trillion students in the class (with unique names no less), i.e. more than could possibly fit in the computer's memory at any one time.
C++ array dimensions must be known at compile time (ie not dependent on user-entered variables at run-time). Use strings instead:
string sname[25];
If you were using something besides char arrays, you could also use a vector.
Think about what the problem statement is actually asking for. Your program only needs to output the first and last names alphabetically. Do you actually need to store all the names to do that?
Just for fun, here's how I would do it. Don't turn this in unless are ready to explain to your teacher how it works.
struct MinMax {
std::string min;
std::string max;
MinMax& operator+(const std::string& kid) {
if( min.empty() || kid < min) min = kid;
if( max.empty() || kid > max) max = kid;
return *this;
}
};
int main() {
int nKids;
std::cout << "How many students? " << std::flush;
std::cin >> nKids;
std::cout << "Enter students' names, followed by EOF\n";
MinMax mm(std::accumulate(
std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string>(),
MinMax()));
std::cout << mm.min << ", " << mm.max << "\n";
}
can anyone help me make this more generalised and more pro?
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
// open text file for input:
string file_name;
cout << "please enter file name: ";
cin >> file_name;
// associate the input file stream with a text file
ifstream infile(file_name.c_str());
// error checking for a valid filename
if ( !infile )
{
cerr << "Unable to open file "
<< file_name << " -- quitting!\n";
return( -1 );
}
else cout << "\n";
// some data structures to perform the function
vector<string> lines_of_text;
string textline;
// read in text file, line by
while (getline( infile, textline, '\n' ))
{
// add the new element to the vector
lines_of_text.push_back( textline );
// print the 'back' vector element - see the STL documentation
cout << lines_of_text.back() << "\n";
}
cout<<"OUTPUT BEGINS HERE: "<<endl<<endl;
cout<<"the total capacity of vector: lines_of_text is: "<<lines_of_text.capacity()<<endl;
int PLOC = (lines_of_text.size()+1);
int numbComments =0;
int numbClasses =0;
cout<<"\nThe total number of physical lines of code is: "<<PLOC<<endl;
for (int i=0; i<(PLOC-1); i++)
//reads through each part of the vector string line-by-line and triggers if the
//it registers the "//" which will output a number lower than 100 (since no line is 100 char long and if the function does not
//register that character within the string, it outputs a public status constant that is found in the class string and has a huge value
//alot more than 100.
{
string temp(lines_of_text [i]);
if (temp.find("//")<100)
numbComments +=1;
}
cout<<"The total number of comment lines is: "<<numbComments<<endl;
for (int j=0; j<(PLOC-1); j++)
{
string temp(lines_of_text [j]);
if (temp.find("};")<100)
numbClasses +=1;
}
cout<<"The total number of classes is: "<<numbClasses<<endl;
Format the code properly, use consistent style and nomenclature and throw out the utterly redundant comments and empty lines. The resulting code should be fine. Or “pro”.
Here, I’ve taken the efford (along with some stylistic things that are purely subjective):
Notice that the output is actually wrong (just run it on the program code itself to see that …).
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string file_name;
cout << "please enter file name: ";
cin >> file_name;
ifstream infile(file_name.c_str());
if (not infile) {
cerr << "Unable to open file " << file_name << " -- quitting!" << endl;
return -1;
}
else cout << endl;
vector<string> lines_of_text;
string textline;
while (getline(infile, textline)) {
lines_of_text.push_back(textline);
cout << lines_of_text.back() << endl;
}
cout << "OUTPUT BEGINS HERE: " << endl << endl;
cout << "the total capacity of vector: lines_of_text is: "
<< lines_of_text.capacity() << endl << endl;
int ploc = lines_of_text.size() + 1;
cout << "The total number of physical lines of code is: " << ploc << endl;
// Look for comments `//` and count them.
int num_comments = 0;
for (vector<string>::iterator i = lines_of_text.begin();
i != lines_of_text.end();
++i) {
if (i->find("//") != string::npos)
++num_comments;
}
cout << "The total number of comment lines is: " << num_comments << endl;
// Same for number of classes ...
}
I'm not really sure what you're asking, but I can point out some things that can be improved in this code. I'll focus on the actual statements and leave stylistic comments to others.
cin >> file_name;
To handle file names with spaces, better write
getline(cin, file_name);
int PLOC = (lines_of_text.size()+1);
Why do you claim that there's one more line than there actually is?
if (temp.find("//")<100)
with some complicated comment explaining this. Better write
if (temp.find("//")<temp.npos)
to work correctly on all line lengths.
cout<<"The total number of comment lines is: "<<numbComments<<endl;
Actually, you counted the number of end-of-line comments. I wouldn't call a comment at the end of a statement a "comment line".
You don't count /* */ style comments.
Counting the number of classes as };? Really? How about structs, enums, and plain superfluous semicolons? Simply count the number of occurences of the class keyword. It should have no alphanumeric character or underscore on either side.
Use proper indentation, your code is very difficult to read in its current form. Here is a list of styles.
Prefer ++variable instead of variable += 1 when possible; the ++ operator exists for a reason.
Be consistent in your coding style. If you're going to leave spaces between things like cout and <<, function arguments and the function parantheses do it, otherwise don't, but be consistent. Pick one naming convention for your variables and stick to it. There is a lot about styles you can find on google, for example here and here.
Don't use the entire std namespace, only what you need. User either using std::cout; or prefix all of your cout statements with std::
Avoid needless comments. Everyone knows what ifstream infile(file_name.c_str()); does for example, what I don't know is what your program does as a whole, because I don't really care to understand what it does due to the indentation. It's a short program, so rather than explaning every statement on its own, why not explain what the program's purpose is, and how to use it?
These are all stylistic points. Your program doesn't work in its current form, assuming your goal is to count comments and classes. Doing that is a lot more difficult than you are considering. What if I have a "};" as part of a string for example? What if I have comments in strings?
Don't import the whole std namespace, only things you need from it:
using std::string;
Use a consistent naming convention: decide whether you prefer name_for_a_variable or nameforavariable or nameForAVariable. And use meaningful names: numbComments makes me associate to very different things than would numberOfComments, numComments or commentCount.
If your original code looks like this, I strongly recommend to select a single consistent indentation style: either
if ( ... )
{
...
}
or
if ( ... )
{
...
}
bot not both in the same source file.
Also remove the useless comments like
// add the new element to the vector
This is "only" about the readability of your code, not even touching its functionality... (which, as others have already pointed out, is incorrect). Note that any piece of code is likely to be read many more times than edited. I am fairly sure that you will have trouble reading (and understanding) your own code in this shape, if you need to read it even a couple of months after.
"More professional" would be not doing it at all. Use an existing SLOC counter, so you don't reinvent the wheel.
This discussion lists a few:
http://discuss.techinterview.org/default.asp?joel.3.207012.14
Another tip: Don't use "temp.find("};}) < 100)", use "temp.find("};") != temp.npos;"
Edit: s/end()/npos. Ugh.