I am a newbie here!Although this code completed outputting most of the file, it aborted just before it ended, what went wrong? (2VI3 is a huge data file for coordinates).
Could someone recommend better ways of writing this code?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
string *array = new string[2000];
ifstream iFile("2VI3_SA.txt");
if (!iFile.is_open()) {
cerr << "error: file cannot be opened" << endl;
abort();
}
int x = 0;
while (!iFile.eof()) {
getline(iFile, array[x]);
cout << array[x] << endl;
x++;
}
iFile.close();
cout << x << endl;
ofstream oFile("something.txt");
if (!oFile.is_open()) {
cerr << "error: file cannot be opened" << endl;
abort();
}
for (int i = 0; i < 2000; i++) {
if (i < 818) {
oFile << array[i] << "\n";
}
else if (i<1317){
oFile << array[i].substr(0, 8) << i - 378 << array[i].substr(11, 68) << '\n';
//renumbering all lines below the change
}
else {
oFile << array[i];
}
}
oFile.close();
delete[] array;
return 0;
}
I see at least three problems with the code:
1.
while (!iFile.eof())
This approach to reading a file is always wrong.
2.
An array of 2000 strings gets allocated. There is no explicit check for the actual number of lines read from the input files. It is stated that the file is very big. It is highly likely that there are more than 2000 lines in the file, which will result in a corrupted heap, and undefined behavior.
3.
A more comprehensive review of the code's logic reveals the fact that reading the entire file into a memory buffer is completely unnecessary in the first place! It is perfectly sufficient to read the input file one line at a time, and then write the corresponding output line or lines to the output file, and simply tracking the number of the line currently read. The entire array can be completely eliminated. It's not needed.
Related
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);
}
template <class T>
void savetext(T *a, char const *b) //writes to text file inside .sln however the text file is corrupt
{
ofstream fout(b, ios::out);
for (int i = 0; a[i] != '\0'; i++)
fout << a[i] << endl;
cout << "Text file successfully written to." << endl;
}
template <class T>
void gettext(T *a, char const *b) //this is where the error occurs: inside the text file it puts the right values along with piles of junk. Why is this?
{
ifstream fin(b, ios::in);
if (fin.is_open())
{
cout << "File opened. Now displaying .txt data..." << endl;
for (int i = 0; a[i]!= '\0'; i++)
{
fin >> a[i];
}
cout << "Data successfully read." << endl;
}
else
{
cout << "File could not be opened." << endl;
}
}
int main()
{
const int n1 = 5, n2 = 7, n3 = 6;
int a[n1], x, y, z;
float b[n2] = {};
char c[n3] = "";
//Begin writing files to text files which I name herein.
cout << "Writing data to text 3 text files." << endl;
savetext(a, "integer.txt");
savetext(b, "float.txt");
savetext(c, "string.txt");
cout << endl;
//Retrieve the text in the files and display them on console to prove that they work.
cout << "Now reading files, bitch!" << endl;
gettext(a, "integer.txt");
gettext(b, "float.txt");
gettext(c, "string.txt");
cout << endl;
return 0;
system("PAUSE");
}
Hello, and good evening. I have a C++ program that is currently writing data (integer, floats and chars) to 3 separate text files. However, when it writes the data to the text files two things happen: the data is inside the text file, but so is a bunch of unintelligible wingdings text and large numbers and large negative numbers -- data which I never entered in.
As a result of this, I'm not able to retrieve the information from the text file and I'm not able to display the information of the text file. How do I solve that problem? Thank you.
Your first problem is that you are writing uninitialized data to your files.
I posted something on this last night, but I have decided to change my approach slightly as I wasn't fully understanding the code I was trying to use.
I apologise as I know this topic has been done to death but I'd like a little help with the code I've written.
I'm loading a .txt file from my computer with 100 integers in. They are each on new lines.
This is my code so far:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main ()
{
ifstream fout;
ifstream fin;
string line;
ifstream myfile ("100intergers.txt");
if (myfile.is_open())
{
while ( getline(myfile,line) )
{
cout << line << '\n';
}
// Closes my file
myfile.close();
// If my file is still open, then show closing error
if (myfile.is_open())
cerr << "Error closing file" << endl;
exit(1);
}
int y = 0;
int z = 0;
int sum = 0;
double avg = 0.0;
avg = sum/(y+z);
cout << endl << endl;
cout << "sum = " << sum << endl;
cout << "average = " << avg << endl;
// checking for error
if (!myfile.eof())
{
cerr << "Error reading file" << endl;
exit(2);
}
// close file stream "myfile"
myfile.close();
return(0);
}
When I run it I get exit code 1 (as well as a list of my 100 integers).
Which means my if clause isn't the right choice, what's a better alternative?
If I delete that bit completely, it fails to run do to an arithmetic error which I think is 0/0*0
Also I think the code I've written for the .txt file is for words, not numbers, but when I change string to int it really bugs and tells me I have more problems than without.
Finally - after this I want to make an array to calc variance - any tips?
Cheers
Jack
You're reading lines from the file, which you output.
Then you do arithmetic with some variables, all of which have the value zero.
These variables have no connection to the file's contents.
I'll help with the basic loop structure by showing a way to count the numbers in the file:
int main()
{
int value = 0;
int count = 0;
ifstream myfile("100intergers.txt");
while (myfile >> value)
{
count++;
}
cout << "There were " << count << " numbers." << endl;
}
Summing and the rest is left as an exercise.
I have been making a program for a local... place, and it is a program that will calculate how much pizza will should be ordered. The problem, however, is not even the calculations, but rather with the files that keep log-in I.D. data.
#include <iostream>
#include <stdlib.h>
#include <iomanip>
#include <fstream>
using namespace std;
string logs[20];
void test(ifstream& IN, string logs[], ofstream& OUT);
void introduction();
int logging_in(string id, string logs[]);
void menu();
string newl = "\n";
string dnewl = "\n\n";
string tnewl = "\n\n\n";
string qnewl = "\n\n\n\n";
string pnewl = "\n\n\n\n\n";
int main()
{
ifstream IN;
ofstream OUT;
string id;
IN.open("loginn.dat");
cout << IN.is_open();
test(IN, logs, OUT);
string sup;
int receive = 0;
introduction();
return 0;
}
void test(ifstream& IN, string logs[], ofstream& OUT)
{
for (int x = 0; x < 20; x++)
{
IN >> logs[x];
}
IN.close();
OUT.open("loginn.dat");
for (int x = 0; x < 20; x++)
{
OUT << logs[x] << " " << "hue" << " ";
}
}
void introduction()
{
string cont;
cout << "Hello. I am the..." << dnewl
<< "Statistical" << newl << "Pizza" << newl
<< "Order" << newl << "Amount" << newl
<< "Diagnostic." << dnewl
<< "Otherwise known as Pizzahand. I will be assisting you to estimate the \namount of pizza that is to be ordered for <INSERT NAME>, as to \neliminate excessive ordering."
<< tnewl;
cout << "Press Enter to continue..." << newl;
cin.get();
}
In theory this is supposed to output the array "logs[]" before executing the rest of the code. This was the case when I had no functions in addition to the main function. As soon as I started to use my next function, "introduction()", the code for reading the text file here
for (int x = 0; x < 20; x++)
{
IN >> logs[x];
}
seemed to be knocked out of order. Instead of performing this task before anything else, it seems as if it does it at the very end of the program as I have tested by outputting its contents while the program was still reading "test()", with no luck. After the main function returns "0", however, I see that my program has outputted data into a test file, "loginns.dat", properly.
It is imperative for my program that this login ID data gets read in at the beginning as when the program transitions to logging in, the data is needed. Also, I have tried placing these arrays and for loops in different locations: in the log-in functions themselves, in the main function, and even another function that I created out of desperation.
I have searched for hours on how to solve this to no avail and experimented myself for plenty of hours more. Every step I took to attempt to fix this lead to more dead ends, or more questions. I am quite the beginner in the sense that this school-year is the first year of studying c++, and I am desperate for an expert opinion (or anyone knowledgeable) to help me face the right direction.
Thank you.
You just need to flush the stream after writing to it:
for (int x = 0; x < 20; x++)
{
OUT << logs[x] << " " << "hue" << " ";
}
OUT.flush();
The reason for this strange behaviour is that file streams don't necessarily write out to files immediately when you write to them. For efficiency reasons, they write the data to an internal memory buffer (an area of memory used by the stream), and then write the buffer contents out to the file all at once when the buffer is flushed. When an application finishes then all of its stream buffers are automatically flushed, which is why you are seeing that the file has been written to after your program finishes. However you can flush them earlier yourself, as shown above. It can also happen when the buffer gets full.
You can also trigger a flush using the endl token, which writes a newline character and flushes the buffer, like this:
for (int x = 0; x < 20; x++)
{
OUT << logs[x] << " " << "hue" << " " << endl;
}
This is part of a greater code for reading an input file word-for-word, then printing the words in reverse order. It uses a string array called words[] to store, word-by-word, the char strings from an input file earlier in the program:
//print to screen
for (int i = MAXSIZE; i >= 0; i--)
{
cout << words[i] << " ";
}
Test input file contents:
This is my test file. I hope this works.
Output is just "works. " repeating on and on.
Why is the i-- apparently never happening?
EDIT: Everything from my code. I'm on a bit of a time crunch here, to say the least. MAXSIZE=1024 part of lab prompt. Can't use vectors or reverse; seen that all over, but it's off limits for this lab. New to programming, so if you could refrain from being condescending, that'd be great. Just trying to get this to work. The reading input.txt and print to screen bit works fine. Output portion is utter fail and I don't know why. Can someone just tell me why instead of insulting me, thanks?
//Kristen Korz
//CIS 22A
//This program reads an input file and writes the words in reverse order to an output file.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
//create and link input...
ifstream inputFile;
inputFile.open("input.txt");
//...and output files
ofstream outputFile;
outputFile.open("output.txt");
//error message for file open fail
if (inputFile.fail())
cout << "Error opening the file.\n";
//constant for max size
const int MAXSIZE = 1024;
//string array and temporary-use string
string words[MAXSIZE];
string str; //note: variables will be used for output loops too
//read words from input file
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)
{
words[i] = str;
//for showing in terminal if read correctly
cout << words[i] << " ";
}
inputFile.close();
cout << endl;
//something wrong with for loop resulting in i apparently not updating
for (int i = MAXSIZE; (outputFile << str) && (i >= 0); --i)
{
words[i] = str;
//for showing in terminal if written correctly
cout << words[i] << " ";
}
outputFile.close();
cout << endl;
system("pause");
return 0;
}
For output with i also printed, my cout statements in the for-loops say:
cout << words[i] << " " << i << " ";
Giving terminal output:
This 0 is 1 my 2 test 3 file. 4 I 5 hope 6 this 7 works. 8
works. 1023 works. 1022 works. 1021 (lots of repeats of works. followed by decrementing numbers) works. 3 works. 2 works. 1 works. 0
Your output loop does:
words[i] = str;
for every iteration. str still holds the value of the last string you input, so this sets every member of words to be the same string. Since your last input string was "works", this explains why you output "works" every time.
It should work better if you just remove that line. Also, start from MAXSIZE - 1. The valid indices of the array are 0 through MAXSIZE-1. Your out-of-bounds access causes undefined behaviour, although apparently in this instance it had no effect.
However if your input only has 8 words as you suggest, then outputting 1024 words will give you a lot of blank space. Consider starting the output from where i got up to, instead of MAXSIZE - 1.
At the part marked as not working (the second for loop), str is being read from but it is never changed to anything else in that loop, so it repeats the last word. i is being updated, the problem is that str is not being updated.
The other issue is that you are trying to access an element past the end of the array, as WhozCraig and Velthune discussed in their answers. You need to properly figure out what you want to do with words in your second for loop. This is key. Also, you need to store where the array you read in ends.
Viewing WhozCraig's link, if you have:
const int MAXSIZE = 1024;
string words[MAXSIZE];
for (int i = MAXSIZE; i >= 0; i--) {
cout << words[i] << " ";
}
You have a string that from 0..1023.
Accessing words[1024] is potentially dangerous.
For iterate correctly your string do:
for (int i = MAXSIZE - 1; i >= 0; --i) {
cout << words[i] << " ";
}
By the way, when you fill words, add a control:
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)) {
if(str.size() <= MAXSIZE) {
words[i] = str;
}
}
update
Be sure that your string in file:
"This is my test file. I hope this works. "
doesn't end with a space. To be sure, test adding "EOF" to your string:
"This is my test file. I hope this works.EOF"
Other, do your loop in this way:
int i = 0;
while(inputFile.good() && i < MAXSIZE) {
std::string word << inputFile;
if(!word.empty())
words[i] = str;
//for showing in terminal if read correctly
cout << words[i] << " ";
}
The problem why you get a lot of "works" here is:
After this piece of codes:
//read words from input file
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)
{
words[i] = str;
//for showing in terminal if read correctly
cout << words[i] << " ";
}
inputFile.close();
cout << endl;
//str = "works";
The values of variable str is works.
After that, you set every elements in words by str. So every elements in the words now are the same value works.
for (int i = MAXSIZE; (outputFile << str) && (i >= 0); --i)
{
words[i] = str;//=="works"
//for showing in terminal if written correctly
cout << words[i] << " ";
}
outputFile.close();
cout << endl;