How to read string in text file then loop to another string? - c++

I have been tackling this problem for almost two sleepless(?) weeks now. I'm creating a program that will read from a text file and prints getline() with a period '.' delimiter. I want to read each sentence AND also check for the strings "[INT]" and the like.
This program is a rudimentary text-based visual novel, and thus needs choices, stats and save algorithms.
#include <iostream>
#include <cstdlib>
#include <string>
#include <fstream>
#include <ctype.h>
using namespace std;
#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define ENTER 13
#define ESC 27
#define BACKSPACE 8
int main()
{
if(!loadfile)
{
cout<<"\n\n[Load a Saved File First.]\n\n\n\n";
system("pause");
//loadgame(); unimportant for now
}
menu = true;
system("cls");
ifstream novel("Novels\\main.vnt");
fstream backlog;
backlog.open("backlog.txt");
pagex=0;
/*while(pagex!=page)
{
//loop until pagex = page
}*/
string title = "title ", line;
getline(novel, line);
system(("title "+line).c_str());
while(menu)
{
c=0;
switch((c=getch()))
{
case KEY_DOWN:
getline(novel, line, '.');
line += ".";
backlog<<line;
page++;
cout<<line;
break;
case KEY_UP:
while(getline(backlog, logline))
{
cout<<logline;
system("pause");
}
break;
//case 's':
//case 'S':
// savegame(1, 's'); unimportant for now
case ESC:
menu = false;
//goto character; unimportant for now
break;
case ENTER:
/*In this part, the code should loop (using page as a counter)
until it reaches one of the special formats (like "[INT]",
"[PAT]", "[CHOICE]" and so on*/
break;
}
//character:
//character(); unimportant for now
system("pause");
return 0;
}
As for the format of the story:
Hello there.
[CHOICE]:
[INT]: I'm so smart.
[PAT]: I'm so patient.
[CHR]: I'm so charming.
[SAN]: I'm so sane.
[INT](
Yeah, right. I can't even finish this sente
)
[PAT}(
Yeah, right. You do know you should pass this tomorrow, right?
)
[CHR](
Yeah, right. Why does my heart beat fast?
)
[SAN](
Hurr, durr.
)
I've tried reading a line and saving it instead rather than using a number, but due to the sentence-based printing, I can't just up and save a line and expect the user to understand where he left off when he reads
"ere are you?", said the maid. Apparently, standardiza"
Please help.

Related

Use If statement / conditional to output data to one file or another file C++

New to C++. I have a #define variable (global variable? Not sure what these are called in C++) which I can set to a 1 or a 0. If it is == 1, I want my code to output my data to "File_A.txt". If it == 0, I want my code to output the data to "File_B.txt".
I tried to use an if statement when initializing the output file:
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
#define value 1
...
if (value == 1){
ofstream fout("File_A.txt");
} else if (value == 0){
ofstream fout("File_B.txt");
}
but it seems like doing this makes the code not recognize fout as the output file identifier when I try to close the file fout << endl; and rather it thinks that fout is an undeclared variable... When I try to compile, it returns the classic error error: ‘fout’ was not declared in this scope.
I feel like this should be pretty simple, haha. Let me know if I need to supply more specifics. I tried to keep this brief and straight to the point.
Thanks
Here's a code fragment, based on Sam Varshavchik's comment:
std::ofstream fout; // Don't assign to a file yet.
//...
char const * p_filename = nullptr;
switch (value)
{
case 0: p_filename = "File_B.txt"; break;
case 1: p_filename = "File_A.txt"; break;
}
fout.open(p_filename);
In the above example, the filename is determined first, based on value, then the file stream variable is opened using the filename.
Edit 1: Alternative
An alternative is to determine the filename first, then declare the file stream:
char const * p_filename = nullptr;
switch (value)
{
case 0: p_filename = "File_B.txt"; break;
case 1: p_filename = "File_A.txt"; break;
}
std::ofstream fout(p_filename);

How to detect user input of CTRL-X in C++

I need to end my function once the user inputs CTRL-X or '/'. I don't know how to detect/check for a user input of CTRL-X.
The task given to me states:
'When you edit the file, you will enter data line by line and when done, you will enter ‘/’ or CTRL + X to exit.'
I have written this code so far. I'm a beginner so pardon my code.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string data;
int line_num=1;
ofstream editFile;
editFile.open("edit_test.txt");
while(data!="/"){ //some kind of condition ORed with the condition already present in while loop?
cout<<line_num<<"> "; //I want to display line numbers every time the user presses enter
getline(cin, data);
if(data!="/"){
editFile<<data<<endl;
line_num++;
}
}
editFile.close();
return 0;
}
CTRL+X is the same as character code 24 (since X is the 24th letter of the alphabet). Barring any system interference*, all you need to do is check to see if character code 24 is in the input.
while (getline( std::cin, s ))
{
// Find ^C in s
auto n = s.find( '\x18' );
if (n != s.npos) s = s.substr( 0, n );
// process s normally here
// If ^C was found in s, we're done reading input from user
if (n != s.npos) break;
}
CTRL+X doesn’t tend to have any special system actions attached to it, so you shouldn’t have any problem getting it as input.

C++ Keylog Not Working Properly

I'm trying to make a simple keylogger in C++ (for learning only) and it's not quite working how I would like it to. My goal is to have it write to a txt. Here's the code I have so far:
#include <iostream>
#include <fstream>
#include <conio.h>
#define LOG(x) logger << x;
int main()
{
using std::ofstream;
using std::fstream;
ofstream logger("logger.txt", fstream::app);
char ascii;
bool typing;
for(;;)
{
if(_kbhit())
{
typing = true;
ascii = getch();
while(typing == true) //tried 'if', doesn't work
{
LOG(ascii);
std::cout << ascii << std::endl;
//typing = false;
//break
//tried using the above two and didn't work
}
}
else typing = false;
}
logger.close();
}
When I make while(typing == true) continuous, the key that is pressed continuously gets printed, but at least it actually gets saved to the txt. When I try to make the loop stop after one keyboard click, nothing gets saved to the txt.
So what am I doing wrong? Thanks for any help!
The variable typing is never set to false, so it stays true and your loop continues. The following code works:
#include <fstream>
#include <conio.h>
int main()
{
std::ofstream logger("logger.txt", std::fstream::app);
for(char ascii; ascii != 3;)
{
ascii = getche();
logger << ascii;
}
return 0;
}
getche() prints the character typed, and 3 is the ASCII code for Ctrl+C. This logs all characters, even non-printable ones.
A few comments on your code:
Don't use macros (#define) unless you are substituting a large amount of code and using it often, or plan on changing what something does.
You use loops and variables where you don't need to. getch and related functions wait for input.
logger.close() is automatically done when logger goes out of scope and is destructed.
return 0 should be at the end of main. It's not necessary, but it is used to return to the OS and return 0, although automatically put in, is important to have in for clarity.
I personally don't use using statements. Just write out the namespace, it helps avoid collisions. That's why it's in a namespace.

Proper character by character input?

To better familiarize myself with C++, I'm redoing an old college OS assignment: program your own shell. The first thing I tackled was accepting commands but my approach leaves some features to be desired. Here's what I have:
string GetLine() {
string line;
char input = _getch();
while (input != 13) {
switch (input) {
case 8: // backspace
if (line.length() != 0) {
line = line.substr(0, line.length() - 1);
cout << "\b \b";
}
break;
case -32: // all arrows' first byte
input = _getch(); // distinctly different arrow byte
switch (input) {
case 72: // up
break;
case 80: // down
break;
case 75: // left
break;
case 77: // right
break;
}
break;
case 9: // tab
break;
default:
line += input;
cout << input;
break;
}
input = _getch();
}
cout << endl;
return line;
}
It works pretty well and I know I have more to do with the arrow keys (if I'm even distinguishing between them correctly as is). The main problem I'm asking about is a certain situation where the cursor has wrapped to the next line on the terminal. Aiming to emulate cmd.exe I print a prompt and wait at the end of it for the user's input. When this prompt is long, it only takes a few characters before my command runs across two lines. If I just type it out and let it wrap around and press enter everything works fine. If I wrap to the second line and want to backspace back to the first line, the cursor stops at the first character on it's new line and won't "unwrap" back to the first line as I'd hope. What can I do here to achieve this unwrapping behaviour?
I think the problem is that trying to print '\b' won't unwrap, but I don't have an idea for an alternative and I am hoping that I don't have to treat this as a special case and that code that will backspace in the middle of a line will also work at the beginning of a line.
You need to use the winapi, SetConsoleCursorPosition will help you. Here is a minimal example that moves the cursor up one row from the current position:
#include <iostream>
#include <windows.h>
int main() {
std::cout << "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaa";
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
csbiInfo.dwCursorPosition.Y -= 1; // Move Y coordinate up by one
SetConsoleCursorPosition(hStdout, csbiInfo.dwCursorPosition);
std::cin.get();
}
Also, Console Functions has an entire list of all the necessary functions to control the console. You will want to use these in your program.
You will need to make your own screen buffer with CreateConsoleScreenBuffer and then set it as the buffer first. Then after that handle everything written and read from the console yourself.

Getting arrow keys from cin

I am sure this must have been asked before, but a quick search found nothing.
How can I get the arrow/direction keys with cin in c++?
It has indeed been asked before, and the answer is that you cannot do it.
C++ has no concept of a keyboard or a console. It only knows of an opaque input data stream.
Your physical console preprocesses and buffers your keyboard activity and only sends cooked data to the program, usually line-by-line. In order to talk to the keyboard directly, you require a platform-specific terminal handling library.
On Linux, this is usually done with the ncurses or termcap/terminfo libraries. On Windows you can use pdcurses, or perhaps the Windows API (though I'm not familiar with that aspect).
Graphic-application frameworks such as SDL, Allegro, Irrlicht or Ogre3D come with full keyboard and mouse handling, too.
Here is a pointer if you dont mind using getch() located in conio.h.
#include <stdio.h>
#include <conio.h>
#define KB_UP 72
#define KB_DOWN 80
#define KB_LEFT 75
#define KB_RIGHT 77
#define KB_ESCAPE 27
int main()
{
int KB_code=0;
while(KB_code != KB_ESCAPE )
{
if (kbhit())
{
KB_code = getch();
printf("KB_code = %i \n",KB_code);
switch (KB_code)
{
case KB_LEFT:
//Do something
break;
case KB_RIGHT:
//Do something
break;
case KB_UP:
//Do something
break;
case KB_DOWN:
//Do something
break;
}
}
}
return 0;
}