Let's say my program or another program did:
cout << "Hi" << endl;
And I want to read the last line entered into the console.
Something like:
string s=lastline();
s should have "Hi" as its contents.
Or to take it one step further, get the entire contents of the console put into something (vector, array, string, string stream, etc).
How would I go about doing this?
Related
Let's say you have a txt file, it currently holds content that's important. Currently the content is at such
"I like blue cats and yellow dogs."
but you want to update said content.
std::ofstream myFile;
myFile.open("file.txt");
myFile << "I like " << catColorStr << " cats and " << dogColorStr << " dogs.";
myFile.close();
But let's say for some reason your program crashes between line two and three or maybe the user's power cuts out or they use end process in windows task manager etc. Well you have just deleted the entire contents of file.txt. How do you go about accounting for this typically?
Is the typical way of dealing with this to open it as read only copy the contents to your program. Then copy that to a new tempfile or something. Then write to your actual file and if that succeeds deleting your tempfile else upon start you say your actual file = your temp file?
Typically, you create a new file, write to it, close it, then rename the new file to the old file.
std::ofstream myFile;
myFile.open("file.txt.new");
myFile << "I like " << catColorStr << " cats and " << dogColorStr << " dogs.";
myFile.close();
sys::filesystem::rename("file.txt.new", "file.txt");
// or POSIX rename or Windows or...
(Error checking omitted for brevity)
The rename operation atomically deletes the old file and gives the new file the old name. If somebody pulls the power cord in the middle of it, it's your operating system's problem, not yours. Modern OSes are quite good at dealing with it.
I have over 80 levels for my game and only one fails the salted sha1 hashing. The reason is salt is being added inside the level file instead of end of it.
The problem occurs only in Ubuntu 16.04 64-bit, works in Windows. It happens at every launch and being inserted to the same position every time.
Level file is 2 lines, first line is the level file and second line is the hash. So I get the first line and append salt to it. But problem is still same with single line file too.
Here is the minimized code:
int main() {
std::ifstream inf("level.txt");
std::string lvl_file;
std::getline(inf, lvl_file);
inf.close();
lvl_file += "MYSECRETSALT"; // lvl_file.append(..) also has same issue
std::cout << lvl_file << std::endl;
}
This code prints the whole level file but MYSECRETSALT gets inside of it not to the end of it. If I print the lvl_file before appending, it prints nicely without missing anything.
// IT SHOULD BE LIKE
...[0,26],[1,61]],"decor_2":[[0,25000]],"decor_3":[[0,25000]],"tiles_3":[[0,25000]]},"ghosts":[],"turrets":[]}MYSECRETSALT
// BUT IT PRINTS LIKE THIS
...[0,26],[1,61]],"decor_2":[[0,25000]],"decorMYSECRETSALT0]],"tiles_3":[[0,25000]]},"ghosts":[],"turrets":[]}
Level file is at bottom of this: https://hastebin.com/ayeduwucid.php
Hardcoding the file into stringstream works normally though.
std::stringstream inf;
inf << R"json(..)json";
That file was written in Windows, and it goes to second line with \n. When I checked it in hex, it actually puts \r\n which leads these problems.
I'm launching my program using the command line and the redirect symbol like so
program > out.txt
Is there a way some cout calls can ignore the > operator and still be displayed in the console?
What I want is to have a console menu that will appear in the console, but the rest will get redirected to the file.
Thank you.
No, there isn't.
> redirects the whole stdout stream to a file, not particular writes to that stream. If you want to write to multiple locations, you are to use multiple streams. For example, you could use stderr:
cout << "redirected" << endl;
cerr << "not redirected" << endl;
You could reformat what you are doing and use std::cout when you want to go to stdout, and a Log function that writes to a file you specify as the input to the progam.
It might be neater still to have a Menu function which displays to std::cout, and the Log file able to be configured as to where it ends up.
Okay, so let's say I have a program that couts a line while the user may be typing in information.
For this example, let's say we're using the code
cout << "THIS CODE IS BEING COUTED" << endl;
Let's say for our example, the user is in the process of typing up an input and as it stands they have only entered "hello", but has not yet pressed enter.
As it stands, when the line is executed, the user will see
"helloTHIS CODE IS BEING COUTED"
and they will be given a new line to input information.
What I want to do is instead of cout'ing, I would like to get the text in the current input, erase it from the input, cout the line that needs to be cout'ed, and then re-enter the info into the input.
Does this make sense or is this a bunch of jumbled nonsense?
Thanks for reading.
Edit: Clarification: I want it so if I have a string entered into my input and I cout, that the cout will be displayed above my input instead of inserting it past my input. I also want my input to be unaffected so the user can continue typing or delete what was already entered.
If you are getting the input character by character then when you need to output your text you could move the output position to the start of the line by printing carriage return, '\r'. Then your output will overwrite the current input, after which print a line feed and reprint what has been input so far
cout << "\r" << output << "\n" << currentinput;
If the output is shorter than the input then you will only partially overwrite the input, in which case you could pad the output with spaces up to the length of the current input
You may ask user in one, main thread with cin >> data there and read data from stdin in other thread by fread or something like that what works with FILE* handle.
After the data you want was typed by user you may clear screen (for example by clrscr() in conio.h or by any other better way) and cout what you want.
Hi this might seem a bit noobie, but here we go. Im developing a program that downloads leaderboards of a certain game from the internet and transforms it into a proper format to work with it (elaborate rankings, etc).
The files contains the names, ordered by rank, but between each name there are 7 random control codes (obivously unprintable). The txt file looks like this:
..C...hName1..)...&Name2......)Name3..é...þName4..Ü...†Name5..‘...QName6..~...bName7..H...NName8..|....Name9..v...HName10.
Checked via an hexEditor and saw the first control code after each name is always a null character (0x00). So, what I do is read everything, and then cout every character. When a 0x00 character is found, skip 7 characters and keep couting. Therefore you end up with the list, right?
At first I had the problem that on those random control codes, sometimes you would find like a "soft EOF" (0x1A), and the program would stop reading there. So I finally figured out to open it in binary mode. It worked, and then everything would be couted... or thats what I thought.
But I came across another file which still didn't work, and finally found out that there was an EOF character! (0x0A) Which doesn't makes sense since Im opening it in binary mode. But still, after reading that character, C++ interprets that as a new file, and hence skips 7 characters, so the name after that character will always appear cut.
Here's my current code:
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
int main () {
string scores;
system("wget http://certainwebsite/001.txt"); //download file
ifstream highin ("001.txt", ios::binary);
ofstream highout ("board.txt", ios::binary);
if (highin.is_open())
{
while ( highin.good() )
{
getline (highin, scores);
for (int i=0;i<scores.length(); i++)
{
if (scores[i]==0x00){
i=i+7; //skip 7 characters if 'null' is found
cout << endl;
highout << endl;
}
cout << scores[i];
highout << scores[i]; //cout names and save them in output file
}
}
highin.close();
}
else cout << "Unable to open file";
system("pause>nul");
}
Not sure how to ignore that character if being already in binary mode doesn't work. Sorry for the long question but I wanted to be detailed and specific. In this case, the EOF character is located before the Name3, and hence this is how the output looks like:
http://i.imgur.com/yu1NjoZ.png
By default getline() reads until the end of line and discards the newline character. However, the delimiter character could be customized (by supplying the third parameter). If you wish to read until the null character (not until the end of line), you could try using getline (highin, scores, '\0'); (and adjusting the logic of skipping the characters).
I'm glad you figured it out and it doesn't surprise me that getline() was the culprit. I had a similar issue dealing with the newline character when I was trying to read in a CSV file. There are several different getline() functions in C++ depending on how you call the function and each seems to handle the newline character differently.
As a side note, in your for loop, I'd recommend against performing a method call in your test. That adds unnecessary overhead to the loop. It'd be better to call the method once and put that value into a variable, then enter the loop and test i against the length variable. Unless you expect the length to change, calling the length() method each iteration is a waste of system resources.
Thank you all guys, it worked, it was the getline() which was giving me problems indeed. Due to the 'while' loop, each time it found a new line character, it restarted the process, hence skipping those 7 characters.