How to log all input (cin) into file in C++ - c++

Actually, I'm working on a minishell. My functions work, but when I want to log the whole cin stuff (commands, parameters, output) into a file, nothing appears in the file. Nowhere can I find something to handle with full input and output with parameters.
I hope someone can help me.
My code:
using namespace std;
ofstream outputFile;
void read_command(char *com, char **par){
fprintf(stdout, "$");
cin >> com;
outputFile.open("logging.txt"); // file opened but nothing APPEARS IN IT????
if(strcmp(com,"date")== 0){ // DATE
time_t rawtime;
time ( &rawtime );
printf ( "%s", ctime (&rawtime) );
}
else if(strcmp(com,"echo")== 0) // ECHO
{
string echo_part;
cin >> echo_part;
cout << echo_part << endl;
}
else if(strcmp(com,"sleep")== 0){ // SLEEP
int howlong = 0;
cin >> howlong;
cout << "seconds: " << howlong << "....zZZzzZzz" << endl;
sleep(howlong);
}
else if(strcmp(com,"ps")== 0) // PROCESS
{
execlp("/bin/ps","ps","-A",NULL); // ps - command
}
}
void handler(int p) { // CTR-C handler
cout << endl;
cout << "Bye !" << endl;
outputFile.close();
alarm(1); // 2 seconds alarm ends process with kill
}
int main(){
int childPid;
int status;
char command[20];
char *parameters[60];
signal(SIGINT,&handler); // CTR-C exit disabled
while (1) {
read_command(command, parameters);
if ((childPid = fork()) == -1) {
fprintf(stderr,"can't fork\n");
exit(1);
}
else if (childPid == 0) { //child
execv(command, parameters);
exit(0);
}
else { // parent process
wait(&status);
}
}
}

You re-open the output stream outputFile for every line, overwriting the file with each new command.
Edit: As the other posters noted, not actually writing something to outputFile might be a second reason.

You open outputFile, but never write anything to it. What should appear there?
To output something to the file, try
outputFile << something

there are no
outputFile << ...;
so you are not writing to the file

Your code contains a lot of potential memory access violations.
There are libraries to help you in what you are trying to do (reading and interpreting user input), for instance the GNU Readline library, which is coded in C (but can be used by C++ code, as is the case for all the C-written libraries).
There are some nice C++ wrappers, such as for instance SReadlineWrapper.

Related

Trying to make something write to a file in c++

I tried programming a file writer, but when i try to write to a file with something that has multiple words it will suddenly create files.
My code
#include <fstream>
#include <iostream>
#include <unistd.h>
int main(int argc, char *argv[]) {
char cwd[256];
while (true) {
getcwd(cwd, 256);
std::string cwd_s = (std::string)cwd;
std::string Input;
std::cout << cwd_s << "> ";
std::cin >> Input;
std::ofstream file(Input);
std::cout << "cmd /";
std::cin >> Input;
file << Input;
};
for (int i; i < argc; i++) {
std::cout << argv[i] << '\n';
};
return 0;
}
I expected to get this:
C:\Users\code> File.txt
cmd /hello world!
File.txt
hello world!
But it only had "hello", it created another file named world!
I have tried changing the code, but to no avail.
So I have wrote this code that I think does what you expect. The behavior you were seing is because you used the same string to store the filename and the user input. Also you redefined a new file every loop (without closing the previous one). I added a signal handler since if you press Ctrl+C the program would quit without saving/closing the file.
I added comments about how you can make a better CLI interface (if you're interested)
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
std::ofstream outfile;
void signalHandler(int signum) {
outfile.close();
exit(signum);
}
int main() {
char cwd[256];
if (getcwd(cwd, sizeof(cwd)) != NULL) {
std::cout << cwd << "> ";
} else {
std::cerr << "Error: Could not get current working directory." << std::endl;
return 1;
}
std::string filename;
std::getline(std::cin, filename);
outfile.open(filename);
// We intercept the Ctrl+C signal to close the file before exiting. Else nothing will be written to it.
// You can also use Ctrl+D (EOF: End Of File) to exit the program.
// The best praticte would be to implement a command line interface with a "quit" command. (like a map<string, function> for example)
signal(SIGINT, signalHandler);
// Another good practice is to check if the file did open correctly.
if (!outfile.is_open()) {
std::cerr << "Error: Could not open file for writing." << std::endl;
return 1;
}
std::cout << "cmd / ";
char ch;
while (std::cin.get(ch)) {
outfile.put(ch);
if (ch == '\n') {
std::cout << "cmd / ";
}
}
outfile.close();
return 0;
}
Hope it will help you ! And if you have any question about the code feel free to ask I'll explain !

Segmentation fault: unable to fix the problem

I'm new to C++, and I'm trying to write a project that interacts through command line. Right now, whenever I run my main (which is the executable), I always receive a segmentation fault error when the main program finished.
Edit comment:
I'm told by tutor to use as little as C++ features such as vectors or strings ... I'm also very new to C++, so i'm trying to utilize as many basic C functions as I can.
I'm
My main function looks like this:
int main(int argc, char** argv) {
cout << "starting mvote..." << endl;
int run_flag = 1;
char* actionBuffer = (char*)malloc(100 * sizeof(char));
char* action = (char*)malloc(16 * sizeof(char));
char* readPtr;
char exit[4] = { 'e','x','i','t' };
//parse command line argumentand get the filename
char* filename = argv[2];
cout << filename;
FILE* fp;
char line[64];
//from here, I'm opening the file and read it by lines
fp = fopen(filename, "r");
if (fp == NULL) {
cout << "file not exists";
return -1;
}
while (fgets(line, 64, fp) != NULL) {
cout << line << "\n";
}
fclose(fp);
while (run_flag == 1) {
cout << "what do you want?\n " << endl;
cin.getline(actionBuffer, 1024);
if (strcmp(actionBuffer, exit) == 0) {
cout << "bye!";
run_flag = 0;
break;
}
//if not exit, Look for the space in the input
readPtr = strchr(actionBuffer, ' ');
int size = readPtr - actionBuffer;
//extract the operation
strncpy(action, actionBuffer, size);
for (int i = 0; i < size; i++) {
cout << "operation:" << action[i];
}
// depend on the operation specified before the first empty space
run_flag = 0;
}
free(actionBuffer);
free(action);
return 0;
}
Description:
I first try to open up a csv file which lies in the same folder as main, and I read the file line by line. Then, I just implement a simple command where you can type exit and quit the program.
I allocate two memory, actionBuffer and action, which are used to hold command
Problem: a segmentation fault [core dumped] always exists when I type exit and hit enter, and then the process finished.
Research: So I learned that segmentation fault is due to accessing a memory that does not belongs to me. But where in my program am I trying to access such a memory?
Any advice is appreciated! Thank you.
Just to give you an idea, this would be an example of C++ code
#include<iostream>
#include<fstream>
#include<string_view>
#include<string>
#include<sstream>
#include<exception>
int main(int argc, char** argv) {
std::cout << "starting mvote...\n";
//parse command line argumentand get the filename
std::string filename = argv[2]; // NO CHECKS!
std::cout << filename <<'\n';
//from here, I'm opening the file and read it by lines
{
std::ifstream ifs(filename);
if (!ifs) {
throw std::invalid_argument("file not exists");
}
std::string line;
while (std::getline(ifs, line)) {
std::cout << line << '\n';
}
}
bool run_flag = true;
while (run_flag) {
std::cout << "what do you want?\n";
std::string userInput;
std::getline(std::cin, userInput);
if (userInput == "exit") {
std::cout << "bye!\n";
return 0;
}
std::stringstream userInputSs(userInput);
std::string operation;
while(userInputSs >> operation){
std::cout << "operation: " << operation << '\n';
}
}
}

How do I write a message in the Protocol Buffer C++ tutorial?

I am new to Protocol Buffers and inexperienced with C++, I am trying to complete the tutorial at https://developers.google.com/protocol-buffers/docs/cpptutorial
I've created the proto file mentioned in the tutorial and gotten addressbook.pb.h and addressbook.pb.cc from this proto. I am trying to follow the segment "Writing A Message", so I copied and pasted the following code from the tutorial. I immediately run into an issue in the main function, which I'll explain below:
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
using namespace std;
// This function fills in a Person message based on user input.
void PromptForAddress(tutorial::Person* person) {
cout << "Enter person ID number: ";
int id;
cin >> id;
person->set_id(id);
cin.ignore(256, '\n');
cout << "Enter name: ";
getline(cin, *person->mutable_name());
cout << "Enter email address (blank for none): ";
string email;
getline(cin, email);
if (!email.empty()) {
person->set_email(email);
}
while (true) {
cout << "Enter a phone number (or leave blank to finish): ";
string number;
getline(cin, number);
if (number.empty()) {
break;
}
tutorial::Person::PhoneNumber* phone_number = person->add_phone();
phone_number->set_number(number);
cout << "Is this a mobile, home, or work phone? ";
string type;
getline(cin, type);
if (type == "mobile") {
phone_number->set_type(tutorial::Person::MOBILE);
} else if (type == "home") {
phone_number->set_type(tutorial::Person::HOME);
} else if (type == "work") {
phone_number->set_type(tutorial::Person::WORK);
} else {
cout << "Unknown phone type. Using default." << endl;
}
}
}
// Main function: Reads the entire address book from a file,
// adds one person based on user input, then writes it back out to the same
// file.
int main(int argc, char* argv[]) {
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
if (argc != 2) {
cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
return -1;
}
tutorial::AddressBook address_book;
{
// Read the existing address book.
fstream input(argv[1], ios::in | ios::binary);
if (!input) {
cout << argv[1] << ": File not found. Creating a new file." << endl;
} else if (!address_book.ParseFromIstream(&input)) {
cerr << "Failed to parse address book." << endl;
return -1;
}
}
// Add an address.
PromptForAddress(address_book.add_person());
{
// Write the new address book back to disk.
fstream output(argv[1], ios::out | ios::trunc | ios::binary);
if (!address_book.SerializeToOstream(&output)) {
cerr << "Failed to write address book." << endl;
return -1;
}
}
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
In the main function the code exits without prompting for any inputs due to this portion:
if (argc != 2) {
cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
return -1;
}
which appears as one of the first few lines in the function, before any inputs are requested. I read that argc will be the number of inputs. I'm confused because I copied and pasted exactly what the tutorial wrote, but it doesn't appear to be running correctly.
That code expects a file name to be passed on the command line, not read from stdin. You've not specified what platform you're on, but you'll do something like my_program.exe C:\some\file\somewhere on Windows or ./my_program /some/file/somewhere on Linux/Mac/Other Unix like OS. If you're running the program from your IDE's run/debug function then you'll need to configure it to pass the name of the file as a command line argument. How to do that will depend on what IDE you're using.

When compiling code antivirus says it's virus and delete it

Hi i try to make code in c++. This code only makes text file easy encrypted and save into a new file. And when i compile this code antivirus says, it is virus/spyware Gen:Variant.Kazy.20825. I dont know why it is virus.
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void controlParameters(int argc){ //check if input parameters are ok
if(argc == 1){
cout << "Pokud chcete text zasifrovat, spustte program s parametrem: -enc \"Nazev_souboru.txt\"\n";
cout << "Pokud ho chcete desifrovat, spustte program s parametrem: -dec \"Nazev_souboru.txt\"\n";
}else if(argc > 3){
cout << "Moc parametru. Spustte si program bez parametru.\n";
}else if(argc < 3){
cout << "Chybi jeden parametr. Spustte si program bez parametru.\n";
}else{
cout << "Vsechno vypada zatim dobre\n";
}
}
void encryption(string &file); //encrypt text file
void decryption(string &file); //decrypt text file
bool controlFile(string &file); //check if file can be opened
int main(int argc, char **argv){
controlParameters(argc);
string file;
file = argv[2];
if(controlFile(file)){
}else{
cout << "Soubor nesel nacist." << endl;
return -1;
}
cout << "Ukonceno.\nZmacknete ENTER pro pokracovani..."<<endl;
cin.get();
return 0;
}
bool controlFile(string &file){
ifstream ifs;
ifs.open(file);
if(ifs.is_open()){
ifs.close();
return true;
}else{
ifs.close();
return false;
}
}
void encryption(string &file){
ifstream ifs;
ofstream ofs;
string line;
ifs.open(file);
ofs.open("encrypt.txt");
if(ifs.is_open()){
while(!ifs.eof()){
getline(ifs,line);
int a = line.length();
int i = 0;
while(i < a){
ofs << ((char)(line[i]^100));
}
line.clear();
ofs << "\n";
}
}else{
cout << "Nelze nacist soubor" << endl;
}
}
void decryption(string &file){
ifstream ifs;
ofstream ofs;
string line;
ifs.open(file);
ofs.open("decrypt.txt");
if(ifs.is_open()){
while(!ifs.eof()){
getline(ifs,line);
int a =line.length();
int i = 0;
while(i < a){
ofs << ((char)(line[i]^100));
}
line.clear();
ofs << "\n";
}
}else{
cout << "Nelze nacist soubor" << endl;
}
}
It's good practice to exclude your source-control directories from virus scanners; they can cause performance and locking problems even if there are no false positives while performing source-control actions or compiling (I've seen it happen several times).
So if only to make your programming experience more reliable, disable the virus scanner on those directories.
You may still want to scan the final, released version of your executable to help avoid false positives: after all, even if it's not your fault the virus scanner chokes, it's not a good impression to leave behind on a user.
Antivirus software uses "heuristics" to determine what is a virus and what isn't. So it looks for patterns in the file that does things that it finds suspicious. I can't see anything directly wrong in your code, so I suspect it's a "false-positive". I personally don't like antivirus software, it causes more problems than it solves...
By the way, you could add the "output filename" to your encrypt/decrypt function, and make them one function! ;)

XCode will not take input from a file

For some reason, Xcode will not take input from a file, while Visual C++ will.
When I run this program in xcode, the variables numberRows and numberCols stay 0 (they are initialized to 0 in the main function).
When I run it in Visual C++ they become 30 and 30 (the top line of maze.txt is "30 30" without the quotes).
Any ideas why this is happening?
void readIn(int &numberRows, int &numberCols, char maze[][100]){
ifstream inData;
inData.open("maze.txt");
if (!inData.is_open()) {
cout << "Could not open file. Aborting...";
return;
}
inData >> numberRows >> numberCols;
cout << numberRows << numberCols;
inData.close();
return;
}
There is something else wrong.
Unfortunately it is hard to tell.
Try flushing the output to make sure you get the error message:
void readIn(int &numberRows, int &numberCols, char maze[][100])
{
ifstream inData("maze.txt");
if (!inData) // Check for all errors.
{
cerr << "Could not open file. Aborting..." << std::endl;
}
else
{
// Check that you got here.
cerr << "File open correctly:" << std::endl;
// inData >> numberRows >> numberCols;
// cout << numberRows << numberCols;
std::string word;
while(inData >> word)
{
std::cout << "GOT:(" << word << ")\n";
}
if (!inData) // Check for all errors.
{
cerr << "Something went wrong" << std::endl;
}
}
}
interesting, so I followed the following suggestion from this post http://forums.macrumors.com/showthread.php?t=796818:
Under Xcode 3.2 when creating a new
project based on stdc++ project
template the target build settings for
Debug configuration adds preprocessor
macros which are incompatible with
gcc-4.2:
_GLIBCXX_DEBUG=1
_GLIBXX_DEBUG_PEDANTIC=1
Destroy them if you want Debug/gcc-4.2
to execute correctly.