C++ Specific File Handling - c++

I need help in my program where I need to extract the first line of an input txt file that is filled with numbers separated by commas that need to be put into a singly linked list.(Ex: 6,3,5,7) But also the rest of the line has specific instructions and numbers that are separated by a colon.(Example: insert at top:3). The instruction will be used to change the l.list by what asking. The struggling with is how would i be able to extract the information properly. In the program, I can't use advanced structures like trees or hash. Also, I can only use a vector for the input only. I have managed to get a way to get the first line but the second line is what gives most trouble. I have tried to use it to get lines so it can maybe ignore the first line to get the second line but it didn't work.
Here is an example text file:
0,98,6,7,43
insert at top:10
insert at bottom:20
insert at position 1:73
delete at position 4
reverse
print middle
keep unique
Here is what I have right now for the source code:
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
struct numList
{
int data
string instruction;
numList*next;
};
class node()
{
private:
numList*head = nullptr;
numList*tail = nullptr;
public:
}
int main() {
ifstream inFile;
ofstream outFile;
// Un-hardcode this part bellow
inFile.open("input1.txt");
outFile.open("output.txt");
if (inFile.is_open())
{
string line;
getline(inFile, line);
stringstream ss(line);
vector<int> inNumbers;
string number;
while (getline(ss, number, ','))
{
int _number = stoi(number);
inNumbers.push_back(_number);
}
ss.clear();
line.ignore(30,'/n');
stringstream ss(line);
vector<string>instuctions;
while(getline(ss,line,':'))
{
instuctions.pushback(line);
}
}
inFile.close();
outFile.close();
}
I just want to know a way I can try to get the second please explain how your concept or code works so I am not copying. I will respond later to the answer since it is later where I am and I am gonna sleep.

Related

How to read from a text file and split it into values in C++

This is my text file (mytext.text):
rho_0,10
kp_0,8
Beta_kp,6
x_min,5
x_max,8
y_min,9
y_max,5
z_min,4
z_max,7
I want to read from this text file line by line, and store each value in the parameter at the same line.
For example, for the first line, store 10 in rho_0.
I have written this code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
string line;
ifstream myfile("mytext.txt");
if (myfile.is_open())
while (getline(myfile, line))
{
cout << line << endl;
}
}
But I don't think it will save the value for the corresponding parameter.
I know that I should split each line by delimiter, and then convert string to double (float), but I don't know how to implement it for each line.
You'll want to use a map data structure of some sort to store parameter values. You'll probably want std::unordered_map for this. Like #user4581301 said, you can use std::getline with a specific delimiter, like a comma.
std::unordered_map<std::string, float> params;
std::ifstream myfile("mytext.txt");
std::string param_name;
float param_value;
while (std::getline(myfile, param_name, ',')) {
myfile >> param_value;
myfile.get(); // discard newline
params.insert({ param_name, param_value });
}
This code doesn't handle invalid input, so you can add error handling if you want.

How can I read from a file and sort them by category

I'm trying to read a bunch of words from a file and sort them into what kind of words they are (Nouns, Adjective, Verbs ..etc). For example :
-Nouns;
zyrian
zymurgy
zymosis
zymometer
zymolysis
-Verbs_participle;
zoom in
zoom along
zoom
zonk out
zone
I'm using getline to read until the delimiter ';' but how can I know when it read in a type and when it read in a word?
The function below stop right after "-Nouns;"
int main()
{
map<string,string> data_base;
ifstream source ;
source.open("partitioned_data.txt");
char type [MAX];
char word [MAX];
if(source) //check to make sure we have opened the file
{
source.getline(type,MAX,';');
while( source && !source.eof())//make sure we're not at the end of file
{
source.getline(word,MAX);
cout<<type<<endl;
cout<<word<<endl;
source.getline(type,MAX,';');//read the next line
}
}
source.close();
source.clear();
return 0;
}
I am not fully sure about the format of your input file. But you seem to have a file with lines, and in that, items separated by a semicolon.
Reading this should be done differently.
Please see the following example:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
std::istringstream source{R"(noun;tree
noun;house
verb;build
verb;plant
)"};
int main()
{
std::string type{};
std::string word{};
//ifstream source{"partitioned_data.txt"};
if(source) //check to make sure we have opened the file
{
std::string line{};
while(getline(source,line))//make sure we're not at the end of file
{
size_t pos = line.find(';');
if (pos != std::string::npos) {
type = line.substr(0,pos);
word = line.substr(pos+1);
}
std::cout << type << " --> " << word << '\n';
}
}
return 0;
}
There is no need for open and close statements. The constructor and
destructor of the std::ifstream will do that for us.
Do not check eof in while statement
Do not, and never ever use C-Style arrays like char type [MAX];
Read a line in the while statement and check validity of operation in the while. Then work on the read line later.
Search the ';' in the string, and if found, take out the substrings.
If I would knwo the format of the input file, then I will write an even better example for you.
Since I do not have files on SO, I uses a std::istringstream instead. But there is NO difference compared to a file. Simply delete the std::istringstream and uncomment teh ifstream definition in the source code.

Trouble with parsing text file based on commas (C++)

I am working on creating a program that is supposed to read a text file (ex. dog, buddy,,125,,,cat,,,etc...) line by line and parse it based on commas. This is what I have so far but when I run it, nothing happens. I am not entirely sure what i'm doing wrong and I am fairly new to the higher level concepts.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <cstdlib>
#include <sstream>
#include <vector>
using namespace std;
int main()
{
std::ifstream file_("file.txt"); //open file
std::string line_; //declare line_ as a string
std::stringstream ss(line_); //using line as stringstream
vector<string> result; //declaring vector result
while (file_.is_open() && ss.good())
{ //while the file is open and stringstream is good
std::string substr; //declares substr as a string
getline( ss, substr, ',' ); //getting the stringstream line_ and substr and parsing
result.push_back(substr);
}
return 0;
}
Did you forget to add a line like std::getline(file_, line_);? file_ was not read from at all and line_ was put into ss right after it was declared when it was empty.
I'm not sure why you checked if file_ is open in your loop condition since it will always be open unless you close it.
As far as I know, using good() as a loop condition is not a good idea. The flags will only be set the first time an attempt is made to read past the end of the file (it won't be set if you read to exactly the end of the file when hitting the delimiter), so if there was a comma at the end of the file the loop will run one extra time. Instead, you should somehow put the flag check after the extraction and before you use the result of the extraction. A simple way is to just use the getline() call as your loop condition since the function returns the stream itself, which when cast into a bool is equivalent to !ss.fail(). That way, the loop will not execute if the end of the file is reached without extracting any characters.
By the way, comments like //declaring vector result is pretty much useless since it gives no useful information that you can't easily see from the code.
My code:
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
int main()
{
std::ifstream file("input.txt");
std::string line, word;
std::vector<std::vector<string>> result; //result[i][j] = the jth word in the input of the ith line
while(std::getline(file, line))
{
std::stringstream ss(line);
result.emplace_back();
while(std::getline(ss, word, ','))
{
result.back().push_back(word);
}
}
//printing results
for(auto &i : result)
{
for(auto &j : i)
{
std::cout << j << ' ';
}
std::cout << '\n';
}
}

Reading data in from a .csv into usable format using C++

I would like to be able to read the data that I have into C++ and then start to do things to manipulate it. I am quite new but have a tiny bit of basic knowledge. The most obvious way of doing this that strikes me (and maybe this comes from using excel previously) would be to read the data into a 2d array. This is the code that I have so far.
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>
#include <sstream>
using namespace std;
string C_J;
int main()
{
float data[1000000][10];
ifstream C_J_input;
C_J_input.open("/Users/RT/B/CJ.csv");
if (!C_J_input) return -1;
for(int row = 0; row <1000000; row++)
{
string line;
getline(C_J_input, C_J, '?');
if ( !C_J_input.good() )
break;
stringstream iss(line);
for(int col = 0; col < 10; col++)
{
string val;
getline(iss, val, ',');
if (!iss.good() )
break;
stringstream converter(val);
converter >> data[row][col];
}
}
cout << data;
return 0;
}
Once I have the data read in I would like to be able to read through it line by line and then pull analyse it, looking for certain things however I think that could probably be the topic of another thread, once I have the data read in.
Just let me know if this is a bad question in any way and I will try to add anything more that might make it better.
Thanks!
as request of the asker, this is how you would load it into a string, then split into lines, and then further split into elements:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <sstream>
//This takes a string and splits it with a delimiter and returns a vector of strings
std::vector<std::string> &SplitString(const std::string &s, char delim, std::vector<std::string> &elems)
{
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim))
{
elems.push_back(item);
}
return elems;
}
int main(int argc, char* argv[])
{
//load the file with ifstream
std::ifstream t("test.csv");
if (!t)
{
std::cout << "Unknown File" << std::endl;
return 1;
}
//this is just a block of code designed to load the whole file into one string
std::string str;
//this sets the read position to the end
t.seekg(0, std::ios::end);
str.reserve(t.tellg());//this gives the string enough memory to allocate up the the read position of the file (which is the end)
t.seekg(0, std::ios::beg);//this sets the read position back to the beginning to start reading it
//this takes the everything in the stream (the file data) and loads it into the string.
//istreambuf_iterator is used to loop through the contents of the stream (t), and in this case go up to the end.
str.assign((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
//if (sizeof(rawData) != *rawSize)
// return false;
//if the file has size (is not empty) then analyze
if (str.length() > 0)
{
//the file is loaded
//split by delimeter(which is the newline character)
std::vector<std::string> lines;//this holds a string for each line in the file
SplitString(str, '\n', lines);
//each element in the vector holds a vector of of elements(strings between commas)
std::vector<std::vector<std::string> > LineElements;
//for each line
for (auto it : lines)
{
//this is a vector of elements in this line
std::vector<std::string> elementsInLine;
//split with the comma, this would seperate "one,two,three" into {"one","two","three"}
SplitString(it, ',', elementsInLine);
//take the elements in this line, and add it to the line-element vector
LineElements.push_back(elementsInLine);
}
//this displays each element in an organized fashion
//for each line
for (auto it : LineElements)
{
//for each element IN that line
for (auto i : it)
{
//if it is not the last element in the line, then insert comma
if (i != it.back())
std::cout << i << ',';
else
std::cout << i;//last element does not get a trailing comma
}
//the end of the line
std::cout << '\n';
}
}
else
{
std::cout << "File Is empty" << std::endl;
return 1;
}
system("PAUSE");
return 0;
}
On second glance, I've noticed few obvious issues which will slow your progress greatly, so I'll drop them here:
1) you are using two disconnected variables for reading the lines:
C_J - which receives data from getline function
line - which is used as the source of stringstream
I'm pretty sure that the C_J is completely unnecessary. I think you wanted to simply do
getline(C_J_input, line, ...) // so that the textline read will fly to the LINE var
// ...and later
stringstream iss(line); // no change
or, alternatively:
getline(C_J_input, C_J, ...) // no change
// ...and later
stringstream iss(C_J); // so that ISS will read the textline we've just read
elsewise, the stringstream will never see what getline has read form the file - getline writes the data to different place (C_J) than the stringstream looks at (line).
2) another tiny bit is that you are feeding a '?' into getline() as the line separator. CSVs usually use a 'newline' character to separate the data lines. Of course, your input file may use '?' - I dont know. But if you wanted to use a newline instead then omit the parameter at all, getline will use default newline character matching your OS, and this will probably be just OK.
3) your array of float is, um huge. Consider using list instead. It will nicely grow as you read rows. You can even nest them, so list<list<float>> is also very usable. I'd actually probably use list<vector<float>> as the number of columns is constant though. Using a preallocated huge array is not a good idea, as there always be a file with one-line-too-much you know and ka-boom.
4) your code contains a just-as-huge loop that iterates a constant number of times. A loop itself is ok, but the linecount will vary. You actually don't need to count the lines. Especially if you use list<> to store the values. Just like you;ve checked if the file is properly open if(!C_J_input), you may also check if you have reached End-Of-File:
if(C_J_input.eof())
; // will fire ONLY if you are at the end of the file.
see here for an example
uh.. well, that's for start. Goodluck!

is it possible to read from a specific character in a line from a file in c++?

Hey all so I have to get values from a text file, but the values don't stand alone they are all written as this:
Population size: 30
Is there any way in c++ that I can read from after the ':'?
I've tried using the >> operator like:
string pop;
inFile >> pop;
but off course the whitespace terminates the statement before it gets to the number and for some reason using
inFile.getline(pop, 20);
gives me loads of errors because it does not want to write directly to string for some reason..
I don't really want to use a char array because then it won't be as easy to test for the number and extract that alone from the string.
So is there anyway I can use the getline function with a string?
And is it possible to read from after the ':' character?
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;
int main()
{
string fname;
cin >> fname;
ifstream inFile;
inFile.open(fname.c_str());
string pop1;
getline(inFile,pop1);
cout << pop1;
return 0;
}
ok so here is my code with the new getline, but it still outputs nothing. it does correctly open the text file and it works with a char array
You are probably best to read the whole line then manipulate the string :-
std::string line;
std::getline(inFile, line);
line = line.substr(19); // Get character 20 onwards...
You are probably better too looking for the colon :-
size_t pos = line.find(":");
if (pos != string::npos)
{
line = line.substr(pos + 1);
}
Or something similar
Once you've done that you might want to feed it back into a stringstream so you can read ints and stuff?
int population;
std::istringstream ss(line);
ss >> population;
Obviously this all depends on what you want to do with the data
Assuming your data is in the form
<Key>:<Value>
One per line. Then I would do this:
std::string line;
while(std::getline(inFile, line))
{
std::stringstream linestream(line);
std::string key;
int value;
if (std::getline(linestream, key, ':') >> value)
{
// Got a key/value pair
}
}