can't get file to output correctly - c++

i am writing this very simple program that ouputes hello world using files. keep in mind i want the hello and world to be on separate lines.
here is the following code:
int main()
{
std::ofstream someFile("file.dat");
someFile << "" << std::endl;
std::fstream someOtherFile("file.dat",ios::in | ios::out);
std::string content;
someOtherFile << "hello" << std::endl;
someOtherFile << "world" << std::endl;
someOtherFile.seekg(0, ios::beg);
std::getline(someOtherFile, content);
std::cout << content << std::endl;
return 0;
}
however, whenever i run the following program, it only prints "hello".
any help will be greatly appreciated, and PLEASE give an example using fstream, not ofstream or ifstream (I am trying to learn how fstream works, however am finding a little trouble).
my compiler is the latest VS.

getine function only read one line per one time, so you should call getline until the end of file. The code be below can help you.
#include <iostream>
#include <fstream>`
#include <string>
using namespace std;
int main()
{
std::ofstream someFile("file.dat");
someFile << "" << std::endl;
std::fstream someOtherFile("file.dat",ios::in | ios::out);
std::string content;
someOtherFile << "hello" << std::endl;
someOtherFile << "world" << std::endl;
someOtherFile.seekg(0, ios::beg);
while(std::getline(someOtherFile, content))
{
std::cout << content << std::endl;
}
return 0;
}

You have 2 lines of code:
someOtherFile << "hello" << std::endl;
someOtherFile << "world" << std::endl;
They put 2 lines of strings into file.dat:
// file.dat
hello
world
The function "getline()" gets only 1 line from the file. And the "seekg" function sets the read position to the first line of the file: which contains "hello".
If you want to read to the end of the file: then replace:
std::getline(someOtherFile, content);
std::cout << content << std::endl;
with:
while (!someOtherFile.eof())
{
std::getline(someOtherFile, content);
std::cout << content << std::endl;
}
Or use a counter variable if you just want specific lines.
By the way, I am just assuming that you meant to put the variable "content" where "name" is.

std::getline only get one line of text from the specific file. As http://www.cplusplus.com/reference/string/string/getline/?kw=getline says:
istream& getline (istream& is, string& str);
Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, '\n', for (2)).

Add another getline(..) and cout statement after the first set of getline and cout. you will get the world as output.
someOtherFile << "hello" << std::endl;
someOtherFile << "world" << std::endl;
someOtherFile.seekg(0, ios::beg);
std::getline(someOtherFile, content);
std::cout << content << std::endl;
std::getline(someOtherFile, content);
std::cout << content << std::endl;
getline gets only one line in a file. To get next line, you need to call again.

#include<fstream>
#include<iostream>
using namespace std;
int main()
{
std::ofstream someFile("file.dat");
someFile << "" << std::endl;
someFile.close();
std::fstream someOtherFile("file.dat",ios::in | ios::out);
std::string content;
someOtherFile << "hello ";
someOtherFile << "world" << std::endl;
someOtherFile.close();
someOtherFile.seekg(0, ios::beg);
std::getline(someFile1, content);
std::cout << content << std::endl;
someFile1.close();
return 0;
}
This will print your desired answer

Related

How would I make an underline exactly the length of any text inputted as well as capitalizing every letter

Sorry I'm really new to programming and need some assistance. How would I make this happen. This is the function I currently have.
void DisplayTitle(string aTitle) {
cout << "\t" << aTitle << endl;
cout << "\t--------------\n\n";
}
How would I go about making sure that no matter which title is inputted, every character will be capitalized and the underscores will be the same amount of characters as the displayed title above.
You can use std::setfill combined with std::setw from <iomanip> as follows:
std::cout << std::setfill('-') << std::setw(title.size()) << "";
Here, you're telling the stream to use a padding character of '-', then a padded output size that's the length of your title, and then output an empty string. Because the string is empty, it will pad that entire area.
#include <iostream>
#include <iomanip>
#include <string>
void DisplayTitle(const std::string& title, const char* prefix = "\t")
{
std::cout << prefix << title << "\n";
std::cout << prefix << std::setfill('-') << std::setw(title.size()) << "" << "\n\n";
}
int main()
{
for (std::string title; std::getline(std::cin, title); )
{
DisplayTitle(title);
}
}
Example input:
One flew over the cuckoo's nest
The birds and the bees
Example output:
One flew over the cuckoo's nest
-------------------------------
The birds and the bees
----------------------
Here is a live demo of the above.
Oh, it seems I missed the fact your question was asking two things. You also want to capitalize the title. You can do that with std::transform, and in fact it can even be done without modifying the string:
void DisplayTitle(const std::string& title, const char* prefix = "\t")
{
// Write title in all-caps
std::cout << prefix;
std::transform(title.begin(), title.end(),
std::ostream_iterator<char>(std::cout),
[](char c) { return std::toupper(c); });
std::cout << "\n";
// Underline title
std::cout << prefix << std::setfill('-') << std::setw(title.size()) << "" << "\n\n";
}
Here is the updated live demo with the above change.
You can use std::transform and to_upper to capitalize the string.
You can use std::string's two-parameter constructor which takes a length and a character to generate a sequence of - of the same length as the title
Together we get:
#include <iostream>
#include <string>
#include <algorithm>
void DisplayTitle(std::string aTitle) {
std::transform(aTitle.begin(), aTitle.end(), aTitle.begin(), toupper);
std::cout << "\t" << aTitle << "\n";
std::cout << "\t" << std::string(aTitle.length(), '-') << "\n\n";
}
int main()
{
for (std::string title; std::getline(std::cin, title); )
{
DisplayTitle(title);
}
}
demo on godbolt

C++ Error in creating the file (name based on other file name)

I have a problem with creating a file, whose name is a little bit modified from some other file's name.
But if the new name is not based on another name - the program works - but I need to use that first method.
I used backslash (\b) to remove ".srt" from the original file name to modify the copy - in this program, I cannot modify path_file_1 and path_file_2, so I cannot just miss the extension and add it later when I finished preparing the copy.
Here's the code:
#include <iostream>
#include <fstream>
int main()
{
std::cout << "Starrting!" << std::endl;
std::string path_file_1 = "Sub-File1.srt";
std::string path_file_2 = "Sub-File2.srt";
std::string path_file_new = path_file_1 + "\b\b\b\b-corr.srt";
//std::string path_file_new = "Sub-File1-corr.srt";
//this works!
std::cout << path_file_1 << std::endl;
std::cout << path_file_new << std::endl;
//Creating a new file
std::fstream file;
file.open(path_file_new, std::ios::out | std::ios::binary);
if (!file)
{
std::cout << "Error in creating file!!!";
return 0;
}
std::cout << "File created successfully." << std::endl;
file.close();
}
Here's the output:
Starrting!
Sub-File1.srt
Sub-File1-corr.srt
Error in creating file!!!
Adding \b\b\b\b to your string adds 4 backspace characters. It does not remove 4 chars from the string.
This would work:
std::string path_file_new = path_file_1.substr(0, path_file_1.size()-4) + "-corr.srt";
As others have stated, you can't use backslash characters to remove characters, you would need to use string::substr() instead in this particular situation.
If you are using C++17 or later, you can use the <filesystem> library to manipulate file paths more easily, eg:
#include <iostream>
#include <fstream>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
std::cout << "Starrting!" << std::endl;
fs::path path_file_1 = "Sub-File1.srt";
fs::path path_file_new = path_file_1.stem(); // removes the extension...
path_file_new += "-corr.srt";
std::cout << path_file_1 << std::endl;
std::cout << path_file_new << std::endl;
//Creating a new file
std::ofstream file(path_file_new, std::ios::binary);
if (!file.is_open())
{
std::cout << "Error in creating file!!!";
return 0;
}
std::cout << "File created successfully." << std::endl;
file.close();
}
Online Demo
Using backspaces for this won't cut it, unfortunately. Displaying the filename is misleading because they will have the desired effect on the display, but the filename itself will not be correct because it will contain actual backslash characters.
Instead, you want what Ted says in his answer - make a shortened version of the original string and add the desired suffix.

Assertion failure when writing to a text file using ofstream

I am trying to write some string data to a .txt file that i read from the user but after doing so, the program shuts down instead of continuing and when i check the results inside the .txt file i see some part of the data and then some gibberish, followed by an assertion failure error! Here's the code:
#include "std_lib_facilities.h"
#include <fstream>
using namespace std;
using std::ofstream;
void beginProcess();
string promptForInput();
void writeDataToFile(vector<string>);
string fileName = "links.txt";
ofstream ofs(fileName.c_str(),std::ofstream::out);
int main() {
// ofs.open(fileName.c_str(),std::ofstream::out | std::ofstream::app);
beginProcess();
return 0;
}
void beginProcess() {
vector<string> links;
string result = promptForInput();
while(result == "Y") {
for(int i=0;i <= 5;i++) {
string link = "";
cout << "Paste the link skill #" << i+1 << " below: " << '\n';
cin >> link;
links.push_back(link);
}
writeDataToFile(links);
links.clear(); // erases all of the vector's elements, leaving it with a size of 0
result = promptForInput();
}
std::cout << "Thanks for using the program!" << '\n';
}
string promptForInput() {
string input = "";
std::cout << "Would you like to start/continue the process(Y/N)?" << '\n';
std::cin >> input;
return input;
}
void writeDataToFile(vector<string> links) {
if(!ofs) {
error("Error writing to file!");
} else {
ofs << "new ArrayList<>(Arrays.AsList(" << links[0] << ',' << links[1] << ',' << links[2] << ',' << links[3] << ',' << links[4] << ',' << links[5] << ',' << links[6] << ',' << "));\n";
}
}
The problem lies probably somewhere in the ofstream writing procedure but i can't figure it out. Any ideas?
You seem to be filling a vector of 6 elemenents, with indices 0-5, however in your writeDataToFile function are dereferencing links[6] which is out of bounds of your original vector.
Another thing which is unrelated to your problem, but is good practice:
void writeDataToFile(vector<string> links)
is declaring a function which performs a copy of your vector. Unless you want to specifically copy your input vector, you most probably want to pass a const reference, like tso:
void writeDataToFile(const vector<string>& links)

Unexpected output when reading from getline into a non-empty string

I get confused with the "istream& getline (istream& is, string& str)"function, and according to http://www.cplusplus.com/reference/string/string/getline/, the following program:
#include <iostream>
#include <sstream>
int main()
{
std::istringstream s("this is a test");
std::string line = "line ";
getline( s, line );
std::cout << line << std::endl;
s.str("test again");
getline( s, line );
std::cout << s.str() << std::endl;
std::cout << line << std::endl;
return 0;
}
I expect the output to be:
line this is a test
test again
test again
but when I test it on Visual Studio, the output is :
this is a test
test again
this is a test
Could anyone explain the frustrating function for me ?
Clear the error flags between the calls to getline:
int main()
{
std::istringstream s("this is a test");
std::string line = "line ";
getline( s, line );
std::cout << line << std::endl;
s.str("test again");
s.clear() // <<<--------------- to clear error flags
getline( s, line );
std::cout << s.str() << std::endl;
std::cout << line << std::endl;
return 0;
}
The first getline sets eofbit on the stream. The second one then fails and line stays intact.
With the fix, you'll get:
this is a test
test again
test again
because getline doesn't add to the string, it replaces the content.
Whatever value line has prior to the call will not matter, as from the documentation for std::getline:
Calls str.erase()
Your second logical error is due to reusing a stream once you've reached its end.

ostringstream breaks cout?

I want to output the content of a ostringstream to some other stream (for example std::cout). I know that I can use std::ostringstream::str() but I assume it has an overhead on copying the stream contents to a string and then further to the other stream. I found that I could use std::ostringstream::rdbuf() (Comment suggesting that has 25 votes). But it breaks std::cout as is shown in the output of the test program below. Am I doing something wrong?
#include <iostream>
#include <sstream>
int main(int argc, char const *argv[])
{
std::ostringstream ss;
ss << "some data" << std::endl;
std::cerr << std::cout << std::endl;
std::cout << "start" << std::endl;
std::cout << ss.str();
std::cout << ss.rdbuf();
std::cout << "end" << std::endl;
std::cerr << std::cout << std::endl;
return 0;
}
Results in:
0x6013b8
start
some data
0
Your problem is that the rdbuf() buffer for an ostringstream is, as you might expect from the name, write only (the ostringstream returns the string through the str() method). You can't read the data back out of it through the buffer pointer.
Change your ostringstream to stringstream and it should work fine.