Check input is a valid integer [duplicate] - c++

This question already has answers here:
How to determine if a string is a number with C++?
(36 answers)
Closed 10 months ago.
Hi Can anyone help me please. I need to check that my input only contains integers. Im guessing from looking it up that I use the isDigit function but I am not sure how to use this to check the whole number.
I'm using C++ to interact with MSI so i'm getting the integer as follows:
hr = WcaGetProperty(L"LOCKTYPE",&szLockType);
ExitOnFailure(hr, "failed to get the Lock Type");
I think i have to change szLockType to a char and then use isdigit to scan through each character but i am not sure how to implement this. Any help would be greatly appreciated. P.s im a beginner so please excuse if this is a really trivial question..:)

Use std::stoi(). You'll get an exception if the string is not an integer value.

What's the type of szLockType?
Is it a a null-terminated char-string?
Then you can use the array syntax to get individual characters.
for(int i = 0; i < std::strlen(szLockType); i++) {
if(!std::isDigit(szLockType[i])) {
// it contains a non-digit - do what you have to do and then...
break; // ...to exit the for-loop
}
}
Or is it a std::string? Then the syntax is slightly different:
for(int i = 0; i < szLockType.length(); i++) {
if(!std::isDigit(szLockType.at(i)) {
// it contains a non-digit - do what you have to do and then...
break; // ...to exit the for-loop
}
}

Even better, with modern C++ you can do this:
#include <algorithm>
#include <cctype>
auto lambda = [](auto elem)
{
return std::isdigit(elem);
};
return std::all_of(szLockType, szLockType + strlen(szLockType), lambda);
Your choice as to whether you prefer a named lambda or regular, anonymous lambda.
FYI it is std::isdigit rather than isDigit.
https://en.cppreference.com/w/cpp/string/byte/isdigit

Related

Having issues with basic a basic string operation [c++, visual studio 2013]

[RESOLVED]
I'm reading in lines from a .txt file that stores scrambled up radio messages, not that it matters. One of the lines is called "it" and some of it's opening characters are numbers, the numbers are followed by a '/'. I'm trying to export these first few numbers into a string(called "s1") so it can be later be used as a single integer, here's the code that is supposed to do that:
for (i = 0; i < it.find('/'); i++)
{
s1[i] = it[i];
}
cout << s1;
but i get a string subscript range error message, what did i screw up?
EDIT
Issue is resolved now, thank you for helping out an absolute newbie :D My mistake was not knowing how strings work, for an actual answer from someone who understands the issue find Ben Voigt's replies. Correct code is: s1+= it[i];
You most likely attempted to assign outside of the allocated memory for s1.
Assuming it and s1 are std::string:
for (auto c : it)
{
if (c == '/')
{
break;
}
s1 += c;
}
cout << s1;
I'm assuming the line you originally have is of the type std::string.
The error message "subscript out of range" basically tells that you are trying to access a invalid position of an array, in your case, a string. This commonly happens when the number between brackets [ ] is out of range of the container.
One way to avoid this type of bug is to use iterator. By using iterators, you can traverse through the entire container without manually calling operator[].
Consider the following code for a simple idea, this would separate the part before / from the original string and save it to the new variable:
#include <iostream>
#include <string>
int main() {
std::string s = "42/fortytwo";
std::string result = "";
for (std::string::iterator it=s.begin(); it!=s.end(); ++it) {
if (*it == '/') break;
result += *it;
}
std::cout << result;
return 0;
}
Note:
To use iterators, a class must have correctly implemented * (unary operator), !=, ++, begin(), end() operators.
For a more consistence usage, a const iterator can be used.

c++ if(cin>>input) doesn't work properly in while loop

I'm new to c++ and I'm trying to solve the exercise 6 from chapter 4 out of Bjarne Stroustrups book "Programming Principles and Practise Using C++ and don't understand why my code doesn't work.
The exercise:
Make a vector holding the ten string values "zero", "one", ...,
"nine". Use that in a program that converts a digit to its
corresponding spelled-out value: e.g., the input 7 gives the output
seven. Have the same program, using the same input loop, convert
spelled-out numbers into their digit form; e.g., the input seven gives
the output 7.
My loop only executes one time for a string and one time for an int, the loop seems to continue but it doesn't matter which input I'm giving, it doesn't do what it's supposed to do.
One time it worked for multiple int inputs, but only every second time. It's really weird and I don't know how to solve this in a different way.
It would be awesome if someone could help me out.
(I'm also not a native speaker, so sorry, if there are some mistakes)
The library in this code is a library provided with the book, to make the beginning easier for us noobies I guess.
#include "std_lib_facilities.h"
int main()
{
vector<string>s = {"zero","one","two","three","four","five","six","seven","eight","nine"};
string input_string;
int input_int;
while(true)
{
if(cin>>input_string)
{
for(int i = 0; i<s.size(); i++)
{
if(input_string == s[i])
{
cout<<input_string<<" = "<<i<<"\n";
}
}
}
if(cin>>input_int)
{
cout<<input_int<<" = "<<s[input_int]<<"\n";
}
}
return 0;
}
When you (successfully) read input from std::cin, the input is extracted from the buffer. The input in the buffer is removed and can not be read again.
And when you first read as a string, that will read any possible integer input as a string as well.
There are two ways of solving this:
Attempt to read as int first. And if that fails clear the errors and read as a string.
Read as a string, and try to convert to an int. If the conversion fails you have a string.
if(cin >> input) doesn't work properly in while loop?
A possible implementation of the input of your program would look something like:
std::string sentinel = "|";
std::string input;
// read whole line, then check if exit command
while (getline(std::cin, input) && input != sentinel)
{
// use string stream to check whether input digit or string
std::stringstream ss(input);
// if string, convert to digit
// else if digit, convert to string
// else clause containing a check for invalid input
}
To discriminate between int and string value you could use peek(), for example.
Preferably the last two actions of conversion (between int and string) are done by separate functions.
Assuming the inclusion of the headers:
#include <iostream>
#include <sstream>

Want to read important double value at the end of line of istream C++

I'm trying to read in a large matrix calculated from a text file for a finite element code. The matrix is spatially dependent though and thus I need to be able to conveniently organize the data. The outside source that calculated the values for the matrix was kind enough to put the following lines at the top of the text file
No. activity levels : 3
No. pitch-angles : 90
No. energies : 11
No. L-shells : 10
Which basically tell me the number of positions the matrix is known at. I want to be able to easily pick out these values because it will allow me to preallocate the size of the matrix, as well as know immediately how much I need to interpolate for values not given by this text file. I am trying to do that with the following code
#include<iostream>
#include<fstream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<vector>
using namespace std;
int main(){
string diffusionTensorFileName = "BAS_drift_averaged_chorus_kp.txt";
string sline;
int alphaSize=0;
ifstream diffusionTensorFile(diffusionTensorFileName.c_str());
while(getline(diffusionTensorFile,sline)){
if(strncmp(sline.c_str(),"No. pitch-angles : 90",sline.size()-1)==0 && sline.size()-1 != 0){
alphaSize = atoi(sline.c_str());
printf("alphaSize %d \n", alphaSize);
vector<double> alpha(alphaSize);
}
}
}
atoi of course doesn't work very well, and I can't seem to get strtod or any of those functions to work either. Any thoughts? I'm also open to this being the completely wrong way to do this and alternate suggestions on how to proceed.
I think the easiest way would be to use the scan_is method of the std::ctype facet imbued in the streams locale. Its job is to search for first character that matches a given classification and return a pointer to it. We'll take the result of that call and use std::stoi (C++11) to parse it into an integer.
std::locale loc(diffusionTensorFile.getloc());
auto& f = std::use_facet<std::ctype<char>>(loc);
while (std::getline(diffusionTensorFile, sline))
{
const char* begin = sline.front(),
end = sline.back() + 1;
const char* result;
if ((result = f.scan_is(f.digit, begin, end)) != end)
{
alphaSize = std::stoi(result);
// do something with alphaSize
}
}
Live Demo

Comparing a string of quiz answers to questions

I have a C++ test question that asks us to write a program that:
1) asks the user to input a string of answers a,b,c, and d: (Example: ACDBDA)
2) asks he user to input a string that is the answer key: (example DBADCD) (we also need to put in something to make sure the length of the answer key is the same as the answers, but that is no biggie)
3) prints the percentage of input answers that were correct, ie match up with the answer key.
Most of this isn't too bad, but I'm not sure how to go about comparing the two strings to see how they differ. Is there any way to get a variable equal to one of the characters in the string which could then be compared with a variable representing the character in the same place as the other string? That's the only way that comes to mind for me. I'm not really looking for a specific code or someone to do it for me, just need some pointers in the right direction.
Thanks!
Ok, so I've made some progress on this and I think I am close. The problem now is that I'm getting "Expression must be of class type" error on the commented lines. I think the issue is in the way I am passing my parameters but I can't seem to figure out how to fix it :(. I've google'd several parameter passing articles but none seem to speak to passing a parameter then getting it's length or comparing it as I do in the program. Any help would be greatly appreciated. Here is the code:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
string getAnswers(string answers)
{
cout << "What are your answers to this questionless quiz? BE WARY OF CHOOSING INCORRECTLY\n:";
cin >> answers;
return answers;
}
string getKey(string key)
{
cout << "Just kidding. What are the answers? \n:";
cin >> key;
return key;
}
double getPercentage(double percentage)
{
int total;
int correct;
getAnswers();
getKey();
total = getAnswers.size(); // "error: expression must have class type"
for (i=0; i>total; i++)
{
int j = 0;
if (getAnswers.at(j) = getKey.at(j)) // "error: expression must have class type" (for both getAnswers and getKey)
correct++;
j++;
}
percentage = (correct/total) * 100;
}
int main()
{
getAnswers();
getKey();
cout << getPercentage(answers, key); //Also I'm really not sure how to get the parameters from previous functions into this one here. Maybe I shoudln't even add parameters and just show the function?
return 0;
}

check if a pointer has some string c++

I am not good with c++ and I cannot find this anywhere, please apologize me if it is a bad question. I have a pointer and I want to know if some names store in this pointer begins with some specific string. As in python something like (maybe it is a bad example):
if 'Pre' in pointer_name:
This is what I have:
double t = 0;
for (size_t i =0; i < modules_.size(); ++i){
if(module_[i].name() == "pre"){ // here is what I want to introduce the condition
if (modules_[i].status() == 2){
std::cout << module_[i].name() << "exists" << std::endl;
}
}
}
The equivalent of Python 'Pre' in string_name is:
string_name.find("Pre") != std::string::npos // if using string
std::strstr(pointer_name, "Pre") // if using char*
The equivalent of Python string_name.startswith('Pre') ("begins with some specific string") is:
string_name.size() >= 3 && std::equal(string_name.begin(), string_name.begin() + 3, "Pre"); // if using string
string_name.find("Pre") == 0 // less efficient when it misses, but shorter
std::strncmp(pointer_name, "Pre", 3) == 0 // if using char*
In two of those cases, in practice, you might want to avoid using a literal 3 by measuring the string you're searching for.
Check std::string::find, there are enough good examples. If you are using c-style string, use strstr.
You can use the algorithm header file to do most of things usually one liners in python.
In this case though it might be just easier to use string find method .
If your name variable is of type std::string then you can use name().compare("Pre") == 0 for string comparison.
EDIT: Seems I misunderstood the question, for contains you can use string find, as other said.
Using C style strings, char * is not recommended in C++. They are error prone.