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

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.

Related

Cant read number char frequency

#include <stdio.h>
int main() {
FILE *fb;
char data[255];
int c=0;
int count[75] = {0};
fb = fopen("Input.txt", "r");
fgets(data, 255, fb);
/* Start finding frequency*/
while (data[c] != '\0')
{
if( data[c] >= '0' && data[c] <= 'z')
count[data[c] - 'a']++;
c++;
}
for (c = 0; c < 75; c++)
{
/** Printing only those characters
whose count is at least 1 */
if (count[c] != 0)
printf("%c occurs %d times in the entered string.\n",c+'a',count[c]);
}
return 0;
}
Example input file: "Fred Fish 12345678"
I am able to handle space from the input file, but the program does not read Frequency of capital letter as well as number character. What can I change in the program help fixing the problem. After reading the freq, my plan is to save the file so that I can compress using HUffman
#include <stdio.h>
int main() {
FILE *fb;
char data[255];
int c = 0;
int count[75] = { 0 };
fb = fopen("Input.txt", "r");
fgets(data, 255, fb);
/* Start finding frequency*/
while (data[c] != '\0')
{
if (data[c] >= 'a' && data[c] <= 'z') // here you check normal letters
count[data[c] - 'a']++;
else if (data[c] >= 'A' && data[c] <= 'Z')
count[data[c] - 'A' + 26]++; // Capital letters will be stored after lower cases
else if (data[c] >= '0' && data[c] <= '9')
count[data[c] - '0' + 51]++; // Numbers will be stored after capital letters
c++;
}
// count[] is initialized as following :
// From count[0] to count[25] == Occurence of low case characters
// From count[26] to count[51] == Occurence of capital characters
// From count[52] to count[61] == Occurence of numbers from 0 to 9
for (c = 0; c < 61; c++)
{
/** Printing only those characters
whose count is at least 1 */
if (count[c] != 0) {
if (c < 26)
printf("%c occurs %d times in the entered string.\n", c + 'a', count[c]);
// Starting from 'a', iterating until 'z'
else if (c < 52)
printf("%c occurs %d times in the entered string.\n", c + 'A' - 26, count[c]);
// Same as for low case characters
// Substracting 26 because we already have iterated through the first 26 low case characters
// Starting from 'A' until 'Z'
else if (c >= 52)
printf("%c occurs %d times in the entered string.\n", c + '0' - 51, count[c]);
// Same as for characters
// Substracting 51 because we already have iterated through low cases and capital characters
// Starting from '0' until '9'
}
}
return 0;
}
The problem is that, considering the ascii table, you were storing the capital letters and numbers in a negative indice of your array countby substracting 'a'which is equal to 97in ASCII. This should work but I couldn't test it yet so be careful with it.
For the printing, we do the same thing for low case characters, then capital characters and then numbers : we start from the first one : 'a', then 'A', then '0', iterate until the last one using c and printing them all. We use the fact that in C, 'a' + 1 = 'b', 'A' + 1 = 'B' etc.
For the input Fred Fish 12345678 the output with this code is :
d occurs 1 times in the entered string.
e occurs 1 times in the entered string.
h occurs 1 times in the entered string.
i occurs 1 times in the entered string.
r occurs 1 times in the entered string.
s occurs 1 times in the entered string.
F occurs 2 times in the entered string.
1 occurs 1 times in the entered string.
2 occurs 1 times in the entered string.
3 occurs 1 times in the entered string.
4 occurs 1 times in the entered string.
5 occurs 1 times in the entered string.
6 occurs 1 times in the entered string.
7 occurs 1 times in the entered string.
8 occurs 1 times in the entered string.
I guess chaning the code
count[data[c] - 'a']++;
to
count[data[c] - '0']++;
if data[c] is less than 75, then count[data[c] - 'a'] does not work
You should modify the 'a' to '0' in your code to take all capital letters and numerics into account.
#include <stdio.h>
int main() {
...
/* snippet */
...
while (data[c] != '\0')
{
if( data[c] >= '0' && data[c] <= 'z')
count[data[c] - '0']++;
c++;
}
for (c = 0; c < 75; c++)
{
/** Printing only those characters
whose count is at least 1 */
if (count[c] != 0)
printf("%c occurs %d times in the entered string.\n",c+'0',count[c]);
}
return 0;
}

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.

Converting from hexadecimal to decimal number in C

I am doing the exercise in the C Programming language book, and exercise 2-3 asked us to write a function htoi to convert a hexadecimal number to decimal number.
This is the code I wrote, however when it runs, it always show that my hexadecimal number is illegal.
Please help!
#include<stdio.h>
#define TRUE 1
#define FALSE 0
int htoi (char s[]);
int main() {
printf("The decimal number is %d\n", htoi("0x134"));
return 0;
}
int htoi (char s[]) {
int j; /* counter for the string */
int temp; /* temp number in between conversion */
int number; /* the converted number */
int ishex; /* if the number is a valid hexadecimal number */
char c;
number = 0;
temp = 0;
ishex = FALSE;
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
ishex = TRUE;
}
else {
ishex = FALSE;
printf("This is not valid hexadecimal number.\n");
return number = 0;
}
if (ishex == TRUE) {
for (j = 2; (c = s[j]) != EOF; ++j) {
if (c >= '0' && c <= '9')
temp = c - '0';
else if (c >= 'a' && c <= 'f')
temp = 10 + c - 'a';
else if (c >= 'A' && c <= 'F')
temp = 10 + c - 'A';
else {
printf("This is a illegal hexadecimal number.\n");
ishex = FALSE;
return 0;
}
number = number * 16 + temp;
}
}
return number;
}
A string is a sequence of characters that terminates at the first '\0' character. That means "0x134" terminates with a '\0' character value, not an EOF value.
You are operating on a sequence of characters that you expect to be terminated by an EOF value, but that is simply not possible. I'll explain why later... Suffice to say for now, the string "0x134" contains no EOF value.
Your loop reaches the string-terminating '\0', which isn't in the range 0..9, a..f or A..F and so this branch executes:
else {
printf("This is a illegal hexadecimal number.\n");
ishex = FALSE;
return 0;
}
Perhaps you meant to write your loop like so:
for (j = 2; (c = s[j]) != '\0'; ++j) {
/* SNIP */
}
I promised to explain what is wrong with expecting EOF to exist as a character value. Assuming an unsigned char is 8 bits, getchar can return one of 256 character values, and it will return them as a positive unsigned char value... OR it can return the negative int value EOF, corresponding to an error or end-of-file.
Confused? In an empty file, there are no characters... Yet if you try to read a character from the file, you will get EOF every time, in spite of there being no characters. Hence, EOF is not a character value. It's an int value, and should be treated as such before you attempt to convert the value to a character, like so:
int c = getchar();
if (c == EOF) {
/* Here, c is NOT A CHARACTER VALUE! *
* It's more like an error code ... *
* XXX: Break or return or something */
}
else {
/* Here, c IS a character value, ... *
* so the following conversion is ok */
char ch = c;
}
On another note, c >= '0' && c <= '9' will evaluate truthfully when c is one of the digits in the range 0..9... This is a requirement from the C standard
Neither c >= 'a' && c <= 'f' nor c >= 'A' && c <= 'F' are required to evaluate truthfully under any circumstance, however. It happens to work on your system, because you are using ASCII which contains all of the lowercase letters in one contiguous block, and all of the uppercase letters in another contiguous block. C does not require that ASCII be the character set.
If you want this code to work portably, you might consider something like:
char alpha_digit[] = "aAbBcCdDeEfF";
if (c >= '0' && c <= '9') {
c -= '0';
}
else if (strchr(alpha_digit, c)) {
c = 10 + (strchr(alpha_digit, c) - alpha_digit) / 2;
}
else {
/* SNIP... XXX invalid digit */
}

Check whether the input is digit or not in C programming

I am currently reading this book: The C Programming Language - By Kernighan and Ritchie (second Edition) and one of the examples I am having trouble understanding how to check whether the input is digit or not. The example is on Page 22, explaining under the array chapter.
Below is the example.
#include <stdio.h>
/* count digits, white space, others */
main()
{
int c, i, nwhite, nother;
int ndigit[10];
nwhite = nother = 0;
for (i = 0; i < 10; ++i)
{
ndigit[i] = 0;
}
while ((c = getchar()) != EOF)
{
if (c >= '0' && c <= '9')
{
++ndigit[c-'0'];
}
else if (c == ' ' || c == '\n' || c == '\t')
{
++nwhite;
}
else
{
++nother;
}
printf("digits =");
for (i = 0; i < 10; ++i)
{
printf(" %d", ndigit[i]);
}
printf(", white space = %d, other = %d\n",nwhite, nother);
}
For this example, what confused me is that the author mentioned that the line ++ndigit[c-'0'] checks whether the input character in c is a digit or not. However, I believe that only the if statement ( if (c>= '0' && c<= '9') ) is necessary, and it will check if c is digit or not. Plus, I do not understand why [c-'0'] will check the input(c) is digit or not while the input variable (c) is subtracted from the string-casting ('0').
Any suggestions/explanations would be really appreciated.
Thanks in advance :)
The if statement checks whether the character is a digit, and the ++ndigit[c-'0'] statement updates the count for that digit. When c is a character between '0' and '9', then c-'0' is a number between 0 and 9. To put it another way, the ASCII value for '0' is 48 decimal, '1' is 49, '2' is 50, etc. So c-'0' is the same as c-48, and converts 48,49,50,... to 0,1,2...
One way to improve your understanding is to add a printf to the code, e.g. replace
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
with
if (c >= '0' && c <= '9')
{
++ndigit[c-'0'];
printf( "is digit '%c' ASCII=%d array_index=%d\n", c, c, c-'0' );
}
I would try to explain with an example
suppose the input is abc12323
So the frequency of 1=1
frequency of 2=2
frequency of 3=2
if (c >= '0' && c <= '9') //checks whether c is a digit
++ndigit[c-'0'];
Now if you do printf("%d",c) then you will get the ascii value of the
character
for c='0' the ascii value will be 48,c='1' ascii value will be 49 and it goes
till 57 for c='9'.
In your program you are keeping a frequency of the digits in the input so you need to update the index of the digit in the array every time you get it
if you do ndigit[c]++ then it will update ndigit[48] for c='0',ndigit[49] for c='1'
So either you can do ndigit[c-'0']++ as ascii value of '0'=48 in decimal
or you can simply do ndigit[c-48]++ so for c='0' ndigit[0] is updated,c=1'
ndigit[1] is updated
you can check the re factored code here http://ideone.com/nWZxL1
Hope it helps you,Happy Coding

checking stored variable with scanf

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

Resources