formatting strings in a .txt file (C++) - c++

unformatted_grades.txt:
formatted_grades.txt:
I am working on an assignment where my professor wants me to open and read a .txt file with different strings inside of it. We are supposed to format the content of the file.
Ex:
The read_grade_file method has a parameter int number_of_students
The first line of the file is "number_of_students 9"
I have opened and read the file and pushed each individual line into a string vector.
How do I get the number 9 in the first line by itself so I can make the number_of_students parameter equal to it???
Please help.
(We are allowed to skip over or delete any irrelevant data from the vector).
My code:
void Read_Grade_File(string names[MAX_CLASS_SIZE][2], int scores[MAX_CLASS_SIZE][MAX_NUMBER_OF_ASSIGNMENTS], int *number_of_students, int *number_of_assignments, const string input_filename) {
string currline; // temporarily holds the content of each line read from the file
ifstream inFile; // filestream
vector<string> content; // vector containing each string from the file
inFile.open(input_filename); //open the file.
if (inFile.is_open()){
// reads file and pushes the content into a vector
while(!inFile.eof()){
getline(inFile, currline);
if(currline.size() > 0){
content.push_back(currline);
}
}
}
// prints the content stored in the vector
for (int i = 0; i < content.size(); i++){
cout << content[i] << endl;
}
}

Rather than reading the entire line at once, it may make more sense to read the various values on the line as you go. For example, if you know the format of the file, then you can read the first variable's name followed by reading the value of the variable like this:
std::string variableName;
int variableValue;
inFile >> variableName;
inFile >> variableValue;
So you could get the variables whose names you know, find their values, and then loop through the rest of the file reading in that many records.

Related

Cout empty when there are two getline?

I am trying to cout my array but it keep showing empty whenever I try to.
int array_size = 0;
int pos;
string line;
ifstream inFile;
string filename = 'test.txt';
inFile.open(filename);
for(array_size = 0; getline(inFile, line); array_length++);
string * array_holder = new string[array_size];
while(getline(inFile, line))
{
array_holder[pos++] = line;
}
printArray(array_holder, array_size);
Print array
void printArray(string * data, int x)
{
for(int z = 0; z < x; z++)
cout << data[z] << endl;
}
When I comment out this line:
for(array_size = 0; getline(inFile, line); array_length++);
The printArray will show all the contents inside.
But when I uncomment the line, it just show empty lines (depending on the array size).
I reckon this is due to double getline? Do I need to clear the getline buffer or something? I couldn't find any details about getline buffer except for cin. Or is this memory issue?
Note that I cannot use vector in my situation and I need to read the total number of lines in the text file in order to parse the array size to my array syntax.
Thanks.
for(array_size = 0; getline(inFile, line); array_length++);
This loop reads inFile, one line at a time, until the end of the file is reached.
After this loop terminates, the entire file has been read. After all, that's exactly what your program tells your computer to do: read one line at a time, incrementing the counter, until getline fails, which happens at the end of the file. But then immediately afterwards, the second loop attempts to continue reading from the file:
while(getline(inFile, line))
However, since the end of the file has already been reached, this immediately fails, and nothing happens.
You obviously want to reread the file from the beginning, here. However, the Golden Rule Of Computer Programming states "your computer will always do exactly what you tell it to do, instead of what you want it to do". You have not told your computer to go back to the beginning of the file here, so it has no reason to do that. So, you simply have to tell your computer to do that, by closing and reopening the file, or by using the seekg() method.

Delete specific line from .txt file (C++)

I am trying to scan through the content of a .txt file in order to compare it with a user's int input and once found the matching value, line where it is written to be removed.
The file DOES NOT have only numerical values.
Ex of what the file contains:
" hello world 505 "
" hello world 506 " etc.
So far my code is able to make the comparison(the lines do not have the same length) but I do not know how to move the file pointer to the line where said value is found.Any help?
void comparisoniD2 (int a) {
int x[ countLinesOf() ];
ifstream readFile;
readFile.open("ClientList.txt");
string str;
for (int i = 0; i< countLinesOf();i++){
while (getline(readFile, str)) {
reverseStr2(str);
str.erase(3);
reverseStr2(str);
stringstream geek(str);
geek >> x[i];
if( x[i]==a ){
cout<<a<<" is equal to "<<x[i]<<endl;
break;
}
}
}
readFile.close();
}
If you want to do this in the same file it's slightly difficult.
For example you can open the same file twice: for reading strings and for saving strings.
Your cycle would be: read string, save string (if it doesn't contain suitable number).
Another trouble is to cut file to lower size. You can use boost::filesystem or native api.

read a .dat file in c++

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.

My alphabetical string organizer won't save into a file correctly

I have a function that I want to take a file, look at the words in the file, position them in alphabetical order and replace the file with that. So far, I have it to get the words in alphabetical order. The problem is, is that it only saves the last word to the file.
Here is my current code:
void thingy(string Item)
{
fstream File; // Open the file, save the sorted words in it, and then close it.
File.open("Data/Alphabet.txt", ios::out | ios::in);
File << Item;
File.close();
}
void Alphabetical_Order(string Text_File)
{
fstream file;
file.open(Text_File); // Open the file that we are going to organize
std::set<std::string> sortedItems; // The variable that we will store the sorted words in
fstream words; // To see how many words are in the file
words.open(Text_File);
int Words = 0;
do
{
string word;
words >> word;
Words++;
} while (!words.eof());
for (int i = 1; i <= Words; ++i) // Set a loop to take the words out of the file and put them in our variable
{
std::string Data;
file >> Data;
Data = Data + " ";
sortedItems.insert(Data);
}
std::for_each(sortedItems.begin(), sortedItems.end(), thingy);
}
Does anyone know how to fix this?
When you open the fstream in thingy, try opening with ios::ate flag as well. This will allow you to append your text to the file, rather than rewrite every time you call the function.
That being said, you should not be opening and closing the file every time you call the function. Maybe pass a reference to a fstream that gets managed from outside the function thingy.
I hope this helps.
Aiden already pointed out the main problem in your code (+1).
For the records, I'd like however to propose you a more efficient output using the powerfull ostream_iterator: it avoids opening/closing the output file a lot of times and doesn't need trailing spaces in all strings. This being said, I'd suggest to void the unnecessary double pass read as well:
void Alphabetical_Order(string Text_File)
{
ifstream file(Text_File); // Open in read mode
std::string word;
std::set<std::string> sortedItems; // The variable that we will store the sorted words in
while (file >> word) { // just read the file in one pass
sortedItems.insert(word); // to populate the set
}
ofstream ofs("alphasorted.txt");
std::copy(sortedItems.begin(), sortedItems.end(), std::ostream_iterator<std::string>(ofs, " "));
}

new >> how would i read a file that has 3 columns and each column contains 100 numbers into an array?

int exam1[100];// array that can hold 100 numbers for 1st column
int exam2[100];// array that can hold 100 numbers for 2nd column
int exam3[100];// array that can hold 100 numbers for 3rd column
int main()
{
ifstream infile;
int num;
infile.open("example.txt");// file containing numbers in 3 columns
if(infile.fail()) // checks to see if file opended
{
cout << "error" << endl;
}
while(!infile.eof()) // reads file to end of line
{
for(i=0;i<100;i++); // array numbers less than 100
{
while(infile >> [exam]); // while reading get 1st array or element
???// how will i go read the next number
infile >> num;
}
}
infile.close();
}
int exam1[100];// array that can hold 100 numbers for 1st column
int exam2[100];// array that can hold 100 numbers for 2nd column
int exam3[100];// array that can hold 100 numbers for 3rd column
int main() // int main NOT void main
{
ifstream infile;
int num = 0; // num must start at 0
infile.open("example.txt");// file containing numbers in 3 columns
if(infile.fail()) // checks to see if file opended
{
cout << "error" << endl;
return 1; // no point continuing if the file didn't open...
}
while(!infile.eof()) // reads file to end of *file*, not line
{
infile >> exam1[num]; // read first column number
infile >> exam2[num]; // read second column number
infile >> exam3[num]; // read third column number
++num; // go to the next number
// you can also do it on the same line like this:
// infile >> exam1[num] >> exam2[num] >> exam3[num]; ++num;
}
infile.close();
return 0; // everything went right.
}
I assume you always have 3 numbers per line. If you know the exact number of lines, replace the while with a for from 0 to the number of lines.
Rule # 1 about reading data from a file: don't trust the contents of the file. You never know with absolute certainty what is in the file until you've read it
That said, one correct way to read lines of data from a file, where each line is composed of multiple whitespace-delimited fields would be to use a combination of getline and stringstream:
std::string line;
while (std::getline(infile, line))
{
std::stringstream ss(line);
int a, b, c;
if (ss >> a >> b >> c)
{
// Add a, b, and c to their respective arrays
}
}
In English, we get each line from the file stream using getline, then parse the line into three integers using a stringstream. This allows us to be certain that each line is formatted correctly.
We check to ensure the extraction of the integers succeeded before we add them to the arrays to ensure that the arrays always have only valid data.
There is other error handling that might be desirable:
In the example, if extraction of the integers from the line fails, we just ignore that line; it could be a good idea to add logic to abort the process or report an error.
After we get three integers, we ignore the rest of the line; it might be a good idea to add checks to ensure that there is no more data on the line after the required integers, depending on how strict the file's formatting needs to be.
After we finish reading the file, we should test to be sure eof() is set and not fail() or bad(); if one of those two flags is set, some error occurred when reading the file.