How to check using isdigit() if there more than one character - c++

So, I'm still new on coding, and my friend is kindly taught me a lot and I want to be learn it quick, then he gave me this exercise to study in my home
He gave me this question about booking table number, so I tried to make it..
But I'm having trouble with this part checking the table number if it is a digit or not... I was searching on google on how, but they only give example on how to do it with single character.. So, I made an account then ask here xD
btw, the table max number is 25.
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<ctype.h>
bool checkDigit(char tablenum){
char digit[3];
int n;
int value = tablenum;
if(tablenum>0 && tablenum<10)
n=1;
if(tablenum>9 && tablenum < 26)
n=2;
for(int i=0;i<n;i++){
digit[i] = value%10;
value /= 10;
}
if(n==1){
printf("digit 0 = %d\nisdigit = %d\n",tablenum,isdigit(tablenum)); //just checking the isdigit value
if(isdigit(digit[0])!=0){
puts("It's digit");
return true;
}
else{
puts("It's not digit");
return false;
}
}
if(n==2){
printf("digit 0 = %d isdigit 0 = %d \ndigit 1 = %d isdigit 1 = %d\n",digit[0],isdigit(digit[0]),digit[1],isdigit(digit[1])); //checking the values too
if(isdigit(digit[0]) != 0 && isdigit(digit[1]) != 0){
puts("It's digits!");
return true;
}
else{
puts("It's not digits!");
return false;
}
}
else{
printf("It's not digit!")
return false;
}
}
int main(){
int num;
bool itsdigit;
do{
scanf("%d",&num);fflush(stdin);
itsdigit = checkDigit(num);
} while(itsdigit != 1 );
getchar();
return 0;
}
Input = "25" "1" "0" "test"
Output = "It's a digit" "It's a digit" "It's not a digit" "
Since the table is only 1 to 25
When I input "1" on it shows the right digit, but when it when in to isdigit() I keep getting 0.
I wonder what when wrong with this, and please give explanation.
And thanks before!

You have multiple problems.
Lets start by taking a closer look at these two lines:
checkDigit(num);
itsdigit = checkDigit;
The first line calls checkDigit but throws away the result.
The second line does not call the function, instead the compiler will let it decay to a pointer to the function and assign that pointer to itsdigit. Your compiler should have complained about it.
Furthermore, isdigit doesn't have to return 1 when the character is a digit, it only have to return something which is non-zero.
Lastly, in the digits array you don't store characters, you store integer values. isdigit(1) will be false while isdigit('1') will be true. Just because you use the type char doesn't automatically store characters in the variables. And considering that you read an integer, and store its digits in the digits array, there's no need to check if the digits are actually digits. Of course the digits will be digits.

You probably want this:
bool IsOnlyDigits(const char text[])
{
int length = strlen(text);
for (int i = 0; i < length; i++)
{
if (!isdigit(text[i]))
return false;
}
return true;
}
int main() {
char num[50];
scanf("%s", num);
if (IsOnlyDigits(num))
puts("It's digits!");
else
puts("It's not digits!");
fflush(stdout);
getchar();
return 0;
}
Disclaimer: non error checking and non bounds checking code. #includes omitted for brevity. Is has been tested under Visual Studio 2015 and seems to be working fine here.
Examples of input and output:
123
It's digits!
12a
It's not digits!
abc
It's not digits!
To understand this, you need to learn about strings and arrays. Just read the corrsponding chapters in your C textbook.

You could instead create an array of type char or int, iterate through the array and check if any character instance is a digit or not using the isdigit() function.
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char arr[10];
cin>>arr;
for(int i=0;i<strlen(arr);i++){
if(isdigit(arr[i])){
cout<<arr[i]<<" is a digit\n";
}
else {
cout<<arr[i]<<" is not a digit\n";
}
}
return 0;
}

Related

I am trying to convert octal number to decimal number using a string as an input but the answer is coming out to be wrong

This is the given code. I am accessing each element of the string and trying to multiply it with powers of 8 but, the result is coming out to be wrong.
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int od(string s)
{
reverse(s.begin(),s.end());
int ans=0;
for(int i=0;i<s.length();i++)
{
ans=ans+s[i]*pow(8,i);
}
return ans;
}
int main()
{
string s;
cin>>s;
cout<<od(s);
return 0;
}
The problem lies in the line:
ans=ans+s[i]*pow(8,i);
Here s[i] is a character. When numerical operations are performed with it, its ASCII value is taken. So here's an easy fix:
ans=ans+((s[i]-'0'))*pow(8,i);
This will give you the correct answers for obvious reasons.
This code is the issue
ans=ans+s[i]*pow(8,i);
string characters (chars) are ASCII, so "0" in ASCII is actually 48. ASCII mappings are here
https://en.cppreference.com/w/cpp/language/ascii
I suppose you could check each character and map it to the decimal value, or you could use something like std::stoi
std::stoi(myoctalstring, nullptr, 8);
https://en.cppreference.com/w/cpp/string/basic_string/stol
There are two issues: the string's elements are digits, not numbers ('0' is not the same thing as 0), and pow is a floating-point operation, which you should not use in conjunction with integers.
You can get the number that corresponds to a digit by subtracting '0' from it, and you can keep track of the current power of eight as you loop.
int od(string s)
{
reverse(s.begin(), s.end());
int ans = 0;
int power = 1;
for(int i = 0; i < s.length(); i++)
{
ans = ans + (s[i] - '0') * power;
power *= 8;
}
return ans;
}
but it's actually simpler to not reverse the string and multiply the temporary result on each step instead:
int od(string s)
{
int ans = 0;
for(int i = 0; i < s.length(); i++)
{
ans = ans * 8 + s[i] - '0';
}
return ans;
}
You need to use atoi or _ttoi, something like atoi(s[i]).

finding the number of possible decodings of the given number(dynamic programming)

I am trying to solve a problem where every letter has a respective number such as a-1,b-2....z-26.
Now given a number, in how many ways can the number be decoded is the question. consider an example where 25114 can be decoded as 'BEAN',‘BEAAD’, ‘YAAD’, ‘YAN’, ‘YKD’ and ‘BEKD’. this could be decoded in 6 ways.
I have written code in c++ but I am getting the wrong answer. Please correct my code.
#include<bits/stdc++.h>
using namespace std;
int total = 0;
int arr[100001];
void func(int start,int end,int factor){
if(start==end)
return;
int j =start;
if(factor==2&&j==end-1)//if j is the last element and factor is 2,accessing j+1 element is illegual
return;
if(factor==2){
if((arr[j]*10+arr[j+1])>26)
return;
else{
total++;
func(start+2,end,1);
func(start+2,end,2);
}
}
else{//factor is 1
total++;
func(start+1,end,1);
func(start+1,end,2);
}
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
int p;
cin>>p;
arr[i]=p;
}
func(0,n,1);
func(0,n,2);
cout<<total<<endl;
return 0;
}
essentially what my code is doing is that it fixes one number from the given array(using one digit or two digits from the the given array) and recurses until all the combinations are covered. for example considering the above case, I first choose '2' as my first digit and decode it as 'B'(factor = 1) and then choose '25' and decode it as 'E'(factor = 2).
**following are the input and output from the following code
input : 25114
expected output : 6
my output : 15
input : 3333333333(10 digits)
expected output : 1
my output : 10
Based on the original program from the question I suggest to count the encodings when you reach the end only (if(start==end)).
As func will always be called twice with factor=1 and factor=2, I can freely choose either condition for counting.
Here is the modified code:
#include<bits/stdc++.h>
using namespace std;
int total = 0;
int arr[100001];
void func(int start,int end,int factor){
if(start==end) {
if(factor == 1) total++; // count once when reaching the end
return;
}
int j =start;
if((factor==2) && (j==end-1))//if j is the last element and factor is 2,accessing j+1 element is illegal
return;
if(factor==2){
if((arr[j]*10+arr[j+1])>26)
return;
else{
//total++;
func(start+2,end,1);
func(start+2,end,2);
}
}
else{//factor is 1
//total++;
func(start+1,end,1);
func(start+1,end,2);
}
return;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
int p;
cin>>p;
arr[i]=p;
}
func(0,n,1);
func(0,n,2);
cout<<total<<endl;
return 0;
}
This calculates the expected results from the example input in the question.
$ echo 5 2 5 1 1 4|./program
6
$ echo 10 3 3 3 3 3 3 3 3 3 3|./program
1
There is room for improvement.
Instead of modifying a global variable I would return the number of combinations from func and add the values in the higher level.
I would also handle the distinction between 2-digit and 1-digit numbers in the called func instead of in the caller.
Something like this pseudo code:
int func(int start, int end)
{
if(remaining length is <2) {
// we reached the end, so this is one combination
return 1;
}
if(two-digit number is >26) {
// only a 1-digit number is possible, count remaining combinations
return func(start+1, end);
}
// both a 1-digit or 2-digit number is possible, add the remaining combinations for both cases
return func(start+1) + func(start+2);
}
Your question is tagged as "dynamic-programming", but it is anything but.
Instead, think about the state space and its boundary conditions:
The empty string has zero encodings;
A single digit has a single encoding;
An n-digit string has as many encodings as an (n-1)-digit substring plus as many encodings as an (n-2)-digit substring if the first two digits are <= 26.
Thus, we can walk the string from back to front and store the intermediate results for reuse:
uint64_t solve(std::vector<int>& digits) {
const int n = digits.size();
std::vector<int> encodings(n+1);
encodings[n] = 1;
for (int i = n-1; i >= 0; i--) {
bool two_digits_fit = (i < n - 1) && (digits[i] * 10 + digits[i+1]) <= 26; // What if digits[i] == 0?
encodings[i] = encodings[i+1] + (two_digits_fit ? encodings[i+2] : 0);
}
return encodings[0];
}

Checking if items from a particular txt file agree to constraints in c++ - Name That Number USACO

I have got some doubts while solving - Name That Number.
It goes like this -
Among the large Wisconsin cattle ranchers, it is customary to brand cows with serial numbers to please the Accounting Department. The cowhands don't appreciate the advantage of this filing system, though, and wish to call the members of their herd by a pleasing name rather than saying, "C'mon, #4734, get along."
Help the poor cowhands out by writing a program that will translate the brand serial number of a cow into possible names uniquely associated with that serial number. Since the cowhands all have cellular saddle phones these days, use the standard Touch-Tone(R) telephone keypad mapping to get from numbers to letters (except for "Q" and "Z"):
2: A,B,C 5: J,K,L 8: T,U,V
3: D,E,F 6: M,N,O 9: W,X,Y
4: G,H,I 7: P,R,S
Acceptable names for cattle are provided to you in a file named "dict.txt", which contains a list of fewer than 5,000 acceptable cattle names (all letters capitalized). Take a cow's brand number and report which of all the possible words to which that number maps are in the given dictionary which is supplied as dict.txt in the grading environment (and is sorted into ascending order).
For instance, brand number 4734 produces all the following names:
GPDG GPDH GPDI GPEG GPEH GPEI GPFG GPFH GPFI GRDG GRDH GRDI
GREG GREH GREI GRFG GRFH GRFI GSDG GSDH GSDI GSEG GSEH GSEI
GSFG GSFH GSFI HPDG HPDH HPDI HPEG HPEH HPEI HPFG HPFH HPFI
HRDG HRDH HRDI HREG HREH HREI HRFG HRFH HRFI HSDG HSDH HSDI
HSEG HSEH HSEI HSFG HSFH HSFI IPDG IPDH IPDI IPEG IPEH IPEI
IPFG IPFH IPFI IRDG IRDH IRDI IREG IREH IREI IRFG IRFH IRFI
ISDG ISDH ISDI ISEG ISEH ISEI ISFG ISFH ISFI
As it happens, the only one of these 81 names that is in the list of valid names is "GREG".
Write a program that is given the brand number of a cow and prints all the valid names that can be generated from that brand number or ``NONE'' if there are no valid names. Serial numbers can be as many as a dozen digits long.
Here is what I tried to solve this problem. Just go through all the names in the list and check which is satisfying the constraints given.
int numForChar(char c){
if (c=='A'||c=='B'||c=='C') return 2;
else if(c=='D'||c=='E'||c=='F') return 3;
else if(c=='G'||c=='H'||c=='I') return 4;
else if(c=='J'||c=='K'||c=='L') return 5;
else if(c=='M'||c=='N'||c=='O') return 6;
else if(c=='P'||c=='R'||c=='S') return 7;
else if(c=='T'||c=='U'||c=='V') return 8;
else if(c=='W'||c=='X'||c=='Y') return 9;
else return 0;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
freopen("namenum.in","r",stdin);
freopen("namenum.out","w",stdout);
string S; cin >> S;
int len = S.length();
freopen("dict.txt","r",stdin);
string x;
while(cin >> x){
string currName = x;
if(currName.length() != S.length()) continue;
string newString = x;
for(int i=0;i<len;i++){
//now encode the name as a number according to the rules
int num = numForChar(currName[i]);
currName[i] = (char)num;
}
if(currName == S){
cout << newString << "\n";
}
}
return 0;
}
Unfortunately, when I submit it to the judge, for some reason, it says no output produced that is my program created an empty output file. What's possibly going wrong?
Any help would be much appreciated. Thank You.
UPDATE: I tried what Some Programmer Dude suggested by adding a statement else return 0; at the end of the numOfChar function in case of a different alphabet. Unfortunately, it didn't work.
So after looking further at the question and exploring the information for Name That Number. I realized that it is not a current contest, and just a practice challenge. Thus, I updated my answer and also giving you my version of a successful submission. Nonetheless, that is a spoiler and will be posted after why your code was not working.
First, you forgot a } after the declaration of your number function. Secondary, you did not implement anything to check whether if the input fail to yield a valid name. Third, when you use numForChar() on the character of currName, the function yielded an integer value. That is not a problem, the problem is that it is not the ASCII code but is a raw number. You then compare that against a character of the input string. Of which, is an ASCII's value of a digit. Thus, your code can't never find a match. To fix that you can just add 48 to the return value of the numForChar() function or xor the numForChar() return's value to 48.
You are on the right track with your method. But there is a few hints. If you are bored you can always skip to the spoiler. You don't need to use the numForChar() function to actually get a digit value from a character. You can just use a constant array. A constant array is faster than that many if loop.
For example, you know that A, B, C will yield two and A's ASCII code is 65, B's is 66, and C's equal to 67. For that 3, you can have an array of 3 indexes, 0, 1, 2 and all of them stores a 2. Thus, if you get B, you subtract B's ASCII code 65 will yield 1. That that is the index to get the value from.
For getting a number to a character you can have a matrix array of char instead. Skip the first 2 index, 0 and 1. Each first level index, contain 3 arrays of 3 characters that are appropriate to their position.
For dictionary comparing, it is right that we don't need to actually look at the word if the length are unequal. However, besides that, since their dictionary words are sorted, if the word's first letter is lower than the range of the input first letter, we can skip that. On the other hand, if words' first letter are now higher than the highest of the input first letter, there isn't a point in continue searching. Take note that my English for code commenting are almost always bad unless I extensively document it.
Your Code(fixed):
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int numForChar(char c){
if (c=='A'||c=='B'||c=='C') return 2;
else if(c=='D'||c=='E'||c=='F') return 3;
else if(c=='G'||c=='H'||c=='I') return 4;
else if(c=='J'||c=='K'||c=='L') return 5;
else if(c=='M'||c=='N'||c=='O') return 6;
else if(c=='P'||c=='R'||c=='S') return 7;
else if(c=='T'||c=='U'||c=='V') return 8;
else if(c=='W'||c=='X'||c=='Y') return 9;
else return 0;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
ifstream fin("namenum.in");
ifstream dict("dict.txt");
ofstream fout("namenum.out");
string S;
fin >> S;
int len = S.length();
bool match = false;
string x;
while(dict >> x){
string currName = x;
if(currName.length() != S.length()) continue;
string newString = x;
for(int i=0;i<len;i++){
//now encode the name as a number according to the rules
int num = numForChar(currName[i]) ^ 48;
currName[i] = (char)num;
}
if(currName == S){
fout << newString << "\n";
match = true;
}
}
if ( match == false ){
fout << "NONE" << endl;
}
return 0;
}
Spoiler Code(Improved):
#include <fstream>
#include <string>
using namespace std;
// A = 65
// 65 - 0 = 65
const char wToN[] = {
// A ,B ,C ,D ,E ,F ,G ,H ,I ,
'2','2','2','3','3','3','4','4','4',
// J ,K ,L ,M ,N ,O ,P ,Q ,R ,S
'5','5','5','6','6','6','7','7','7','7',
// T ,U ,V ,W ,X ,Y ,Z
'8','8','8','9','9','9','9'
};
// 2 = {A, B, C} = 2[0] = A, 2[1] = B, 2[2] C
const char nToW[10][3] = {
{}, // 0 skip
{}, // 1
{'A','B','C'},
{'D','E','F'},
{'G','H','I'},
{'J','K','L'},
{'M','N','O'},
{'P','R','S'},
{'T','U','V'},
{'W','X','Y'}
};
int main(){
ifstream fin("namenum.in");
ifstream dict("dict.txt");
ofstream fout("namenum.out");
string S;
fin >> S;
// Since this will not change
// make this a const to make it
// run faster.
const int len = S.length();
// lastlen is last Index of length
// We calculate this value here,
// So we do not have to calculate
// it for every loop.
const int lastLen = len - 1;
int i = 0;
unsigned char digits[len];
unsigned char firstLetter[3];
// If not match print None
bool match = false;
for ( ; i < len; i++ ){
// No need to check upper bound
// constrain did not call for check.
if ( S[i] < '2' ) {
fout << "NONE" << endl;
return 0;
}
}
const char digit1 = S[0] ^ 48;
// There are 3 set of first letter.
// We get them by converting digits[0]'s
// value using the nToW array.
firstLetter[0] = nToW[digit1][0];
firstLetter[1] = nToW[digit1][1];
firstLetter[2] = nToW[digit1][2];
string dictStr;
while(dict >> dictStr){
// For some reason, when keeping the i = 0 here
// it seem to work faster. That could be because of compiler xor.
i = 0;
// If it is higher than our range
// then there is no point contineuing.
if ( dictStr[0] > firstLetter[2] ) break;
// Skip if first character is lower
// than our range. or If they are not equal in length
if ( dictStr[0] < firstLetter[0] || dictStr.length() != len ) continue;
// If we are in the letter range
// we always check the second letter
// not the first, since we skip the first
i = 1;
for ( int j = 1; j < len; j++ ){
// We convert each letter in the word
// to the corresponding int value
// by subtracting the word ASCII value
// to 65 and use it again our wToN array.
// if it does not match the digits at
// this current position we end the loop.
if ( wToN[dictStr[i] - 65] != S[j] ) break;
// if we get here and there isn't an unmatch then it is a match.
if ( j == lastLen ) {
match = true;
fout << dictStr << endl;
break;
}
i++;
}
}
// No match print none.
if ( match == false ){
fout << "NONE" << endl;
}
return 0;
}
I suggest you use c++ file handling. Overwriting stdin and stdout doesn't seem appropriate.
Add these,
std::ifstream dict ("dict.txt");
std::ofstream fout ("namenum.out");
std::ifstream fin ("namenum.in");
Accordingly change,
cin >> S --to--> fin >> S;
cin >> x --to--> dict >> x
cout << newString --to--> fout << newString

A cleaner way to convert a string to int after checking for hex prefix?

This little exercise is meant to get a string from the user that could be decimal, hexadecimal, or octal. 1st I need to identify which kind of number the string is. 2nd I need to convert that number to int and display the number in its proper format, eg:
cout <<(dec,hex,oct, etc)<< number;
Here's what I came up with. I'd like a simpler, cleaner way to write this.
string number = "";
cin >> number;
string prefix = "dec";
char zero = '0';
char hex_prefix = 'x';
string temp = "";
int value = 0;
for(int i =0; i<number.size();++i)
{
if(number[0] == zero)//must be octal or hex
{
if (number[0] == zero && number[1] == hex_prefix ) //is hex
{
prefix = "hex";
for(int i = 0; i < (number.size() - 2); ++i)
{
temp[i] = number[i+2];
}
value = atoi(temp.c_str());
}
//... code continues to deal with octal and decimal
You are checking number[0] twice, that's the first most obvious problem.
The inner if already checks both number[0] and number[1], I don't see the point of the outer one.
The outermost loop is also hard to understand, do you expect non-hex data before the number, or what? Your question could be clearer on how the expected input string looks.
I think the cleanest would be to ignore this, and push it into existing (library) code that can parse integers in any base. In C I would recommend strtoul(), you can of course use that in C++ too.
You have two inner loop with same value integer this could be a conflict problem in your code. I suggest you look at the isdigit and islower methods in the c++ library and take advantage of those methods to accomplish your task. isdigit & islower
Good Luck
This is prints the number after deleting the hex prefix, otherwise return 0:
#include<iostream>
#include<cmath>
#include<stdlib.h>
using namespace std;
int main(){
string number = "";
cin >> number;
string prefix = "dec";
char zero = '0';
char hex_prefix = 'x';
string temp = "";
int value = 0;
if (number.size()>=2 && number[0] == zero && number[1] == hex_prefix ) //is hex
{
prefix = "hex";
for(int i = 0; i < (number.size() - 2); ++i)
{
temp[i] = number[i+2];
}
value = atoi(temp.c_str());
}
cout<<value;
return 0;
}
This partial solution that I found is as clean as possible, but it doesn't report the format of the integer:
int string_to_int(std::string str)
{
std::istringstream stream;
stream.unsetf(std::ios_base::dec);
int result;
if (stream >> result)
return result;
else
throw std::runtime_error("blah");
}
...
cout << string_to_int("55") << '\n'; // prints 55
cout << string_to_int("0x37") << '\n'; // prints 55
The point here is stream.unsetf(std::ios_base::dec) - it unsets the "decimal" flag that is set by default. This format flag tells iostreams to expect a decimal integer. If it is not set, iostreams expect the integer in any base.

Converting a char "number" into a real int

I'm wanting to take the input of a user (mathematic expression) and push it onto a stack. Then I want to run it through some rules which ask if its a '(', a number, or an operator '+'. My problem is so far I don't know how to tell, specifically stating inside the while loop's first if statement, if a char is "actually" a number. Any suggestions?
#include <stack>
int main()
{
std::stack<char> myStack; // initializing the stack
char line[40];
cin.getline(line, 40); // this and the proceeding line get the input
for (int i = 0; i < 40; i++)
myStack.push(line[i]); //pushing all of the char onto the stack.
while (!myStack.empty()) {
if (myStack item = a number) {
// ^ this is where it doesn't compile.
// I need to figure out how to find out if a char is a number
cout << item << endl;
}
else if (myStack.empty()) {
myStack.push(item);
}
}
}
There's a function is C++ called isdigit, it checks if a character is a decimal digit.
if(isdigit(your_char)) //Then it's a number
Use the isdigit function:
isdigit(x)
There is a function called isdigit() in the stdlib that will answer this question for you.
There is no magic to it, however. Digits, in ASCII, are just chars in the range 48-57, 48 being '0' and 57 being '9'.
char isdigit(char d) {
return (d >= 48) && (d <= 57);
}
Based on your question, if all you want is to find if a char is a number or not. Please cast it to int and check if it is between the ascii values of 48 and 57, both included.
bool CheckIfNum(char chartToCheck)
{
int aciiOfChar = (int) charToCheck;
if (asciiOfChar >= 48 && asciiOfChar <= 57)
return true;
return false;
}
you can also use std::isdigit function