checking stored variable with scanf - c

I am wondering why is it that regardless if I input a digit or a letter or a character it keeps printing the last print line, how come the yes "This is an integer line never work? How do I go about getting the user to only input a positive digit?
#include <stdio.h>
#include <limits.h>
main(){
unsigned int num;
printf("Please input a positive number: ");
scanf("%d",&num);
if ((num >= 'a' && num <= 'z') || (num >='A' && num <= 'Z')){
printf("not an interger(alpha)");
}
else if ( num >= '0' && num <= '9'){
printf("yes this is an integer");
}
else{
printf("not an integer");
}
}

change else if ( num >= '0' && num <= '9') to else if ( num >= 0 && num <= 9), assume you input a number between 0 and 9.

You are not comparing against int in second if.
Depending upon your need, change it to (i.e. remove ' ')
(num >= 0)
or
else if ( num >= 0 && num <= 9)

You need to get the types of your variables right. An unsigned int can only ever be that: an non-negative integer. You cannot look at the first character in an integer.
Your program analyses a string, i.e. an array of characters, even if it only looks at the first letter. Therefore, your data must be an array of characters. This also means that you need to scan for a string with "%s".
When you test the first character of your string, you must use an array index, str[0].
To put all this together:
#include <stdio.h>
int main()
{
char str[20];
printf("Please input a positive number: ");
scanf("%19s", str);
if ((str[0] >= 'a' && str[0] <= 'z') || (str[0] >='A' && str[0] <= 'Z')) {
printf("alpha\n");
} else if (str[0] >= '0' && str[0] <= '9') {
printf("integer\n");
} else {
printf("other\n");
}
return 0;
}
Edit: As pointed out, this code does not check whether a string repesents a decimal number. It only checks the first character. A full solution should check all characters and is left as an exercise to the original poster.
My impression is that the OP has difficulties to distinguish between the data types, so I tried to focus on that.
I've also added a field width to the scanf to avoid buffer overflow. I'm not going into the details of sscanf here, because I think that the OP still has to understand more of the very basic stuff.

The ASCII of '0' is 48. and '9' is 48+9.
so else if ( num >= '0' && num <= '9') will be true if you input a value between 48 and 57.
The solution is, as jfly said, change to else if ( num >= 0 && num <= 9).

This code is incorrect. Please check out the manual page for scanf http://linux.die.net/man/3/scanf
You need scanf("%c", &character_var); and call it repeatedly. Alternatively read a string
EDIT
if (scanf("%u", &num) == 1) {
printf("Well done - you managed to type in a positive integer %u\n", num);
} else {
printf("Have another go!\n");
}
Is a solution

Related

Checking if characters in a char array are integers | c script

Hi I have the following code. It is suppose to loop through each character in the string and break out of the loop if one of the characters in the string is not a digit (0-9) (does not have ascii value 0-9).
//check if opperands are positive ints not zero
size_t i = 0;
//iterate through characters in string until null
while (argv[1][i] != '\0') {
int c = argv[1][i];
if(c >= 0 && c <= 9){
printf("True\n");
i++;
}
else {
printf("false\n");
return 1;
}
}
however, say the loop is iterating through the string 1234 it will return false, even though all of the digits ascii values are between 1 and 9. Anyone have any ideas on why it is doing this, I think it might be something with my if/else statement. Thanks!
The number literal 0 and 9 are not the same as the character literal '0' and '9'. You should replace if (c >= 0 && c <= 9) with if (c >= '0' && c <= '9'). Note the single quotes around the digits.

why is printf prints just once in a loop, only for the first input?

void hexToDec(){
char numHex, numDec;
int isNum, isLowAf, isHighAf;
printf("Enter a reversed number in base 16:\n");
scanf("%c", &numHex);
while(numHex != '\n'){
isNum = isHighAf = isLowAf = 0;
if(numHex >= 48 && numHex <= 57)
isNum = 1;
if(numHex >= 65 && numHex <= 70)
isHighAf = 1;
if(numHex >= 97 && numHex <= 102)
isLowAf = 1;
if(!isNum && !isLowAf && !isHighAf)
printf("Error! %c is not a valid digit in base 16\n", numHex);
//else - Hexadecimal to Decimal converter
fflush(stdin);
scanf("%c", &numHex);
}
}
I can't use string.h or arrays[] this task and I need to check every input I get and print every char that isn't digit in base 16. The problem is that it only check the first letter I enter and print not valid for it.
for example:
input:
lds
output:
Error! l is not a valid digit in base 16
expected:
Error! l is not a valid digit in base 16
Error! s is not a valid digit in base 16
Also I can't figure out why the while loop doesn't stop after I click Enter.
fflush(stdin) is not standard C. But on systems where it works (Windows), it will discard all the buffered input that hasn't yet been. So after scanning the first character l, this will cause ds to be discarded, and it will wait for you to type a new line of input.
Get rid of that call if you want it to process the remaining characters of the line.
The while loop is not exiting because of the space in the second scanf.
Would be a tad nicer if character constants are used instead of hard coded numbers.
while(numHex != '\n'){
isNum = isHighAf = isLowAf = 0;
if(numHex >= '0' && numHex <= '9')
isNum = 1;
else if(numHex >= 'A' && numHex <= 'F')
isHighAf = 1;
else if(numHex >= 'a' && numHex <= 'f')
isLowAf = 1;
if(!isNum && !isLowAf && !isHighAf)
printf("Error! %c is not a valid digit in base 16\n", numHex);
//else - Hexadecimal to Decimal converter
//fflush(stdin);//undefined behavior
scanf("%c", &numHex);
}

reading space character into string with size determined by str_size

I'm trying to make this program such that the user could type any given string of characters, and the program would separate alphanumerical characters from the rest, print them into a second string, and finally print the final result into the screen.
I've already tried using scanf ("%[^\n]%*c", string);, but it doesn't seem to work since the size of the string is not specified beforehand, and is rather defined by STR_SIZE.
char string[STR_SIZE];
printf("please type in a string \n");
scanf("%s", string);
printf("string: \n %s \n", string);
int size = (strlen(string));
char alfanumerico[STR_SIZE];
int count = 0;
int count2 = 0;
while(count <= size)
{
if(string[count] >= '0' && string[count] <= '9')
{
alfanumerico[count2] = string[count];
count2++;
}
if(string[count] >= 'a' && string[count] <= 'z')
{
alfanumerico[count2] = string[count];
count2++;
}
if(string[count] >= 'A' && string[count] <= 'Z')
{
alfanumerico[count2] = string[count];
count2++;
}
if(string[count] ==' ')
{
alfanumerico[count2] = string[count];
count2++;
}
count++;
}
printf("alphanumerical characters typed: \n %s \n", alfanumerico);
Given the user typed a string such as: -=-=[[][][]}}Hello 123 ```//././.
I expect the output to be: Hello 123
scanf is not the way to go, especially if your input might contain white-spaces on which scanf would stop reading more inputs and wouldn't store spaces for instance.
You should use fgets which lets you limit the input data according to the buffer this data is stored in. So something like:
fgets(string, STR_SIZE, stdin)
should work.
About the size - you should have some limitation about the maximum size of the string and then STR_SIZE should be set to this number. It should be part of your program requirements or just a size that makes sense if you're making the requirements. It must be defined before you're reading input from the user because the buffer memory is allocated before reading to it.
A comment about style, unrelated to your question - always try to decrease code duplication to 0. The line alfanumerico[count2] = string[count]; count2++; appears 4 times in your code. A more elegant minimal if statement with exactly the same functionality would be:
if ((string[count] >= '0' && string[count] <= '9') ||
(string[count] >= 'a' && string[count] <= 'z') ||
(string[count] >= 'A' && string[count] <= 'Z') ||
(string[count] == ' '))
{
alfanumerico[count2] = string[count];
count2++;
}
and to be even more minimal:
char c = string[count];
if ((c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c == ' '))
{
alfanumerico[count2] = c;
count2++;
}
It's also more readable and more maintainable - if you want to change the variable count to i you do it in one place instead of 8.
Also, always close a scope in a new line.

Why is my function atoi not working? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am trying to create my personal atoi function but i doesn't work properly. I don't know why.
void ft_putchar(char c)
{
write(1, &c, 1);
}
int ft_atoi(const char *str)
{
int i;
i = 0;
while (str[i] == 9 || str[i] == 32 || str[i] == 43 || str[i] == 45)
i++;
while (str[i] > 48 && str[i] < 57)
{
ft_putchar(str[i]);
i++;
}
return (0);
}
int main(void)
{
printf("%d", atoi(" 2794ffafsaasf"));
printf("\n%d",ft_atoi(" 2794fsffsf"));
return(0);
}
I kinda works but it doesn't. It gives me a weird result where it even ignores '\n'.
The result it gives me is this.
272794 and a new line.
with only my function it gives me only the number 27.
EDIT:
I have created a new program. But it still doesn't work. It simply can't see digits.
int ft_atoi(const char *str)
{
int i;
int n;
i = 0;
while (str[i] == '\t' || str[i] == ' ' || str[i] == '+' || str[i] == '-')
++i;
n = i;
while (str[n] >= '0' && str[n] <= '9')
{
++n;
}
return(str[n]);
}
Your test for digits has the bounds set wrong. You're testing str[i] > 48 && str[i] < 57, but 48 is the ordinal for the 0 character, and 57 is the ordinal for 9. This means you only consider 1 through 8 inclusive to be numeric digits, and you stop parsing 2794fsffsf at the 9, not at the first f.
Changing the test to str[i] >= 48 && str[i] <= 57 would fix the bounds issue, but would still be less than self-documenting. To make it obvious what you're doing to people who don't have the ASCII tables memorized, you could do:
while ('0' <= str[i] && str[i] <= '9')
or possibly slightly slower but even more obviously with ctype.h:
while (isdigit(str[i]))
You could similarly replace the many non-obvious tests for whitespace ordinal values with isspace(str[i]).
First thing is to ignore leading whitespace. You can do that with i as you're doing, but it's easier to do it by shifting the start of the string forward. I'm guessing that you're reimplementing the standard C library as an exercise. I'm not, so I'm going to make use of the ctype.h functions. Adjust as you like, the basic code remains the same. You should probably write your own ft_isspace and ft_isdigit rather than hard coding the logic.
/* Move str to point at the first non-space character */
while( isspace(str[0]) ) {
str++;
}
Now there's no need for an i to hold your place, you can just work with str[0] and it will be the first non-whitespace character.
Next we need to find and add up our digits. Again, I'll use isdigit. Follow the advice in ShadowRanger's answer if you can't use that function.
The technique is to convert each character to a digit and add it to the total. Since we're reading a number left to right, each new digit multiplies the existing sum by 10. For example, if we had 1234 it would be... 1 then 10 + 2 then 120 + 3 then 1230 + 4.
int num = 0;
while( isdigit(str[0]) ) {
int digit = str[0] - '0';
num *= 10;
num += digit;
str++;
}
Once again I'm manipulating the pointer rather than using an index. This is just to save an integer, and to avoid mixing up two string iteration techniques in a single function.
And, finally, don't forget to return the number!
return num;
What about negative numbers? We need to look for a - before we check for digits, if it's there flip the sign. We also need to handle a + and ignore it.
/* Assume it's positive. */
short sign = 1;
/* Check for a sign. */
switch( str[0] ) {
case '-':
sign = -1;
str++;
break;
case '+':
str++;
break;
}
And then multiply by the sign to flip the result.
return sign * num;
Your code only writes out the numbers - and not all, as pointed out before me (because it excludes '0' and '9' and they should be included!) - to the file identified by 1 (what is maybe the standard output, I don't remember exactly...), and returns 0 as the parameter of the printf. It seems to me a little strange, you only had 27 printed out with your function, but it might be environment(?) specific. (I have not tested it, so it possibly not exactly work as I suppose...)
I've made my version of atoi, hoping I can show where to start / the way how you should do yours:
int nvi9_atoi(const char *s) {
int n = 0, valid = 0, prev = 0;
while(1) { // infinite loop
if (*s == '\0') break; // if it is the end of the string, finish further processing
if (*s >= '0' && *s <= '9') { // check whether the current character is an ascii number
n *= 10; // "move" all previous digits (eg. 1 -> 10, 43 -> 430); if n is 0, this has no effect
if (n >= 0) n += (*s - '0'); // if n is not negative, add the value of the last digit (here is ascii-number "conversion"!)
else n -= (*s - '0'); // if it is negative, the number should be substracted (note eg. if there was -10 so far, and the new number is 2, the new value should be -12, not -8)
if (n > 0 && !valid) { // if n not 0, and there was no digits before it, check if there was a minus sign before
valid = 1; // preventing more check
if (prev == '-') n *= -1; // makes n negative
}
} else if (valid) break; // if there was numbers processed, but the current character is not a number, finish loop
prev = *s; // store current character for minus sign checking of next loop
s++; // move string pointer to the next character
}
return n; // return the converted value
}
It is also untested, so fixes / corrections / improvements are welcome!
This function can even process strings like " sfg afg-65sd1g". In that case the returned value will be -65, because it looks for the first number, then returns.

Validating user input between 1-9 using getchar()

Hey guys im trying to write a small program where the user has to put in a number between 1-9, anything else is an error, but I'm having trouble validating the input because if you put 12 it only reads the 1 and it goes in the loop. It has to be done using getchar() this is what have so far:
printf(%s,"please enter a number between 1 - 9);
int c;
c = getchar();
while(c != '\n') {
int count = 1;
count ++;
if ((c >= '0' && c <= '9') || count > 1) {
printf(%s, "Congrats!);
}
else
{
print(%s, "ERROR);
}
}
I'm also having problems validating the char into an int after it goes in. If i put in 5 i get 53.
Try changing count > 1 to count == 1, and initialize it to 0 rather than 1. That way you can keep count of the number of digits you have. Also, note that because you initialize count to 1 and then immediately increment it, count > 1 will always evaluate to true, so if you gave it any char it will always say it's correct.
getchar() will return the next character typed. If you want more than the first character you will need a call getchar() again within the while loop.
//Somewhere to store the result
//initialized with an invalid result value
int digitchar = 0;
//Get the first char
int c = getchar();
while (c != '\n')
{
//Check if we already have a digit
//and that the new char is a digit
if (digitchar == 0 && c >= '1' && c <= '9')
{
digitchar = c;
}
//Get the next char
c = getchar();
}
//Check if we have stored a result
if (digitchar != 0)
{
//Success
}
Note this doesn't handle if a non-digit or newline character is entered. You would need to handle that as an error as well as if more than one digit is entered.
This is not working with 12 because getchar() takes one character per time.The following example is one way to solve it.
printf("please enter a number between 1 - 9");
int c[10], count=1;
//Declare an array because user may insert a bigger number
char number;
//This loop allow the user to enter an input
for(i=0;i<10;i++){
number = getchar();
if (number != ' '){
c[i] = atoi(number);
sum = sum + c[i];
}
else if(number == ' '){
//Terminate the loop when user stop typing
break;
}
else if( sum > 9 || sum < 0){
//Start loop again until user enter valid input
printf("You entered a number out of field try again\n");
continue;
}
}
while(c != '\n') {
count ++;
if ((c >= '0' && c <= '9') || count > 1) {
printf("%d Congrats!",c);
}
else
{
printf(" %d ERROR", c);
}
}
Remember that getchar() returns the ascii value of the char, thus when you pass the value to the function you must subtract char '0' to pass the actual decimal value into the function.
Another point is that you must clear the input buffer. If your user enters wrong input, you have to make sure that there is nothing left on the input buffer before you try to read input again.
Hope this helps.
int main(void) {
int input = 0; // 0 is the sentinel value to close program
printf("\n%s\n", "Enter value between 1-9 .\nEnter [0] to finish.");
do {
input = getchar();
if (((input>= '1') && (input <= '9') || input == '0') && getchar() == '\n') {
if ((input >= '1') && (input <= '9')) {
callYourOwnFuntionAndPassValue(input - '0');
printf("\n%s\n", "Enter value between 1-9 .\nEnter [0] to finish.");
}
}
else {
while (getchar() != '\n') {} // clear input buffer
printf("\n%s\n", "Please enter a valid number");
}
} while (input != END_PROGRAM);
return NO_ERROR; // NO_ERROR = 0
}

Resources