I wasn't able to find any obvious answers to this, and I'm pretty stumped.
Do I need to do something different when I want to write a variable string into a text document compared to what I need to do when I want to write just a set string into said document?
This code would properly write "set string" on 8 individual lines on newfile.txt (and create it).
string output_file = "newfile.txt"
ofstream file_object_2;
file_object_2.open(output_file, std::ofstream::out | std::ofstream::app);
string nextline;
for (int i = 0; i <= row_number; ++i)
{
file_object_2 << "set string" << "\n";
}
file_object_2.close();
return 0;
But this would leave the file completely empty, even if line_vector[i] itself has strings within it (and cout can print them)
string output_file = "newfile.txt"
ofstream file_object_2;
file_object_2.open(output_file, std::ofstream::out | std::ofstream::app);
string nextline;
for (int i = 0; i <= row_number; ++i)
{
nextline = line_vector[i];
file_object_2 << nextline << "\n";
}
file_object_2.close();
return 0;
I tried to look at the documentation and do it the same way as they had done, but I'm having no success here. Obviously because of my own failure, but I just can't figure out where I'm in the wrong here.
The only difference with those two codes are in the lines where I'm trying to write into the document
file_object_2 << nextline << "\n";
vs
file_object_2 << "set string" << "\n";
main() that I tried to trim down so it has less dynamic functionality (no manual inputs) but still does not work:
The text file "a.txt" has just a couple of lines of random strings
[a.txt]
("Yogi has a best friend too
Boo Boo, Boo Boo
Yogi has a best friend too
Boo Boo, Boo Boo Bear
Boo Boo, Boo Boo Bear
Boo Boo, Boo Boo Bear
Yogi has a best friend too
Boo Boo, Boo Boo Bear")
And the function itself
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main() {
string input_file = "a.txt";
vector<string> line_vector;
string output_file = "output.txt";
// reads from the original text file. Included in the example because I might
// be constructing the vector in a stupid way and this is where it happens
int row_number = 0;
string line;
while (getline(file_object, line) )
{
cout << line << endl;
line_vector.push_back(line);
++row_number;
}
file_object.close();
// writing onto a new file starts, this is where I'd assume the problem is
ofstream file_object_2;
file_object_2.open(output_file, std::ofstream::out | std::ofstream::app);
string nextline;
for (int i = 0; i <= row_number; ++i)
{
nextline = i + " " + line_vector[i];
file_object_2 << nextline << "\n";
}
file_object_2.close();
return 0;
}
This is broken:
i + " " + line_vector[i]
You meant to_string(i) + " " + line_vector[i], but you used + directly on i and "", which the compiler determines is operator+(int, const char*) which is pointer arithmetic, not a conversion of i to a string. Since the string in question only has one character (a NUL), adding 1 number results in a past-the-end pointer which can't be dereferenced, adding larger numbers is already undefined behavior.
The simplest fix would be to keep i separate from nextline, and write it to the file directly. Your loop body becomes:
{
nextline = line_vector[i];
file_object_2 << i << " " << nextline << "\n";
}
But it should also work to convert i to a string using std::to_string().
As a side note, the first snippet of code you claimed is broken (where nextline = line_vector[i];) actually is just fine. If you had bothered to test that you might have found the problem yourself.
Related
i am trying to get my file to remove the leading and trailing space but it does not work.
this is the txt file contents:
392402 wench
I have tried printing out my code, and this is what is displayed.
first: 392402 wench second:
I want it to display this instead
first: 392402 second: wench
this is my code
void readFile(const string &fileName) {
int limit;
ifstream ifs(fileName);
string::size_type position;
key_type item;
mapped_type count;
string line;
if (ifs.is_open()) {
ifs >> limit;
for (int i = 0; i < limit; i++) {
getline(ifs, line);
position = line.find(" ", 0);
auto c = line.substr(position + 1);
item = line.substr(0, position);
cout << "first: " << c << " second: " << item << endl;
value_type value(item, count);
values.push_back(value);
}
} else {
cout << "Can't open file.";
}
what am i doing wrong? Thank you
The two biggest mistakes you're making are (a) not checking your values for expected output as you go, and (b) not running your code in a debugger to see what is really happening. If you had, the values of position, c, and item would have been blatantly wrong, and you could then surmise where to go from there.
Belaying the highly-likely possibility that the loop iteration is broken from inception because you never consumed the remainder of the entry line containing input, let's look at the actual data and what you're asking of it with your code.
We read this entire line:
392402 wench
You then ask "find the first single-space string in this line" via this code:
position = line.find(" ", 0);
Well, that would be here:
392402 wench
^here
So position is zero (0). You then ask for the sub-string, starting a that position + 1, through the end of the string with this code:
auto c = line.substr(position + 1);
Therefore c now contains (leading space removed via the +1):
392402 wench
Now we build item, which is done with this line:
item = line.substr(0, position);
Remember, position is zero, so you're asking for the string, starting at location 0, length 0. As you can imagine, that isn't going to amount to anything. So now item is an empty string.
Finally, the output statement:
cout << "first: " << c << " second: " << item << endl;
will produce:
first: 392402 wench second:
I.e. exactly what you're seeing. And that's it. Clearly this is wrong.
Alternative
Use better error checking, value checking, and a string stream for per-line extraction. The following code doesn't give two cents about your type aliases (mainly because you didn't include them anyway and I'd rather not loft any guesses as to their origin).
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <limits>
// Expects a file with the following format:
// count
// name1 value1
// name2 value2
// ...
void readFile(const std::string &fileName)
{
std::ifstream ifs(fileName);
if (ifs.is_open())
{
int limit;
if (ifs >> limit && limit > 0)
{
// consume through end of line.
ifs.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// repeat until `limit` iterations or stream error/eof
std::string line;
for (int i = 0; i < limit && std::getline(ifs, line); i++)
{
std::istringstream iss(line);
// extract line values. Note these *can* be formatted
// extraction for things besides just strings
std::string first, second;
if (iss >> first >> second)
{
std::cout << "first: " << first << " second: " << second << '\n';
// TODO: whatever you want to do with first/second
}
}
}
ifs.close();
}
else
{
std::cerr << "Can't open file: " << fileName << '\n';
}
}
Note: The above code will NOT work for remaining-line-content as the expected second value. E.g. It will not process something like this as you may first expect:
10000 this is a multi-word description
will produce this:
first: 10000 second: this
which is considerably different than what you may be expecting:
first: 10000 second: this is a multi-word description
There was no suggestion in the original post such support was mandatory, though adding it wouldn't be terribly difficult to add. If it is a requirement, I leave that task to you.
I want to read data from a file with a quite strange structure. The file looks like this below:
some lines with text....
10 1000 10
1 1 1
1 100 100
.
.
.
some lines with text...
again data like above..
some lines with text... etc
So I have two questions:
How can I read only the specific lines with the data?
How can I read these right aligned data?
Here is one of my trials:
string line;
ifstream myfile ("aa.txt");
double a,b,c;
while (! myfile.eof() )
{
for (int lineno = 0; getline (myfile,line); lineno++)
if (lineno>2 && lineno<5){
myfile>>a>>b>>c;
cout<<lineno<<" " << line << endl;}
}
myfile.close();
how can I read only the specific lines with the data?
well, read all the lines, and then write a function to detect whether the current line is a "data" one or not.
What are the characteristics of your data line? It consists only of digits and spaces? Could there be tabs? What about the columns, are they fixed width? Your predicate function can check there are spaces in the required columns if so.
how can I read these right aligned data?
You want to extract the integer values? Well, you can create a std::istringstream for your line (once you've checked it is data), and then use the >> stream extraction operator to read values into variables of the appropriate type.
Read up on how it handles whitespace (and/or experiment) - it might just do what you need with no effort.
this is just a simple example: you declare 3 variables as you did a, b , c as integer and a string line you open a file and input line convert line to integer if ok assign it to a if not don't do anything to b and c until next read until a valid conversion for a is ok then input b and c and like this:
#include <iostream>
#include <string>
#include <fstream>
int main()
{
std::ifstream in("data.txt");
int a = 0, b = 0, c = 0;
std::string sLine;
if(in.is_open())
{
while(in >> sLine)
{
if( a = atoi(sLine.c_str()))
std::cout << "a: " << a << std::endl;
if(a)
{
in >> sLine;
if( b = atoi(sLine.c_str()))
std::cout << "b: " << b << std::endl;
}
if(b)
{
in >> sLine;
if( c = atoi(sLine.c_str()))
std::cout << "c: " << c << std::endl;
}
}
}
in.close();
std::cout << std::endl;
return 0;
}
Hey everyone this is my first post so if I make any mistakes, such as not enough info etc, please let me know so I do not make them again.
So my issue is I need to take the contents of a file and then input them into a string, which I have working. However after the while loop ends if I try to use that string outside the while loop and manipulate the contents the string. The string is blank and there seems to be no contents. I determined this by using std::cout lines. I believe this to be a scope issue but I am not sure how to fix it. Below is the code pertaining to the question, any tips or help would be greatly appreciated!
std::string str;
std::ifstream file;
while(!file.eof()){
getline(file, str);
std::cout << str << "";
}
file.close();
std::cout << str << "";
std::map<std::string, int> map;
for(int i = 0; i < str.length(); ++i){
std::string sub = str.substr(i, k);
std::cout << sub << std::endl;
map.insert(make_pair(sub, 1));
}
std::cout << "" << std::endl;
Also, I am trying to chop the string up into size k which is a variable defined in a different part of the code, so I used the substr method in C++, and I believe this is working because when I put it in the while loop I can print out the contents of the file but the format is off and I think that is because of the nature of how the while loop runs, but I am not sure, please correct me if I am wrong or have any misconceptions.
Wouldn't it be easier to store the text file into a std::vector and then choose what sentence you'd want to manipulate?
Example:
int main()
{
std::string str;
std::ifstream file{ "file.txt" };
std::vector<std::string> vec;
// Store text file in vector
while (std::getline(file, str)) {
vec.emplace_back(str);
}
// Print out line 2:
std::cout << vec.at(1) << '\n';
// Reverse line 2 and print:
std::string line2 { vec.at(1) };
std::reverse(begin(line2), end(line2));
std::cout << line2 << '\n';
}
You are only storing one line at a time with getline(file, str);. My guess is that the last line of your file is blank, so the last value stored to str is blank.
You can concatenate instead of overwriting:
std::string temp;
std::string str;
std::ifstream file;
while(!file.eof()){
getline(file, temp);
std::cout << str << "";
str = str + temp;
}
Alternatively, add #include <fstream> and use:
std::ifstream inputStream("myfile.txt");
std::string str((std::istreambuf_iterator<char>(inputStream),
(std::istreambuf_iterator<char>()));
working on some code that will place (output/input) 5 different files onto my desktop. Finally, got it down to one error message which is "error <23>: C2109: subscript an array or pointer type is required". Its with myfile.open; I've tried -> operator. Not exactly how to make this into an array, if that is what I'm suppose to do as I have tried making string into char and warnings occur. Can anybody let me know how I can modify my code to correct this? I'm relatively new to C++ and programming, only a few months.
#include <iostream>
#include <fstream>
using namespace std;
struct pizza{
string FILENAMES[9];
};
int main ()
{
int i;
char FILENAMES;
pizza greg = {"file1.doc", "file2.doc", "file3.doc", "file4.doc", "file5.doc"};
cout << "Input is invalid. Program will end. " << "\n" ;
for (i = 0; i < 5; i++)
{
const char *path="/Desktop/Libraries/Documents" ;
ofstream myfile(path);
myfile.open (FILENAMES[i]) ;
myfile << "How you like math?\n" ;
myfile.close();
};
return 0;
}
Your suggestions helped a lot, and my program is now up and running. (no pun intended, haha.)
The loop should really look something like this:
const char *path="/Desktop/Libraries/Documents";
for (int i = 0; i < 5; ++i)
{
std::string name(path + greg.FILENAMES[i]);
std::ofstream myfile(name.c_str());
if (myfile) {
myfile << "How you like math?\n" ;
}
else {
std::cerr << "ERROR: failed to open '" << name << "' for writing\n";
}
}
char FILENAMES;
FILENAMES is not an array. Even if it were, you would have to make it an array of strings or a two dimensional array of characters to do what you intend here.
What you probably intend to do is access the field inside greg.
myfile.open (greg.FILENAMES[i]);
I wrote the code below that successfully gets a random line from a file; however, I need to be able to modify one of the lines, so I need to be able to get the line character by character.
How can I change my code to do this?
Use std::istream::get instead of std::getline. Just read your string character by character until you reach \n, EOF or other errors. I also recommend you read the full std::istream reference.
Good luck with your homework!
UPDATE:
OK, I don't think an example will hurt. Here is how I'd do it if I were you:
#include <string>
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
static std::string
answer (const string & question)
{
std::string answer;
const string filename = "answerfile.txt";
ifstream file (filename.c_str ());
if (!file)
{
cerr << "Can't open '" << filename << "' file.\n";
exit (1);
}
for (int i = 0, r = rand () % 5; i <= r; ++i)
{
answer.clear ();
char c;
while (file.get (c).good () && c != '\n')
{
if (c == 'i') c = 'I'; // Replace character? :)
answer.append (1, c);
}
}
return answer;
}
int
main ()
{
srand (time (NULL));
string question;
cout << "Please enter a question: " << flush;
cin >> question;
cout << answer (question) << endl;
}
... the only thing is that I have no idea why do you need to read string char by char in order to modify it. You can modify std::string object, which is even easier. Let's say you want to replace "I think" with "what if"? You might be better off reading more about
std::string and using find, erase, replace etc.
UPDATE 2:
What happens with your latest code is simply this - you open a file, then you get its content character by character until you reach newline (\n). So in either case you will end up reading the first line and then your do-while loop will terminate. If you look into my example, I did while loop that reads line until \n inside a for loop. So that is basically what you should do - repeat your do-while loop for as many times as many lines you want/can get from that file. For example, something like this will read you two lines:
for (int i = 1; i <= 2; ++i)
{
do
{
answerfile.get (answer);
cout << answer << " (from line " << i << ")\n";
}
while (answer != '\n');
}