User Input - C (Not allowing certain characters) - c

I have a C program where the user will be entering integers or doubles into the command line as input. Negative numbers are allowed, but I have the issue of when a user enters some thing like this:
1-1
It just gets parsed as being a one. I created a function to test whether or not the user input is a valid number, but I'm not sure how to catch instances like that, or the same goes for input like 1+1, 1)2, so on.
Here is the function I created:
int check_number(char *userInput) {
int i;
//check each character
for (i = 0; userInput[i] != '\0'; i++){
if (isalpha(userInput[i])){
printf("Invalid input.\n");
return -1;
}
}
return 0;
}
What should I do to not allow any other random characters (besides letters, since those are already getting tested with isalpha) in the middle of user input?

Basically you want the first character to be either a minus or a digit (and maybe a period) all subsequent characters should be digits or a period. But you will probably also want to count the periods to make sure there is only one. If you want to accept scientific notation as well you will need to deal with that as well.
Checking for not isalpha is the wrong way around, you should check for the characters that are allowed.
Basically something like:
if (*userInput != '-' && !isdigit(*userInput))
return -1;
int periods = 0;
while (*++userInput != 0) {
if (*userInput == '.') {
if (periods >= 1)
return -1;
++periods;
continue;
}
if (!isdigit(*userInput))
return -1;
}
return 0;

if (isdigit(userInput[i]) || userInput[i]=='.') {
printf("Valid input.\n");
}
else return -1;

Related

Password input always returns "not eligible"

I'm learning C right now.
I have been working on a program that will check user's input (password eligibility). In order for password to be considered as eligible and considerably strong, it needs to have at least of one from the list of following items:
Uppercase letter;
'$' sign;
Alphanumerical character;
In my program I have created three integer variables that will keep count of upper mentioned requirements.
Unfortunately, whenever I input the "correct" version of password, the program keeps printing that the password is not eligible.
Please give me a clue, where I might be wrong.
//challenge:
//build a program that checks when user enters a password for an uppercase letter, a number, and a dollar sign.
//if it does output that password is good to go.
int main()
{
char passwordInput[50];
int alphaNumericCount = 0;
int upperCharacterCount = 0;
int dollarCount = 0;
printf("Enter you password:\n");
scanf(" %s", passwordInput);
//int charactersAmount = strlen(tunaString);
for (int i = 0; i < 49; i++){
//tunaString[i]
if( isalpha(passwordInput[i]) ) {
alphaNumericCount++;
//continue;
}else if( isupper(passwordInput[i]) ) {
upperCharacterCount++;
//continue;
}else if( passwordInput[i] == '$' ) {
dollarCount++;
//continue;
}
}
if( (dollarCount == 0) || (upperCharacterCount == 0) || (alphaNumericCount == 0) ){
printf("Your entered password is bad. Work on it!\n");
}else{
printf("Your entered password is good!\n");
}
return 0;
}
The isalpha function returns true if the character is either upper case or lower case. You do that before the condition that calls isupper. Since an upper case character will satisfy the first condition, the second condition will never evaluate to true.
Since being upper case is a subset of being alphanumeric, you need to revise your requirements. If instead you want to check for (for example):
upper case
numeric
"$"
Then you would have one condition use isupper, one use isdigit and one compare with '$'.
Also, you loop through all elements of the passwordInput array, even if they're not all populated. Instead of testing i<49, use i<strlen(passwordInput).

Print output just beside the user input

According to the question, The user needs to enter the no of hours the vehicle is parked and the total charge for the hours should get printed beside it.
for example:
I created this simple program
#include<stdio.h>>
#include<math.h>
float calculateCharges(float hurs);
int main()
{
float hours;//total no of hours vehicle is parked
int i;
printf("%s%10s%10s", "Car", "Hours", "Charges");
for (i = 1; i <= 3; i++)
{
printf("\n%d\t", i);
scanf("%f", &hours);
printf("\t%f\n", calculateCharges(hours));
}
getch();
return 0;
}
float calculateCharges(float hurs)
{
float charges;
hurs = ceil(hurs);
if (hurs >= 24) charges = 10;
else
{
if (hurs <= 3) charges = 2;
else
{
hurs = hurs - 3;
charges = 2 + 0.5*hurs;
}
}
return charges;
}
But now every time I enter hours the charges are getting printed below it instead of beside it. As shown in the image:
Is there is a way to consume the newline after scanf? So that charges can be printed beside the scanf?
I have modified my code this way too, but it didn't make any difference.
printf("%s%10s%10s", "Car", "Hours", "Charges");
for (i = 1; i <= 3; i++)
{
printf("\n%d\t", i);
printf("\t%f\n",(scanf("%f", &hours),calculateCharges(hours)));
}
Let me know if the original question is required. I'm using Visual studio 2017 RC.
You can use something like this:
#include <iostream>
#include <windows.h>
//This will set the position of the cursor
void gotoXY(int x, int y) {
//Initialize the coordinates
COORD coord = {x, y};
//Set the position
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
return;
}
void getCursorXY(int &x, int&y) {
CONSOLE_SCREEN_BUFFER_INFO csbi;
if(GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
x = csbi.dwCursorPosition.X;
y = csbi.dwCursorPosition.Y;
}
}
I found it here.
As already written in one of the answers this solution is not platform independent.
But i guess there are similar solutions on other platforms and you can easy set the cursor on the position you want.
Example usage in your main:
for (i = 1; i <= 3; i++)
{
printf("\n%d\t", i);
scanf("%f", &hours);
gotoXY( 20, i + 1);
printf("\t%f\n", calculateCharges(hours));
}
Workarounds for scanf can be found here.
scanf_s always generates a new line upon enter and unfortunately other user input capturing platform independent functions I know of (getc & getchar) do so too. Anyway on Windows it could be done using _getch() from conio header.
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
int getIntFromUser()
{
char readCharacters[10];
int index = 0;
for (int currentChar = _getch(); currentChar != '\r'; currentChar = _getch())
{
if (currentChar == EOF)
{
// Some error that shouldn't occour in your simple homework program
}
if (index > 9)
{
// Another possible error case where you would start to write beyond 'readCharacters' array
}
// We might as well disallow anything but digits, enter & backspace (You don't need anything else, do you?)
if ((currentChar < '0' || currentChar > '9') && currentChar != '\b')
{
continue;
}
else if (currentChar == '\b')
{
if (index > 0)
{
// Delete last character
printf("\b \b");
readCharacters[index] = '\0';
--index;
}
}
else
{
printf("%c", currentChar);
readCharacters[index] = currentChar;
++index;
}
}
if (index == 0)
{
// User pressed enter without having entered a number, let's give him a zero then
return 0;
}
readCharacters[index] = '\0';
int retVal = atoi(readCharacters);
// Worth noting that the value of converted user given string shouldn't be greater than what a signed int can hold
return retVal;
}
int main(int argc, char* argv[])
{
// Unlike scanf_s this will not generate a new line on enter
printf("getIntFromUser() sample (enter a number)\n");
int someValue = getIntFromUser();
printf(" -- This will be printed on the same line. (someValue is %d)\n\n", someValue);
// scanf_s sample
int anotherValue;
printf("scanf_s() sample (Insert a number.)\n");
scanf_s("%d", &anotherValue);
printf("This will be printed on a new line\n\n");
printf("Press any key to exit.");
_getch();
return 0;
}
EDIT
I feel like the above would become less readable if I were to add a comment over every code line. Instead I'm going to paste some blocks of code 1 by 1.
But first about the _getch function: It waits for the user to type something into the console and then returns the user given char as an int. char implicitly converts to int, so you may compare the _getch result to a character as I did many times in getIntFromUser (e.g. if (currentChar == '\b') { ... }).
You should also know about the values a char can hold and what their values are as an int (check out http://en.cppreference.com/w/cpp/language/ascii).
Going by the table the char '0' would be value 48 as an int, which is what _getch would return if the user were to type a 0.
First declare an array/string of 10 elements. Hope you know about them already. In this case the array is basically a chain of 10 elements that are all of type char, which are also referred to as string.
char readCharacters[10];
An indexer for the string is required.
int index = 0;
Below we have the usual for loop that...
1st: creates a variable of type int and assigns the result of _getch to it.
2nd: will determine if the loop shall keep executing. In this case the loop will break when currentChar is not '\r', which is an escape sequence that represents enter as a character.
3rd: will execute stuff inside once and then update currentChar with a new _getch.
for (int currentChar = _getch(); currentChar != '\r'; currentChar = _getch())
Checks if the user input (retrieved via _getch) is smaller than '0' (value 48 as an int) and greater than '9' (value 57 as an int). If either of them is true it will additionally check if the value of currentChar is not '\b' (value 8 as an int), which is the escape sequence for a backslash.
When that additional check evaluated to true as well then the keyword continue is used. Meaning that the rest of the block in the loop is not executed and instead the loop will start at the top again by getting a new user input and evaluating if the loop is to be continued by checking if obtained currentChar was enter.
if ((currentChar < '0' || currentChar > '9') && currentChar != '\b')
{
continue;
}
NOTE: You might want to read the comments on the else statement before you read these.
When the above if statement was false we get to the next if-statement (actually else if) that we see below.
As mentioned above: '\b' is backslash and if this is the user given char as well as string/array index being greater than 0 we move one character backwards in the console by "printing" '\b' and then write an empty character in order to delete what was written at that place previously. That puts us back to the position we were before so we print another backslash. At this point you might wonder why not just go back to the previous line that scanf_s causes, but that won't work. We must also not forget to replace the last string character with a null terminator and then set the index back by 1.
else if (currentChar == '\b')
{
if (index > 0)
{
// Delete last character
printf("\b \b");
readCharacters[index] = '\0';
--index;
}
}
When we hit this point we know that currentChar is something between 48 and 57 ('0' and '9').
_getch told the program what the user's input was, but we cannot see it in the console unless we print it there. So let's do that.
Also append the user's given character to the string as well as incrementing the index by 1.
else
{
printf("%c", currentChar);
readCharacters[index] = currentChar;
++index;
}
Lastly we call the atoi function that will convert our string/array to an integer.
int retVal = atoi(readCharacters);

Error check for character when reading in integers in C

For my programming class I've written a program to calculate the sum of divisors. So I've gotten to my final part which is error checking, which I am having a problem with if I read a character in. I have searched on S.O. earlier,as well as tried to figure something out, and couldn't find a solution that works for endless negative numbers until 100.
When I hit a character it sets it to 0 and just goes to the end, where I want it to exit once it reads it in
int main (void){
int userIN=0;
int i = 0;
int next = 0;
int temp= 105;
int cycle;
puts("Enter up to 10 integers less than or equal to 100");
while(scanf("%d ", &userIN) !=EOF && (i < 10))
{
if(userIN > 100){
printf("Invalid Input\n");
exit(1);
}
else if(userIN < 100)
{
Thanks for the help in advance
EDIT: The program is cycling through correctly, My Issue is error checking for a character being entered not anything with the code itself
scanf() returns a value other than EOF if it cannot read the values specified by the format string (e.g. with %d, it encounters data like foo). You can check for that. The caveat is that it does not read the offending data from stdin, so it will still be there to affect the next call of scanf() - which can result in an infinite loop (scanf() reporting an error, call scanf() again, it encounters the same input so reports the same error).
You are probably better off reading a whole line of input, using fgets(). Then check the input manually or use sscanf() (note the additional s in the name). The advantage of such an approach is that it is easier to avoid an infinite loop on unexpected user input.
You could loop while i is less than 10. The first if will see if scanf failed. If so the input buffer is cleared and the while loop tries again. If EOF is captured, then exit. If scanf is successful, the input is compared to 100 and if in range, the while loop counter is incremented.
Declare int ch = 0;
while ( i < 10) {
printf("Enter %d of 10 integers. (less than or equal to 100)\n", i + 1);
if(scanf(" %d", &userIN) != 1)
{
while ( ( ch = getchar()) != '\n' && ch != EOF) {
//clear input buffer
}
if ( ch == EOF) {
exit ( 1);
}
}
else {
if(userIN > 100){
printf("Invalid Input\n");
}
else
{
i++;// good input advance to the next input
printf("Valid");
}
}
}

Putting numbers inside array at once in C

I'm struggling finding an answer to this: I want to be able to control if a credit card number (let's say '378282246310005') fulfills certain criteria (f.e. does it start with the number 3).
I want to be able to type the whole number at once, and then check certain places in the number (f.e. every second). However, I only managed to put them in an array when typing them one after another, which is annoying:
int main()
{
int user_input[5];
int i;
for(i=0;i<5;i++)
{
printf("Credit Card Number Digit %d\n",i+1);
scanf("%d",(user_input+i));
}
if(user_input[0] == 5)
printf("MASTERCARD\n");
else
printf("INVALID\n");
return 0;
}
Just check each digit as it is entered and ignore any non-numeric input, e.g.
int main()
{
int user_input[16];
int digits = 0;
while (digits < 16)
{
int c = getchar(); // get character
if (c == EOF) break; // break on EOF
if (isdigit(x)) // if character is numeric
{ // convert it to int and append to user_input array
user_input[digits++] = c - '0';
} // (otherwise just ignore it)
}
if (digits > 0 && user_input[0] == 5)
{
printf("MASTERCARD\n");
}
else
{
printf("INVALID\n");
}
return 0;
}
I would suggest scanning a string into an array of char and then access this array. The technique is included in this Wikipedia article, where the following code can be found.
#include <stdio.h>
int main()
{
char word[20];
if (scanf("%19s", word) == 1)
puts(word);
return 0;
}
The snipped reads a string in the array word, which can be accessed similar as in your question. Apparently, the maximum length of the string can be given as a parameter in the format string.

Is it posible to use 2 functions return in another function, inside printf?

I'm trying to create 3 functions, one for counting words, one for counting letters, and another to print the average of letters and words. Im getting an error in xcode i dont understand in the last function (printing_average()) printf...
Appreciate your help.
My code:
...main()
int num_of_words()
{
int userInput;
int numOfWords = 0;
while ((userInput = (getchar())) != EOF)
{
while (userInput != ' ')
{
if (userInput == ' ')
numOfWords++;
}
}
return numOfWords;
}
int num_of_letters()
{
int userInput;
int numberOfLetters = 0;
while ((userInput = (getchar())) != EOF)
{
if (ispunct(userInput) && numberOfLetters > 0)
{
numberOfLetters--;
}
else if(userInput == 'n' && numberOfLetters > 0)
{
numberOfLetters--;
}
else if (userInput == ' ' && numberOfLetters > 0)
{
numberOfLetters--;
}
else if (isdigit(userInput))
printf("please enter only characters:\n");
continue;
}
return numberOfLetters;
}
int printing_average()
{
printf("please enter couple of words:\n");
return printf("the average of number of letters and number of words is: %d", num_of_letters()/num_of_words());
}
I didn't try to compile your program, but I would say that this logic does not work:
while (userInput != ' ')
{
if (userInput == ' ')
numOfWords++;
}
Like this, numOfWords will never be incremented, so in your last print you will be dividing by zero...
To answer your actual question: yes, you can call an arbitrary number of functions as part of a printf call.
If you are wanting to actually count the same set of words for both letters and words, your logic doesn't work. Each time "getchar()" is called, it takes something out of the input buffer. So for the first calls will read some the input until an EOF is seen. At that point, the second function gets called, and it immediately sees EOF, so there won't be any letters/words to count.
To solve this, you need to rearrange your code to either:
1. Collect all the input into an array, and then use the two functions to determine how many of each thing there is.
2. Write a new function that calculates both numbers of things in one function.
I prefer option two. It is an easier solution, and doesn't cause problems if the input is very large - sure, it will take some time, but you don't need to store everything and then count it twice!

Resources