How to only store specific characters of the user's input? - c++

I want to store the value of specific characters from the user input? like for example:
#include <iostream>
#include <string>
int main(){
int useryear;
std::cout << "\n\tType your favourite year:\n";
std::cout << "\t >> ";
std::cin.ignore(0);
getline(std::cin, useryear);
return 0;
}
So, for example the user entered 1933
How to store only the 19??
or the first two characters they typed?
I think to store the 33 i have to change "cin.ignore(0);" to "cin.ignore(2);"

Personally I would opt for Remy's suggestion (from the comments) if given the choice.
That being said, you could limit the number of characters you read using one of the get overloads of istream.
#include <string>
#include <iostream>
#include <limits>
int main()
{
std::string buffer(3, '\0');
if (std::cin.get(buffer.data(), 3))
{
try
{
const int year{std::stoi(buffer)};
std::cout << "Year: " << year << '\n';
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
catch(const std::invalid_argument& ex)
{
std::cerr << "Invalid input" << '\n';
}
}
}

Related

Having trouble with std::string::compare() return values in c++

Relatively new to c++.
Having trouble understanding an issue I am having with the compare() function returning 1 instead of 0.
I have a program which reads a text file containing an arbitrary number of questions and answers for a quiz. It is formatted as such:
Q: How many days in a week?
A: seven
I have three files, main.cpp, Quiz.cpp, and Quiz.h:
main.cpp:
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include "Quiz.h"
using namespace std;
int main(int argc, char* argv[]){
srand(unsigned(time(0)));
vector<Quiz> quizVector;
ifstream inputQuiz;
inputQuiz.open(argv[1]);
string q, a;
int questionCount = 0;
if(inputQuiz.is_open()){
getline(inputQuiz, q);
getline(inputQuiz, a);
while(!inputQuiz.eof()){
Quiz *instance = new Quiz(q, a);
quizVector.push_back(*instance);
questionCount++;
getline(inputQuiz, q);
getline(inputQuiz, a);
}
}
random_shuffle(quizVector.begin(), quizVector.end());
string userInput;
for(int i = 0; i < questionCount; i++){
cout << quizVector[i].getQuestion() << endl;
cout << "A: ";
getline(cin, userInput);
if(quizVector[i].getAnswer().compare("A: " + userInput) == 0){
cout << "Correct." << endl;
}
else{
cout << "Incorrect." << endl;
}
}
return 0;
}
Quiz.cpp:
#include <string>
#include "Quiz.h"
int Quiz::score = 0;
std::string Quiz::getQuestion(){
return question;
}
std::string Quiz::getAnswer(){
return answer;
}
Quiz.h:
#ifndef QUIZ_H
#define QUIZ_H
class Quiz{
private:
std::string question {""};
std::string answer {""};
public:
Quiz() = default;
Quiz(std::string q, std::string a) : question {q}, answer {a} {}
std::string getQuestion();
std::string getAnswer();
};
#endif
My problem lies within main.cpp:
for(int i = 0; i < questionCount; i++){
cout << quizVector[i].getQuestion() << endl;
cout << "A: ";
getline(cin, userInput);
if(quizVector[i].getAnswer().compare("A: " + userInput) == 0){
cout << "Correct." << endl;
}
else{
cout << "Incorrect." << endl;
}
}
When I input the correct answer corresponding to each question, compare() does not return 0, but consistently returns 1. There are no leading or trailing spaces at the start or ends of each line in the text file. Am I misunderstanding how getline() or compare() works? Is it something else? Any help is appreciated!
I see a number of problems with this code:
std::random_shuffle() is deprecated in C++14 and removed in C++17, use std::shuffle() instead.
you are not validating that argv contains an input parameter before using it.
Your use of eof() in the while loop is wrong. For instance, if the last question/answer pair in the file is terminated by EOF instead of a line break, getline() will still return the question/answer to you, but it will also set the eofbit flag on the stream, which will cause eof() to return true and thus you will skip saving the last pair into the vector. The stream is not technically in a failed state yet in this situation (see the diagram at https://en.cppreference.com/w/cpp/io/basic_ios/eof), so you shouldn't skip the last pair if it terminates with EOF rather than a line break.
Your while loop is leaking memory.
you don't need questionCount at all, use quizVector.size() instead. Or better, a range-for loop.
you don't really need to use compare() at all, you can use operator== instead. But, if you do use compare(), you should take into account that it is case-sensitive (as is operator==). You should also take advantage of the fact that compare() lets you specify an index to start comparing from, so you can ignore the A: prefix in the stored answer (alternatively, you could just strip off the Q: and A: prefixes when storing the question/answer in Quiz's constructor). Otherwise, you can use your compiler's strcmpi() function instead (if it offers one).
Try something more like this instead:
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
#include <random>
#include <cctype>
#include "Quiz.h"
using namespace std;
string toLowercase(string s) {
transform(s.begin(), s.end(), s.begin(),
[](unsigned char c){ return tolower(c); }
);
return s;
}
int main(int argc, char* argv[]){
if (argc < 2){
cerr << "Please specify a file to open!" << endl;
return 0;
}
ifstream inputQuiz(argv[1]);
if (!inputQuiz.is_open()) {
cerr << "Can't open the file!" << endl;
return 0;
}
vector<Quiz> quizVector;
string q, a, userInput;
while (getline(inputQuiz, q) && getline(inputQuiz, a)) {
quizVector.emplace_back(q, a);
}
random_device rd;
mt19937 g(rd());
shuffle(quizVector.begin(), quizVector.end(), g);
for(auto &quiz : quizVector){
cout << quiz.getQuestion() << endl;
cout << "A: ";
getline(cin, userInput);
userInput = toLowercase(userInput);
a = toLowercase(quiz.getAnswer());
if (a == ("a: " + userInput)) {
// or:
// if (a.compare(2, string::npos, userInput) == 0) {
// or, if you strip off "A:" beforehand:
// if (a == userInput) {
cout << "Correct." << endl;
}
else {
cout << "Incorrect." << endl;
}
}
return 0;
}

Make console title bar display the value of a variable

I'm working on a small program that counts up to a number given by the user. The number they enter is stored in the variable limit. I want the number in that variable to be displayed in the title kind of like this: "Counting up to 3000" or "Limit set to 3000" or something like that. I've tried using SetConsoleTitle(limit); and other things but they just don't work. With the code that I have posted bellow, I get the following error:
argument of type "int" is incompatible with parameter of type "LPCWSTR"
I'm currently using Visual Studio 2015 if that's important in any way.
#include <iostream>
#include <windows.h>
#include <stdlib.h>
using namespace std;
int main()
{
begin:
int limit;
cout << "Enter a number you would like to count up to and press any key to start" << endl;
cin >> limit;
SetConsoleTitle(limit); // This is my problem
int x = 0;
while (x >= 0)
{
cout << x << endl;
x++;
if (x == limit)
{
cout << "Reached limit of " << limit << endl;
system("pause");
system("cls");
goto begin;
}
}
system("pause");
return 0;
}
The SetConsoleTitle() function expects a string as its argument, but you're giving it an integer. One possible solution would be to use std::to_wstring() to convert an integer to a wide-character string. C++ string that you get as a result has a different format from the null-terminated wide-character string that SetConsoleTitle() expects, so we need to make the necessary conversion using the c_str() method. So, instead of
SetConsoleTitle(limit);
you should have
SetConsoleTitle(to_wstring(limit).c_str());
Don't forget to #include <string> for to_wstring() to work.
If you want a title that includes more than just a number, you'll need to use a string stream (a wide character string stream in this case):
wstringstream titleStream;
titleStream << "Counting to " << limit << " goes here";
SetConsoleTitle(titleStream.str().c_str());
For string streams to work, #include <sstream>. Here's the full code:
#include <iostream>
#include <string>
#include <sstream>
#include <windows.h>
#include <stdlib.h>
using namespace std;
int main()
{
begin:
int limit;
cout << "Enter a number you would like to count up to and press any key to start" << endl;
cin >> limit;
wstringstream titleStream;
titleStream << "Counting to " << limit << " goes here";
SetConsoleTitle(titleStream.str().c_str());
int x = 0;
while (x >= 0)
{
cout << x << endl;
x++;
if (x == limit)
{
cout << "Reached limit of " << limit << endl;
system("pause");
system("cls");
goto begin;
}
}
system("pause");
return 0;
}

My while loops seems to be ignoring my getline

Here's all the code
#include <iostream>
#include <string>
#include <windows.h>
#include <stdlib.h>
using namespace std;
void Pdelay(string str)
{
for (char c : str)
{
std::cout << "" << c << "";
Sleep(100);
}
std::cout << '\n';
}
int main()
{
int exit = 1;
while (exit == 1)
{
cout<< "Type something\n:";
string str;
str.clear();
getline(cin,str);
Pdelay(str);
cout << "\n\n[1]Type something again"<< endl;
cout << "[2]Exit\n:";
cin >> exit;
}
return 0;
}
Whenever I run it, it works properly the first time round, when it loops back it skips the getline and continues with the two cout statements.
Immediately after you use cin, the newline remains in the buffer and is being "eaten" by the subsequent getline. You need to clear the buffer of that additional newline:
// immediately after cin (need to #include <limits>)
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
That's why it's not a very good idea to combine std::cin and std::getline. BTW, you can write your code in fully standard compliant C++11, with no additional non-library headers:
#include <chrono>
#include <iostream>
#include <limits>
#include <string>
#include <thread>
void Pdelay(std::string str)
{
for (char c : str)
{
std::cout << "" << c << "" << std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::cout << '\n';
}
int main()
{
int ext = 1;
while (ext == 1)
{
std::cout << "Type something\n:";
std::string str;
str.clear();
std::getline(std::cin, str);
Pdelay(str);
std::cout << "\n\n[1]Type something again" << std::endl;
std::cout << "[2]Exit\n:";
std::cin >> ext;
if(!std::cin) // extraction failed
{
std::cin.clear(); // clear the stream
ext = 1;
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
}
}
I just realized that this question has been asked (in a slightly modified form) before, and the answers are great:
Why does std::getline() skip input after a formatted extraction?

String manipulation, when converted show 0 in the beginning of the string

I want to know how can I make the string I converted from DWORD to onstringstream and then to AnsiString.
But that doesn't really matter, the conversion could be from int to string, I just want to know how I can make every string converted to ALWAYS show 6 digits, like if my number is 57, in the string it will be 000057.
Thanks!
Use io manipulators setfill and setw:
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
int main()
{
std::ostringstream s;
s << std::setfill('0') << std::setw(6) << 154;
std::cout << s.str() << "\n";
return 0;
}
So, the question about formatted output?
you can use iostream::width and `iostream::fill':
// field width
#include <iostream>
using namespace std;
int main () {
cout << 100 << endl;
cout.width(6);
cout.fill('0');
cout << 100 << endl;
return 0;
}

convert string to integer in c++

Hello
I know it was asked many times but I hadn't found answer to my specific question.
I want to convert only string that contains only decimal numbers:
For example 256 is OK but 256a is not.
Could it be done without checking the string?
Thanks
The simplest way that makes error checking optional that I can think of is this:
char *endptr;
int x = strtol(str, &endptr, 0);
int error = (*endptr != '\0');
In C++ way, use stringstream:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
stringstream sstr;
int a = -1;
sstr << 256 << 'a';
sstr >> a;
if (sstr.failbit)
{
cout << "Either no character was extracted, or the character can't represent a proper value." << endl;
}
if (sstr.badbit)
{
cout << "Error on stream.\n";
}
cout << "Extracted number " << a << endl;
return 0;
}
An other way using c++ style : We check the number of digits to know if the string was valid or not :
#include <iostream>
#include <sstream>
#include <string>
#include <cmath>
int main(int argc,char* argv[]) {
std::string a("256");
std::istringstream buffer(a);
int number;
buffer >> number; // OK conversion is done !
// Let's now check if the string was valid !
// Quick way to compute number of digits
size_t num_of_digits = (size_t)floor( log10( abs( number ) ) ) + 1;
if (num_of_digits!=a.length()) {
std::cout << "Not a valid string !" << std::endl;
}
else {
std::cout << "Valid conversion to " << number << std::endl;
}
}