I have a .txt file that contains in which the content of an array is written. But if the program closes, the array's content is of course deleted, because of which I need to read the .txt file to "remind" the array of its previous content.
That's my code:
#include <fstream>
unsigned short int highscores[11]{0};
int main()
{
highscores[0] = score;
std::sort(highscores, highscores + 11);
std::ofstream outputFile("scores.txt", std::ios::trunc);
for (short int i = 10; i > 0; i--) {
outputFile << highscores[i] << std::endl;
}
outputFile.close();
}
and that's my scores.txt file:
22
15
13
10
5
5
3
1
1
1
Any recommendations to this code are also welcome!
You are only writing in a file and not reading. If you close your program and start it again your array will be empty like you said. So if you want to read the files from the file you have written in you have to use
std::ifstream inputFile("scores.txt",std::ios::in);
Then there are many ways how to read the file.
One would be to declare a string:
std::string line;
then using a while loop and getline.
usigned short int highscores[11]{0};
int i=0;
while(getline(inputFile,line)
{
highscores[i]=stoi(line);
// stoi means string to int. We use that because line is a string but we need the numbers
}
Related
I am trying to read integers from a file to an array, but when I try to read the elements of said array, I get numbers that have little to nothing to do with the numbers in the file.
#include <fstream>
#include <istream>
#include <iterator>
#include <string>
using namespace std;
//Main Function
int main()
{
//Declare variables and ask user for file names
string f1, f2;
int s1, s2, n = 0;
cout<<"Please enter the names of the files you would like to merge, file extensions included."<<endl;
cout<<"File 1 Name: ";
cin>>f1;
cout<<"File 2 Name: ";
cin>>f2;
//Opening files
ifstream fs1, fs2;
fs1.open(f1);
fs2.open(f2);
//Checking if both files exist
if (fs1 && fs2)
{
//Getting length of files
s1 = distance(istream_iterator<int>(fs1), istream_iterator<int>());
s2 = distance(istream_iterator<int>(fs2), istream_iterator<int>());
//Declaring arrays and writing values to them
int a1[s1], a2[s2];
while(!fs1.eof())
{
fs2 >> a2[n];
n++;
}
//Closing files
fs1.close();
fs2.close();
//Reading array
for (int i=0; i<s2; i++)
{
cout<<a2[i]<<endl;
}
}
//If the requested files do not exist
else
{
cout<<"No file exists with that name."<<endl;
}
}
I have two text files, file1.txt and file2.txt. The code opens the files, determines the number of integers within, and creates an array with the number of integers.
file1.txt: 45 69 87 3 9 32 11 9 6 66
file2.txt: 4
The output I get when reading the array for file1.txt (a1[]) gives very unexpected numbers:
File 1 Name: file1.txt
File 2 Name: file2.txt
0
0
1878276352
6421656
4
6422016
3756032
48
16
4199922
As you can see, this is not the output I expected. file2.txt only consists of the number 4, and its ouput was simply 16
I am somewhat new to c++ and programming in general, so you might have to bear with me. Does anybody see what I've done wrong?
I am using Code::Blocks and gcc is my compiler. Thank you for your time.
Tested, using std:
std::vector<int> read_file(std::string filename) {
int n;
std::vector<int> vector;
std::ifstream file;
file.open(filename);
if (file.is_open()) {
std::string line;
while (std::getline(file, line)) {
std::istringstream is(line);
while (is >> n) {
vector.push_back(n);
}
}
file.close();
}
return vector;
}
int main() {
std::vector<int> vector = read_file("file1.txt");
for (auto element: vector) {
std::cout << element << std::endl;
}
}
Note: int a1[s1], a2[s2]; doesn't comply with the ISO C++ standard. For details, see Why aren't variable-length arrays part of the C++ standard? If you cannot know the length of an array prior to runtime, consider using std::vector.
It is as #user4581301 says, you need to rewind the files, since std::distance() will read the files to the end.
Otherwise you will already be at the end of the files, and you won't read any data into your arrays, which means your arrays will be holding uninitialized memory.
Here is a solution:
// Rewind the files
fs1.clear();
fs2.clear();
fs1.seekg(0);
fs2.seekg(0);
// Read into array 1
for (n = 0; fs1 >> a1[n]; ++n) {}
// Read into array 2
for (n = 0; fs2 >> a2[n]; ++n) {}
seekg() sets the position in the stream to the given offset. seekg(0) resets to the beginning of the stream.
clear() clears the stream's internal error state flags, including the eofbit.
If I open a text file using fstream is there a simple way to jump to a specific line, such as line 8?
Loop your way there.
#include <fstream>
#include <limits>
std::fstream& GotoLine(std::fstream& file, unsigned int num){
file.seekg(std::ios::beg);
for(int i=0; i < num - 1; ++i){
file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
}
return file;
}
Sets the seek pointer of file to the beginning of line num.
Testing a file with the following content:
1
2
3
4
5
6
7
8
9
10
Test program:
int main(){
using namespace std;
fstream file("bla.txt");
GotoLine(file, 8);
string line8;
file >> line8;
cout << line8;
cin.get();
return 0;
}
Output: 8
If every line has the same length then you can use istream::seekg() to jump to the location and read from there.
Here is a working and neat example with std::getline() if the lines have the same length:
#include <iostream>
#include <fstream>
#include <string>
const int LINE = 4;
int main() {
std::ifstream f("FILE.txt");
std::string s;
for (int i = 1; i <= LINE; i++)
std::getline(f, s);
std::cout << s;
return 0;
}
In general, no, you have to walk down using a strategy similar to what Xeo shows.
If as netrom says you know the lines have fixed length, yes.
And even if the line lengths are not known in advance, but (1) you're going to want to jump around a lot and (2) you can guaranteed that no one is messing with your file in the mean time you could make one pass to form a index, and use that thereafter.
you can use while loop as well
fstream f;
f.open("bla.txt", ios_base::in);
int i = 1;
int line = 8;
while(i != line){
f.ignore(1000, '\n');
++i;
}
string fContent;
f >> fContent;
cout << fContent;
Note: create the file first
So I have two simple questions. One is my function okay for reading a text file composed of one number on each line and passing it an array inside main()? And is the text file opening/closing properly or do I not understand the code?
And secondly, I can't seem to fill my array correctly. There's 92 numbers/lines, but I can only seem to get 91 elements. It seems to skip the first number, but I'm not sure why. When I'm debugging I can see "number" reading the the first line, but I don't know where it goes.
The text file is 92 numbers with decimals, with a number in each line like this..and the first number is in the first line, no space above and no vertical space between the numbers.
31.11
25.22
...
int getTempData(double temperatures[]) {
ifstream input("pgm6.txt");
if (!input)
return 1; // closes input file
string number;
while (input >> number)
for (int i = 0; i < 91; i++)
{
input >> temperatures[i];
}
}
and inside main()
const int ARRAY_SIZE = 91;
double temperatures[ARRAY_SIZE];
getTempData(temperatures);
Edit: Thanks so much for the help everyone. I learned my lesson in not using code I don't quite understand from here: https://www.reddit.com/r/learnprogramming/comments/2wwv6i/c_creating_writing_to_and_displaying_text_files/
#include <fstream> // Instead of <iostream>
#include <string>
using namespace std; // Nothing too much wrong with this...
int main() {
ifstream input("input.txt"); // Open the file "input.txt" for reading
(if = input file)
if ( !input ) // Did the file open correctly?
return 1;
ifstream output("output.txt"); // Open the file "output.txt" for writing
(of = output file)
if ( !output ) // Did the file open correctly?
return 1; // C++ automatically closes the input file!
string word;
**while ( input >> word )** // Read a word while the file isn't at its
end
output << word << '\n'; // Write the word on its own line
// C++ automatically closes the output file
// C++ automatically closes the input file
}
What you are trying to achieve seems to boil down to this:
#include <fstream>
int getTempData(double temperatures[]) {
std::ifstream input("pgm6.txt");
int i;
for (i = 0; i < 92 && input >> temperatures[i]; i++) {
// deliberate empty line
}
// input will close file on exiting function
return i; // returns number of elements found
}
int main() {
const int ARRAY_SIZE = 92;
double temperatures[ARRAY_SIZE];
getTempData(temperatures);
}
while (input >> number)
This reads the first number and throws it away. Simply remove this line of code.
Also, you should probably add error checking to input >> temperatures[i];. And your function needs to return something if all is well -- currently there is no return statement at the end. Also, your loop only collects 91 elements.
I am unable to read '.dat' file. I have tired all the possible ways and tired googling it but I could not find the solution. All it gives me is a null value for integer and a junk value for a string variable or char. This what I have written
ifstream file;
file.open("data1.dat"); // I have also tried this way too like file.open("data1.dat", ios::binary, ios::in);
int data=0;
file >> data;
cout << data << endl;
system("pause");
return 0;
I am using visual studio to compile this code. I am pretty sure that the pointer is entering into the data file but I don't know for what reason the data is not being read.
The .dat file consists of integer number per line ranging from 0, so I just need to read the file and get number from each line and should find the sum of all numbers in the file. The file contains number like
5,
468,
3200,
32, etc.,. Each number is in a new line. The file can contain any number of records. this how .dat file looks when opened using a notepad editor
Your code "works" on my system.
The following compiles (without "using namespace std;")
I changed the file name for my convenience.
I created the 't391.dat' file in the same working directory of the code, and put in 10 lines, with 1 value per line, 1..9,0.
#include <fstream>
#include <iostream>
int t391a(void)
{
std::ifstream file;
file.open("t391.dat");
int data=0;
file >> data;
std::cout << data << std::endl; // echo of input / proof it works
//system("pause");
file.close();
return 0;
}
This code outputs the first value (which is all it attempts to do), so it is working!
The echo of input is good idea.
As an experiment, I temporarily renamed the 't391.dat' file to something else. The code ran to completion and printed a single 0, which is not the first value in the file. Perhaps this suggests your file is not being found, I won't guess. To confirm, I restored the file, and the above 'works' again.
Missing items in your code:
error check - file.open()
a loop to read to end of file
error check - formatted extract (i.e. read from stream) of data item
file.close - possibly not needed
If you are still working this issue, I have a minimally extended version of your code that addresses these issues. Let me know.
class ValueGet {
public:
int data;
ValueGet() {
data = 0;
}
};
int main()
{
ValueGet vg;
ifstream file;
file.open("data1.dat", fstream::binary | fstream::out); // Opens a file in binary mode for input operations i.e., getting data from file.
if (!file)
cout << "File Not Found." << endl;
else {
file.seekg(0); // To make sure that the data is read from the starting position of the file.
while (file.read((char *)&vg, sizeof(vg))) // Iterates through the file till the pointer reads the last line of the file.
cout<<vg.data<<endl;
}
//system("pause");
return 0;
}
output of the data in the file
Here is one way which I just found
#include <bits/stdc++.h>
using namespace std;
int main(){
unsigned int a;
unsigned char c;
ifstream file;
file.open("ou.bin", ios::binary);
if(!file.is_open()){
cout<<"error";
return 0;
}
for(int i=0; i<8; i++){
file>>c;
a = c;
a = a<<8;
file>>c;
a = a+ c;
cout<<a<<endl;
}
file.close();
return 0;
}
This for storing two bytes in a number you can store as many bytes in a number or even one.
Hope this helps.
You will not be able to read .dat files and understand them in your context-- they are general formats used for storing data. Unless you know the contents of it or how they are specified, you will always get junk.
I think this should be quite simple, but my googling didn't help so far... I need to write to an existing file in C++, but not necessarily at the end of the file.
I know that when I just want to append text to my file, I can pass the flag ios:app when calling open on my stream object. However, this only let's me write to the very end of the file, but not into its middle.
I made a short program to illustrate the issue:
#include <iostream>
#include <fstream>
using namespace std;
int main () {
string path = "../test.csv";
fstream file;
file.open(path); // ios::in and ios::out by default
const int rows = 100;
for (int i = 0; i < rows; i++) {
file << i << "\n";
}
string line;
while (getline(file, line)) {
cout << "line: " << line << endl; // here I would like to append more text to certain rows
}
file.close();
}
You cannot insert in the middle of the file. You have to copy the old file to a new file and insert whatever you want in the middle during copying to the new file.
Otherwise, if you intend to overwrite data/lines in the existing file, that is possible by using std::ostream::seekp() to identify the position within the file.
You could write to the end and swap lines until it ends up in the right position.
Here's what I had to do.
Here's the test.txt file before:
12345678
12345678
12345678
12345678
12345678
Here's a sample of my program
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
fstream& goToLine(fstream& file, int line){
int charInLine = 10; //number of characters in each line + 2
//this file has 8 characters per line
int pos = (line-1)*charInLine;
file.seekg(pos);
file.seekp(pos);
return file;
}
fstream& swapLines(fstream& file, int firstLine, int secondLine){
string firstStr, secondStr;
goToLine(file,firstLine);
getline(file,firstStr);
goToLine(file,secondLine);
getline(file,secondStr);
goToLine(file,firstLine);
file.write(secondStr.c_str(),8); //Make sure there are 8 chars per line
goToLine(file,secondLine);
file.write(firstStr.c_str(),8);
return file;
}
int main(){
fstream file;
int numLines = 5; //number of lines in the file
//open file once to write to the end
file.open("test.txt",ios::app);
if(file.is_open()){
file<<"someText\n"; //Write your line to the end of the file.
file.close();
}
//open file again without the ios::app flag
file.open("test.txt");
if(file.is_open()){
for(int i=numLines+1;i>3;i--){ //Move someText\n to line 3
swapLines(file,i-1,i);
}
file.close();
}
return 0;
}
Here's the test.txt file after:
12345678
12345678
someText
12345678
12345678
12345678
I hope this helps!
Based on my basic knowledge of Operating systems, I would say it is not possible.
I mean it is not impossible to make an OS that can allow such functionality with current storage technologies, but doing so would always lead to wastage of space in segments.
But I am not aware of any technology that can allow that. Although some cloud-based DataBases do use such kinds of functionally (like inserting content in middle of a file), but they are made specifically for that DBMS software, with very specifically targeted hardware, and they may also have some custom-built kernels to perform such tasks.