Read during a few second in C++ - c++

I want to know how can i read the standard input just for 5 seconds like you just have 5 seconds to write.
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string mystr;
cout << "What's your name? ";
getline (cin, mystr);
cout << "Hello " << mystr << ".\n";
cout << "What is your favorite team? ";
getline (cin, mystr);
cout << "I like " << mystr << " too!\n";
return 0;
}
Like that the user have all the time he want to write. Did getline or read have any option to force the getline to stop after 5sec ?
Thank you

A possible solution is to use poll() and write your own getline() function (tested on xubuntu 18.04 with g++ 7.5.0):
Here the implementation of my getline_timeout(int, std::string):
std::string getline_timeout(int ms, std::string def_value)
{
struct pollfd fds;
fds.fd = STDIN_FILENO;
fds.events = POLLIN;
int ret = poll(&fds, 1, ms);
std::string val;
if (ret > 0 && ((fds.revents & POLLIN) != 0)) {
//cout << "has data" << endl;
std::getline(std::cin, val);
} else {
//cout << "timeout / no data" << endl;
val = def_value;
}
return val;
}
#include <iostream>
#include <string>
#include <poll.h>
#include <unistd.h>
std::string getline_timeout(int ms, std::string def_value);
int main(int argc, char *argv[])
{
std::cout << "What's your name ? " << std::flush;
// Ask for the name
std::string mystr = getline_timeout(5000, "John Doe");
std::cout << "Hello " << mystr << std::endl;
std::cout << "What is your favorite team ? " << std::flush;
// Ask for the team
mystr = getline_timeout(5000, "Gryffindor");
std::cout << "I like " << mystr << " too!" << std::endl;
return 0;
}

The API getline() can not do what you want.
There are two way you can try:
- multi thread can work
- single thread with multiplexing IO like select/poll/epoll/iocp
In fact, they work same : setting a timer and wait for I/O input or timeout.

Related

Placing Printed text in the same line as text before it

I'm currently making a basic program design to behave somewhat like a chell. The code is here:
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <Windows.h>
#include <Stdio.h>
#include <string>
using namespace std;
main()
{
SetConsoleTextAttribute (GetStdHandle(STD_OUTPUT_HANDLE),10);
std::string name;
std::string pass;
std::string msg;
int x = 1;
srand(time(0));
cout << "Booting up system..." << endl;
cout << "Serial Code: " << (rand()%1000) << "." << endl;
cout << "Username: ";
std::getline(std::cin, name);
cout << "Password: ";
std::getline(std::cin, pass);
cout << "" << endl;
while (true)
{
cout<<x<<": ";
std::getline(std::cin, msg);
x += 1;
if (msg == "Hello!"){
cout << "Hi!" << endl;
}
if (msg == ""){
cout << "[No Text Inserted]" << endl;
}
system ("pause");
}
And, if no text is input it displays:
1:
[No Text Inserted]
How do I get this output?
1: [No Text Inserted]
Thank you in advance!
-DJ
In your if statements, store the string into a variable and print out in the end. Also if you're comparing the same variable, I recommend using if else statements. It makes it more readable. So:
string output;
if (msg == "Hello!)
{
output = "Hi!";
}
else if (msg == "")
{
output = "[No Text Inserted]";
}
output = x.str() + ": " + output;
cout << output << endl;
Try that out and let me know if that works.
What you could do is remember input cursor position and if the input is empty string, go back to that position and print your fail message, something like this:
#include <iostream>
#include <string>
#include <windows.h>
int main()
{
HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE);
std::string input;
std::cout << "Enter something: ";
// remember cursor position
CONSOLE_SCREEN_BUFFER_INFO info;
COORD inputPos = GetConsoleScreenBufferInfo(conout, &info) ? info.dwCursorPosition : COORD{ 0, 0 };
if (!std::getline(std::cin, input) || input.empty())
{
SetConsoleCursorPosition(conout, inputPos);
std::cout << "[No Text Inserted]" << std::endl;
}
}

C++ Console Application, Outputting Incorrect Data

I've been working on a simple console application and was stopped when, upon compiling my latest code, it began outputting strings of text and integers which did not match what I have entered.
The purpose of the program thus far is simple: to input a string of data and for it to output correctly multiple times in the console application. Below I have linked the pseudocode.
Thanks in advance.
#include <iostream>
#include <string>
void printIntro();
void RunApp();
bool RequestRestart();
std::string GetAttempt();
int main() // entry point of the application
{
printIntro();
RunApp();
RequestRestart();
return 0;
}
void printIntro() {
// introduce the program
constexpr int WORD_LENGTH = 8; // constant expression
std::cout << "Welcome to the Bull and Cow guessing game\n";
std::cout << "Can you guess the " << WORD_LENGTH;
std::cout << " letter isogram I am thinking of?\n\n";
return;
}
void RunApp()
{
// loop for number of attempts
constexpr int ATTEMPTS = 5;
for (int count = 1; count <= ATTEMPTS; count++)
{
std::string Attempt = GetAttempt();
std::cout << "You have entered " << GetAttempt << "\n";
std::cout << std::endl;
}
}
std::string GetAttempt()
{
// receive input by player
std::cout << "Enter your guess: \n";
std::string InputAttempt = "";
std::getline(std::cin, InputAttempt);
return InputAttempt;
}
bool RequestRestart()
{
std::cout << "Would you like to play again?\n";
std::string Response = "";
std::getline(std::cin, Response);
std::cout << "Is it y?: \n" << (Response[0] == 'y'); //response must be in brackets
return false;
}
You have to change this line
std::cout << "You have entered " << GetAttempt << "\n";
instd::cout << "You have entered " << Attempt << "\n";
In this way you do not print the address of the function, just like you did before, but the variable in which you stored the return value of the GetAttempt function.
You are printing a pointer to GetAttempt. Instead print Attempt:-
std::cout << "You have entered " << Attempt << "\n";

Floating Point Exception while reading from file

the program should read from 2 files (author.dat and citation.dat) and save them into a map and set;
first it reads the citationlist without problem, then it seems to properly read the authors and after it went through the whole list (author.dat) a floating point exception arises .. can't quite figure out why
seems to happen in author.cpp inside the constructor for authorlist
author.cpp:
#include <fstream>
#include <iostream>
#include "authors.h"
using namespace std;
AuthorList::AuthorList(char *fileName) {
ifstream s (fileName);
int idTemp;
int nrTemp;
string nameTemp;
try {
while (true){
s >> idTemp >> nrTemp >> nameTemp;
cout << idTemp << " " << nrTemp << " " << nameTemp << " test_string";
authors.insert(std::make_pair(idTemp,Author(idTemp,nrTemp,nameTemp)));
if (!s){
cout << "IF-CLAUSE";
throw EOFException();
}
cout << "WHILE-LOOP_END" << endl;
}
} catch (EOFException){}
}
author.h:
#ifndef CPP_AUTHORS_H
#define CPP_AUTHORS_H
#include <iostream>
#include <map>
#include <string>
#include "citations.h"
class Author {
public:
Author (int id, int nr, std::string name) :
articleID(id),
authorNR(nr),
authorName(name){}
int getArticleID() const {
return articleID;
}
std::string getAuthorName() const {
return authorName;
}
private:
int articleID;
int authorNR;
std::string authorName;
};
class AuthorList {
public:
AuthorList(char *fileName);
std::pair<std::multimap<int,Author>::const_iterator, std::multimap<int,Author>::const_iterator> findAuthors(int articleID) {
return authors.equal_range(articleID);
}
private:
std::multimap<int,Author> authors;
};
#endif //CPP_AUTHORS_H
programm.cpp:
#include <iostream>
#include <cstdlib>
#include "citations.h"
#include "authors.h"
#include "authorCitation.h"
using namespace std;
int main(int argc, char *argv[]){
CitationList *cl;
AuthorList *al;
//check if argv array has its supposed length
if (argc != 4){
cerr << "usage: programm article.dat citation.dat author.dat";
return EXIT_FAILURE;
}
//inserting citation.dat and author.dat in corresponding lists (article.dat not used)
cl = new CitationList(argv[2]);
al = new AuthorList(argv[3]);
try {
AuthorCitationList *acl;
acl->createAuthorCitationList(al,cl);
acl->printAuthorCitationList2File("authorcitation.dat");
} catch (EOFException){
cerr << "something went wrong while writing to file";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
All files:
https://drive.google.com/file/d/0B734gx5Q_mVAV0xWRG1KX0JuYW8/view?usp=sharing
I am willing to bet that the problem is caused by the following lines of code:
AuthorCitationList *acl;
acl->createAuthorCitationList(al,cl);
You are calling a member function using an uninitialized pointer. I suggest changing the first line to:
AuthorCitationList *acl = new AuthorCitationList;
Add any necessary arguments to the constructor.
While you are at it, change the loop for reading the data also. You have:
while (true){
s >> idTemp >> nrTemp >> nameTemp;
cout << idTemp << " " << nrTemp << " " << nameTemp << " test_string";
authors.insert(std::make_pair(idTemp,Author(idTemp,nrTemp,nameTemp)));
if (!s){
cout << "IF-CLAUSE";
throw EOFException();
}
cout << "WHILE-LOOP_END" << endl;
}
When you do that, you end up adding data once after the end of line has been reached. Also, you seem to have the last line in the wrong place. It seems to me that it should be outside the while loop.
You can use:
while (true){
s >> idTemp >> nrTemp >> nameTemp;
// Break out of the loop when reading the
// data is not successful.
if (!s){
cout << "IF-CLAUSE";
throw EOFException();
}
cout << idTemp << " " << nrTemp << " " << nameTemp << " test_string";
authors.insert(std::make_pair(idTemp,Author(idTemp,nrTemp,nameTemp)));
}
cout << "WHILE-LOOP_END" << endl;
You can simplify it further by using:
while (s >> idTemp >> nrTemp >> nameTemp){
cout << idTemp << " " << nrTemp << " " << nameTemp << " test_string";
authors.insert(std::make_pair(idTemp,Author(idTemp,nrTemp,nameTemp)));
}
cout << "WHILE-LOOP_END" << endl;

having issues comparing strings

For some reason it skips over the first input an goes straight to the second one.
#include<iostream>
#include<string>
using namespace std;
int stringWork()
{
const int LENGTH = 40;
char firstString[LENGTH], secondString[LENGTH];
cout << "Enter First String: ";
//it skips over this following line
cin.getline(firstString, LENGTH);
cout << "Enter Another String: ";
cin.getline(secondString, LENGTH);
if (strcmp(firstString, secondString) == 0)
cout << "You entered Same string two times\n";
else
cout << "The two strings you entered are not the same\n";
system("pause");
return 0;
}
int main()
{
stringWork();
return 0;
}
it only allows input for one string
This piece of code works on my machine just fine. However, please do change #include <string> to #include <string.h> or #include <cstring>, and add #include <stdlib.h> or #include <cstdlib>.
Fix the code like this:
#include <iostream>
#include <string>
void stringWork()
{
const int LENGTH = 40;
char firstString[LENGTH], secondString[LENGTH];
std::cout << "Enter First String: " << std::flush;
std::cin.getline(firstString, LENGTH);
std::cout << "Enter Another String: " << std::flush;
std::cin.getline(secondString, LENGTH);
if (strcmp(firstString, secondString) == 0) {
std::cout << "You entered Same string two times." << std::endl;
} else {
std::cout << "The two strings you entered are not the same." << std::endl;
}
}
int main()
{
stringWork();
return 0;
}
Some notes about my version of your code:
Please don't use using namespace std.
Use std::flush to flush the characters in the output stream. This is necessary because usually the characters are only flushed with std::endl or in some implementations if you add a newline character.
Avoid mixing C and C++ code as you did. Use the std::getline method to read a line directly into a std::string. Shown in the next example.
Please care about your code style, especially if you post it in the public.
A even better implementation would avoid any C code and use just C++:
#include <iostream>
#include <string>
void stringWork()
{
std::cout << "Enter First String: " << std::flush;
std::string firstString;
std::getline(std::cin, firstString);
std::cout << "Enter Another String: " << std::flush;
std::string secondString;
std::getline(std::cin, secondString);
if (firstString == secondString) {
std::cout << "You entered Same string two times." << std::endl;
} else {
std::cout << "The two strings you entered are not the same." << std::endl;
}
}

C++ - Boolean operation

I have this (I've just started to learn btw):
#include <iostream>
#include <string>
using namespace std;
int main()
{
string mystr;
cout << "Welcome, what is your name? ";
getline(cin, mystr);
cout << "Nice to meet you, " << mystr << endl;
cout << "May i call you 1 for short? (y/n)" << endl;
getline(cin, mystr);
}
I want to next say;
cout << "Thank you, 1" << endl;
OR:
cout << "Well ok, " << mystr << endl;
... based on whether or not the user has typed y or n. How would i go about this? I've had a look around but i don't really know how to word it. I'm using Visual Studio Express and it is a console application.
For a very simple way:
if (mystr == "1") {
// ...
}
But you should accustom yourself to more error checking, so check the state of the stream after getline:
getline(cin, mystr);
if (cin) {
if (mystr == "1") {
// ...
}
} else {
// error
}
And of course, you may want to support any number in the future, not just 1. Then you need to convert the input string to a number. See std::stoi if you use C++11, or look at the thousands of past Stackoverflow questions about string-to-number conversions :)
Edit: Just noticed that you actually wanted to check for "y". Well, that's the same then:
if (mystr == "y") {
// ...
}
You should use if-else statement. For example
#include <cctype>
//...
std::string name = mystr;
std::cout << "May i call you 1 for short? (y/n)" << std::endl;
std::getline( std::cin, mystr );
for ( char &c : mystr ) c = std::tolower( c );
if ( mystr == "y" )
{
name = "1";
std::cout << "Thank you, " << name << std::endl;
}
else
{
std::cout << "Well ok, " << name << std::endl;
}