I'm a beginner and I'm trying to transform from previous version of c++ to modern c++17.
I'm trying to read lines from a file. The contents are mostly gibberish and I'm doing this as an exercise to learn the language after not using c++ for many years.
The contents of the file I'm reading from are gibberish, i.e:
werweirwer
weriwrwjeie
werjiwrji
(after solving this I'll use it as an exercise to assign lines after filtering as input to constructors, use regex on it and basically develop it until I feel comfortable enough with input/out concepts, which may take some time).
However, it cannot read from the input file, even though it exists and in the same directory as the .cpp file (with reading permissions). IDE is clion if it matters.
Here's the code I used:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
std::vector<std::string> insertToVector(std::string k){
std::vector<std::string> wordvector;
if(k.empty()) {cerr<<"error reading from file: string is empty";}
else {wordvector.push_back(k);}
return wordvector;
}
int main() {
fstream f("k.txt",ios_base::in);
std::string templine;
if(f){
cout<<"Contents: \n";
while(getline(f, templine)){
cout<<"Contents:"<< templine; //just to output it simply
std::vector<std::string> wordvector= insertToVector(templine);
std::for_each(wordvector.begin(),wordvector.end(),[](const std::string word){std::cout<<word;}); //vector output
}
}else{
std::cerr<<"couldn't open file";
}
f.close();
return 0;
}
Additional question I wonder whether it is good to read lines with while(getline()) or to use while(!f.eof()) instead? Which is better in your opinion?
One more thing, I'm quite confused with functors and std::function, could you show me how to implement the insertToVector as std::function or functor and call it correctly?
Thank you very much. Doing my best to learn
EDIT: Fixed it using auto path = fs::path, and then using that reference with fstream. Worked well. Thank you very much for your explanations in the comments. Helped a lot in learning.
Related
I wrote a code to make "text1.txt" file. It worked correctly, then I've been trying to read from the file, but every time is_open() function doesn't return true. Even so I copied other codes in the way exactly they are in different compilers, but it never works. How will I solve this:(
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream file1("text1.txt");
string str;
if(file1.is_open()){
while(getline( file1, str)){
cout<<str;
}
}
else
cout<<"the file is not open"<<endl;
return 0;
}
How are you running your program?
The most common cause of this I've seen is that you're running your program inside an IDE (like Visual Studio), and your current directory isn't where you think it is.
Try putting in the full path to the file and see if your problem disappears.
If I set a string as a filename, it doesn't work and I have no idea why. (I'm using codeblocks and it seems to work on other IDEs)
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
string FileName="Test.txt";
ofstream File;
File.open(FileName);
}
This does not work,while this next one does:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream File;
File.open("Test.txt");
}
Error message:
no matching function for call to std::basic_ofstream::open(std::string&)
Can someone help a bit with this problem, I cannot understand why this error occurs.
Due to what should be considered a historical accident in the early era of C++ standardisation, C++ file streams originally didn't support std::string for filename parameters, only char pointers.
That's why something like File.open(FileName), with FileName being a std::string, didn't work and had to written as File.open(FileName.c_str()).
File.open("Test.txt") always worked because of the usual array conversion rules which allow the "Test.txt" array to be treated like a pointer to its first element.
C++11 fixed the File.open(FileName) problem by adding std::string overloads.
If your compiler doesn't support C++11, then perhaps you should get a newer one. Or perhaps it does support C++11 and you just have to turn on the support with a flag like -std=c++11.
I have the task to write a function that reads a line from a text file (renamed to .dat, however it contains only text), but I am out of options for a solution because of the following points:
I am using Borland C++ Version 5.02, and no, I CAN´T download another compiler because I dont have admin rights on my laptop and the guy who has the needed password isnt there until next week.
The compiler does not accept using namespace std, and also it doesnt accept getline(), no matter if string and iostream are included or not.
I am trying to find a solution or at least the tiniest approach, but I am unable to find one.
So my question is: How do I read a line from a simple textfile without using getline() (cin.getline works, the ones from string or fstream doesnt) ? The textfile contains several lines like these:
1234;12.05.03;08:44:23; XY12-AB;A1-12;Timeout
2345;12.05.03;09:04:34;XY1-CD;A22-9;Connection refused
And the numbers/letters between the ; need to be stored in variables so they can be worked with.
Im not asking for you to write my code, but I am reallyreaylly frustrated and my instructor is no help.
Live long and prosper,
Me.
http://www.cplusplus.com/reference/string/string/getline/
If you cant use (which you really shouldnt)
using namespace std
Then refer to your namespace with :: operator
For example:
std::string
Now try to write your own code using std:: and comment if you still cant do it.
Also, there is a lot of other options than std::getline() to read line of text.
Ref: Read file line by line
Option 1:
Try using the C's fgets() function.
Option 2:
You mention that cin.getline() works. You can freopen stdin with the input file and then cin will point to mentioned file. After that cin.getline() will read from the file:
Downside: After the freopen you will not be able to accept any input from the user.
Example: Note this has not been tried using g++ but I guess it should work with Borland too.
#include <iostream>
#include <stdio.h>
int main() {
char buf[1000];
freopen("somefile.dat", "r", stdin);
while (cin.getline(buf, sizeof(buf)).good()) {
// Now buf contains a line
// Do something with it
}
return 0;
}
Try using
getline(cin >> ws, variableName);
But first, you have to use
using namespace std;
I'm having the same problem while i using multi dimensional array on structs into a file, i have try different ways. But then i tried this one and it's work for me.
So in my case it gonna be like this
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ifstream myFile;
myFile.open("test.txt");
int count = 0;
while (!myFile.eof())
{
getline(myFile >> ws, data[count].string1);
getline(myFile >> ws, data[count].string2);
myFile >> data[count].int1;
for (int i = 0; i < data[count].int1; i++) {
getline(myFile >> ws, data[count].data2[i].string3);
}
count++;
}
return 0;
}
For more : https://www.geeksforgeeks.org/problem-with-getline-after-cin/
I have searched through a lot of questions on this website which are pretty much the same, but nothing works for me. In the first place, let me tell you that I am using Code::Blocks and I am using Ubuntu. This is my code:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream file("code.out");
string write;
getline(cin, write);
file << write << "\n";
file.close();
}
Tried \n, tried \r\n (\r doesn't seem to do anything for me really). Oh and by the way, if you could also make it work with word-by-word reading that would be great. Thank you very much!
EDIT: Hey guys, I solved it. Thanks for the answers tho! I needed to add a ios::app after code.out!
Should you be using ofstream. http://www.cplusplus.com/reference/fstream/ofstream/
Then check that it has opened.
Then check you have read some data - debugger is handy for that
EDIT
You need
ofstream file("code.out", ios::out | ios::app)
Try this code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
fstream file("code.out", std::fstream::out);
string write;
getline(cin, write);
file << write << '\n';
file.close();
}
Explicitly passing the std::fstream::out through the constructor got it to behave correctly for me and produced the newline.
Edit:
Note for future reference, my solution produces the newline but this will overwrite data currently found in the file. Ed Heal has code for appending to a file in his answer.
Adding
std::fstream::app
to my code would then mimic Ed Helms solution. Please mark his answer if appending functionality is actually what you needed. This answer will be for others who have a similar newline issue who want to overwrite the file.
I also had that problem once.
Try using ofstream instead of fstream. Maby that'll help, because I used that too.
A .csv file is written like this:
M9005U00-X30A0S00-1;BAS;X;-0.002;-0.095
S707RY00-X30AOS00-1;HMV;X;+0.002;+0.081
W3005U00-X30BOJ00-1;BAS;X;+0.026;-0.138
H307QZ00-X30BOJ00-1;HMV;X;-0.025;+0.122
....
now I want to create a function, i.e.
double find_and_extract (string sss)
when this function is used with a keyword as its parameter, for example
find_and_extract (W3005U00-X30BOJ00-1);
it will search in the .csv file line by line, find corresponding line (in this case it should be the third line), and extract the certin part "+0.026" in this line, return as a double.
How should I write this function?
edit: Here is the code i've written so far:
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <vector>
#include <iterator>
#include <cstdlib>
#include <cstdio>
#include <sstream>
#include <stdlib.h>
using namespace std;
void main()
{
find_and_extract (W3005U00-X30BOJ00-1);
}
double find_and_extract (string sss)
{
vector<string> vecarray;
ifstream infile("C:\\Data\\testdata.csv");
string temppo;
string contnt;
char csv_extract[40];
stringstream ss;
vector <string>::iterator ptr;
while (!infile.eof())
{
infile.getline(csv_extract,40);
ss << csv_extract;
ss >> contnt;
vecarray.push_back(contnt);
}
for (ptr=vecarray.begin();ptr!=vecarray.end();ptr++)
{
if ((*ptr).find(sss)==0)
temppo = (*ptr).substr(27,6);
}
return (strtod(temppo.c_str(),NULL,0));
}
Could anyone help me out to point out the errors?
Seeing as you already have the file as a string, I'd use the Knuth–Morris–Pratt algorithm to find the key, find the position of the 3rd and 4th semi-colons on that line and return the string in between them.
That's just an outline - you'll need to add error handling.
Check out strtok(). This is actually a pretty trivial task, and should be a good learning project if you are still new to C++.
You could use sed: This way, you could search for the key very efficiently, without having to implement an algorithm yourself. When you found the key, you can let sed output the parts of the line you need (use regular expressions to describe the pattern and groupings to print only part of it). After that, it's a simple string to float conversion that can be done in a programming language of your choice.
For starters:
sed -n 's/RegexToMatchYourKeyAndValues/MatchedValues/p'
If the text lines in the file are the same length, you may want to read the lines as blocks (i.e. many lines == 1 block) into a buffer, then search the buffer.
Your performance bottleneck will the reading the data from the file. In general, the search method you choose will be faster than reading in the data.