Getting the number of digits of an integer - c

bool isValidId(int* id)
{
if(log10(*id) != 6)
{
return false;
}
return true;
}
printf("Enter ID: ");
gets(input);
c.id = atoi(input);
validID= isValidId(c.id);
if(!validID)
{
printf("Invalid ID format -(Use example 123456 format). \n");
}
This is how it looks now.I ask the user to enter an ID and check it if is valid with the isValidId method but my program is crashing when I enter an ID. Please help! Thanks

return *id >= 100000 && *id < 1000000;
I think this may be a good solution, both easy to read and efficient.
There is no need to acquire its length if you just want to judge if it is a valid id
Program crashes because the parameter of isValidId is pointer to int, not int, so
validID = isValidId(c.id);
should be
validID = isValidId(&c.id);

First of all, I don't see any reason to pass a pointer to isValidId function. You can pass an integer and calculate the number of digits.
bool isValidId(int id) {
// count digits here
}
Now there are at least two ways to calculate the number of digits. First one is to use log10. The number of digits in a 10-base integer n is (int)(log10(n) + 1). You will need to import math.h to use log10. You may check whether n <= 0 before calling log10.
The second way is to loop through n.
int count = 0;
while (n > 0) {
count++;
n /= 10;
}

You've declared isValidId to take a pointer to an int, but you're passing it a plain int; in this case, there's no reason to use a pointer, so you'd be better off changing isValidId to use a regular int.
NEVER NEVER NEVER NEVER NEVER USE GETS -- IT WILL INTRODUCE A POINT OF FAILURE/MAJOR SECURITY HOLE IN YOUR CODE. Use fgets(input, sizeof input, stdin) instead.
How is input declared? Is it large enough to hold as many digits as int will allow, plus a sign, plus a 0 terminator?
log10 returns a double, not an int. To properly count digits with log10, you will need to write something like (int)floor(log10(id)) + 1.
You can simplify your isValidId function a little:
bool isValidId(int id)
{
return (int) floor(log10(id)) + 1 == 6;
}
The Boolean data type is a latecomer to the C language (introduced in C99), so a lot of us older types tend to avoid using Boolean constants in our code.

I've not done C for eons however try something like this
bool isValidId(int* id)
{
char str[15];
sprintf(str, "%d", id)
if(strlen(str) != 6)
{
return false;
}
return true;
}

It's way easier like this:
#include <math.h>
bool isValidId(int *id)
{
return (int)log10(*id) == 6;
}

Related

How to pass this test case? Can someone also explain what I was missing?

This is the tester function:
intA = intB = 0;
printf("TEST-2: ");
intA = getIntPositive(NULL);
if (intA == TEST_INT)
{
printf("<PASSED>\n");
}
else
{
printf("<!!! FAILED !!!>\n");
fail++;
}
This is the function I have written to get positive integer and return it:
int getIntPositive(int *num) {
do
{
scanf("%d", num);
if (*num <= 0)
{
printf("ERROR: Enter a positive value:");
}
} while (*num <= 0);
return *num;
}
The test you show is incomplete (it does not fully test the function), and what you show of it is incomplete (you do not show the input provided to the function). You also do not show the specification of the function (a description of how it is supposed to behave).
What we can tell from the test code you show is:
The function is passed a pointer parameter.
In a certain test case with input unknown to us and a null pointer argument, the function is expected to return a value TEST_INT.
From the source code you show for getIntPositive, we can tell it likely fails this test case because it uses the parameter it is given to access memory even though it is given a null pointer. For scanf("%d", num);, scanf must be passed a pointer to an int, not a null pointer. And, in if (*num <= 0), the behavior of using *num when num is a null pointer is not defined by the C standard.
One way to fix this is simply to ignore the parameter and use another int to get a value from the input stream and return it:
int getIntPositive(int *num)
{
do
{
int x;
scanf("%d", &x);
if (x <= 0)
{
printf("ERROR: Enter a positive value:");
}
} while (x <= 0);
return x;
}
This code might pass that particular test. However, several questions remain unanswered:
What is the code supposed to do when the parameter is a null pointer? What is it supposed to do when the parameter is not a null pointer?
Is the function supposed to loop until it gets a positive value?
What should the function do if there is an error (including end-of-file) in the input stream or a matching failure in scanf (there is input, but it does not match what a decimal numeral should look like).
On question 1, some functions that accept a pointer and return a value provide the value both as the function return value and in the pointed-to-place, and, if the pointer is null, they skip that part. If so, the code above could be modified at the end:
if (num)
*num = x;
return x;
}
However, another possibility is the scanned value is supposed to be returned in *num, if num is non-null, and the return value is supposed to be a status code. Perhaps it should be 0 if a number was scanned successfully or TEST_INT if there was a matching failure or something else if there was an input stream error.
Similarly, on questions 2 and 3, we do not know. Writing a correct function requires having a specification of what the function is supposed to do. We do not even know what the input is in this test case. Is it an empty input stream, at end-of-file? Is it input with some negative numerals followed by a positive numeral? Is it input that does not match a decimal numeral at all? There is critical information missing from what you have shown about the test case.

Convert read-only character array to float without null termination in C

I'm looking for a C function like the following that parses a length-terminated char array that expresses a floating point value and returns that value as a float.
float convert_carray_to_float( char const * inchars, int incharslen ) {
...
}
Constraints:
The character at inchars[incharslen] might be a digit or other character that might confuse the commonly used standard conversion routines.
The routine is not allowed to invoke inchars[incharslen] = 0 to create a z terminated string in place and then use the typical library routines. Even patching up the z-overwritten character before returning is not allowed.
Obviously one could copy the char array in to a new writable char array and append a null at the end, but I am hoping to avoid copying. My concern here is performance.
This will be called often so I'd like this to be as efficient as possible. I'd be happy to write my own routine that parses and builds up the float, but if that's the best solution, I'd be interested in the most efficient way to do this in C.
If you think removing constraint 3 really is the way to go to achieve high performance, please explain why and provide a sample that you think will perform better than solutions that maintain constraint 3.
David Gay's implementation, used in the *BSD libcs, can be found here: https://svnweb.freebsd.org/base/head/contrib/gdtoa/ The most important file is strtod.c, but it requires some of the headers and utilities. Modifying that to check the termination every time the string pointer is updated would be a bit of work but not awful.
However, you might afterwards think that the cost of the extra checks is comparable to the cost of copying the string to a temporary buffer of known length, particularly if the strings are short and of a known length, as in your example of a buffer packed with 3-byte undelimited numbers. On most architectures, if the numbers are no more than 8 bytes long and you were careful to ensure that the buffer had a bit of tail room, you could do the copy with a single 8-byte unaligned memory access at very little cost.
Here's a pretty good outline.
Not sure it covers all cases, but it shows most of the flow:
float convert_carray_to_float(char const * inchars, int incharslen)
{
int Sign = +1;
int IntegerPart = 0;
int DecimalPart = 0;
int Denominator = 1;
bool beforeDecimal = true;
if (incharslen == 0)
{
return 0.0f;
}
int i=0;
if (inchars[0] == '-')
{
Sign = -1;
i++;
}
if (inchars[0] == '+')
{
Sign = +1;
i++;
}
for( ; i<incharslen; ++i)
{
if (inchars[i] == '.')
{
beforeDecimal = false;
continue;
}
if (!isdigit(inchars[i]))
{
return 0.0f;
}
if (beforeDecimal)
{
IntegerPart = 10 * IntegerPart + (inchars[i] - '0');
}
else
{
DecimalPart = 10 * DecimalPart + (inchars[i] - '0');
Denominator *= 10;
}
}
return Sign * (IntegerPart + ((float)DecimalPart / Denominator));
}

Converting a number in one base to another base using recursion

So im having trouble with creating a recursive function to convert a number from bases 2-10 to bases 2-16. I need it to return a string (obviously , due to the bases greater than 10).
here is my function:
main would call it like:
answer = baseConversion(101, 10, 2);
I have hex as a constant char:
const char Hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char * baseConverter(int number,int currbase, int base){
if(currbase != 10){
number = base10Converter(number, currbase); //converts the number to base of 10
currbase = 10;
}
if(number == 0 || base==10){
return number;
}
int r = number%base;
printf("%c", Hex[r]);
//return (number % base) + 10*baseConverter(number /base, currbase, base); // this gives the answer as an integer.
return Hex[r]+ && baseConverter(number /base, currbase, base) // I dont know what to add here to add the characters together
}
i need help with my return statement and recursive call.
Do i need to declare a char array within the function and then append the chars i get from hex[r] to it? If so, How do i go about doing that because I cant change the parameters
ints done't have bases, they just have values. How you display, or represent with a string, have bases. Thus, it doesn't make sense to have a currBase, unless you started with a string representation of the value you want to convert.
baseConverter, is defined so that it returns a string; since it is not passed space for that string, it will have to allocate it.
Thus, for the recursive case, you'd call baseConverter to give you a string for the rest of the number, and use that to make a new string (which you need to allocate), being sure to deallocate the string you got from the recursive call when you are done.

conversion in c

I'm new to C and I need to write a function in c which converts an integer to a string in the specified base and print it.
If I were given an input value of 1234 (base 10) it should return 2322 (base 8).
Here is the code structure I'm currently working on:
void int2ascii(int value, int base){
int a=0;
if (value > base) {
a = a + int2char(value); //recursive case
int2ascii(value/base, base); //base case
}
printf("%s\n",a);
}
The program won't run, can someone enlighten me?
Thanks
Analysis of your program
I noted first off that a is declared int, but it was being passed to printf with %s as the format specifier. %s designates the associated argument will be a string, which a is not. The result will be undefined behavior, and is a possible cause for your crash.
You do not specify what int2char() does, but let's assume that it converts a numeric "digit" into a corresponding char value. With that in mind, let us suppose its implementation is similar to:
int int2char(int d) {
return "0123456789abcdefghijklmnopqrstuvwxyz"[d];
}
In your code, you pass value to int2char(). In my hypothetical implementation, this would cause out-of-bounds access of the array, and thus undefined behavior. This is indicates a logic error, and another possible cause for your crash.
I note that if value is less than base, a remains 0. Probably, you really mean to compute a value for a even when value is less than base. This indicates another logic error.
Base conversion
The number dKdK-1 .. d0, where each di is in (0 .. 9), is a short form for &Sum;di×10i. To discover the base 10 digits of a number N, the process is:
di = ⌊N / 10i⌋ mod 10
But, as it turns out, you can replace 10 with some other base number to compute the digits for a number in that base:
di = ⌊N / Bi⌋ mod B
In your code, the recursive call that divides by the base represents the first part of the calculation. However, in your calculation of a, you were missing the "mod" part of the calculation.
Solution 1
Assuming base is from 2 to 36, and that your int2char(d) does something more or less as illustrated earlier:
void int2ascii(int value, int base){
int a=0;
a = a + int2char(value%base);
if (value > base) {
int2ascii(value/base, base);
}
printf("%c",a);
}
Because you are not passing a into your recursive call, you can only use it to store the current digit to be printed. So, move the code to store the value in a out of the if check, since you always want a sensible value to print at the end. The digit in a is in the radix base, so you need the modulus result to get the right digit value. Since a represents a character, change the format string to match, and remove the \n so that all the digits end up on the same line.
Solution 2
The first solution is an attempt to leave most of your original code intact. Since a is initialized to 0, the extra addition does not make it incorrect. But, since the print doesn't happen until the very end, the value doesn't really need to be stored at all, and can be calculated at the point you actually want to print it. With that in mind, the program can be simplified to:
void int2ascii(int value, int base){
if (value > base) {
int2ascii(value/base, base);
}
printf("%c",int2char(value%base));
}
#include <stdio.h>
#include <limits.h>
char *int2ascii_aux(int n, int base, char *s){
//base {x| 2 <= x <= 36 }
static const char *table = "0123456789abcdefghijklmnopqrstuvwxyz";
if(n){
*--s = table[n % base];
return int2ascii_aux(n/base, base, s);
} else {
return s;
}
}
char *int2ascii(int n, int base){
//base {x| 2<= x <= 36 }
static char s[sizeof(int)*CHAR_BIT+1];
if(n <= 0){
*s = '0';
return s;
}
if(base < 2 || base > 36){
*s = '\0';
return s;
}
return int2ascii_aux(n, base, s + sizeof(s) -1);
}
int main(){
printf("%s\n", int2ascii(1234, 8));
return 0;
}

Translate string to number

I am looking for a way to take a string and check 3 possibilities.
Digit and thus converts it to a signed int (not a long)
Is a symbolic representation previously defined at runtime, and converts it to a signed int
Neither
The "symbolic representation" will be basically like an associative array that starts at 0 elements and expands as more symbols are added. For example lets say for instance that C had associative arrays (I wish) with this peusdocode:
symbol_array['q'] = 3;
symbol_array['five'] = 5;
symbol_array['negfive'] = -5;
symbol_array['random294'] = 28;
signed int i;
string = get_from_input();
if(!(i = convert_to_int(string))) {
if(!(i = translate_from_symbol(string))) {
printf("Invalid symbol or integer\n");
exit(1);
}
}
printf("Your number: %d\n, i);
The idea being if they entered "5" it would convert it to 5 via convert_to_int, and if they entered "five" it would convert it to 5 via translate_from_symbol. As what I feel may be hardest is if they entered "random294" it wouldn't convert it to 294, but to 28. If they entered "foo" then it would exit(1).
My general questions are these: (Instead of making multiple posts)
When making convert_to_int I know I shouldn't use atoi because it doesn't fail right. Some people say to use strtol but it seems tedious to convert it back to a non-long int. The simplistic (read: shortest) way I've found is using sscanf:
int i;
if ((sscanf(string, "%d", &i)) == 1){
return i;
}
However, some people look down on that even. What is a better method if not sscanf or converting strtol?
Secondly, how can I not only return an integer but also know if it found one. For example if the user entered "0" then it would return 0, thus setting off my FALSE in my if statement. I had considered using -1 if not found but since I am returning signed int's then this also suffers from the same problem. In PHP I know for example with strpos they use === FALSE
Finally, is there any short code that emulates associate arrays and/or lets me push elements on to the array in runtime?
First, you might want to revise your syntax and set the keyword apart from the operand, i.e. "neg five" instead of "negfive". Otherwise your symbol lookup for the keywords has to consider every prefix. ("random294" might be okay if your keywords aren't allowed to have digits in them.)
Sure, sscanf tells you whether you found a decimal in the return value and writes that decimal to a separate int, which is nice, but you'll have to watch out for trailing characters by checking that the number of characters read equals the length of your string with the %n format. Otherwise, sscanf will consider 5x as legal decimal number. strtol also returns a pointer to the location after the parsed decimal number, but it relies too much on checking err for my taste.
The fact that strtol uses long integers shouldn't be an issue. If the input doesn't fit into an int, return INT_MAX or INT_MIN or issue an error.
You can also easily write a wrapper function around sscanf or strtol that suits your needs better. (I know I'd like a function that returns true on success and stores the integer via a pointer argument, sscanf style, where success means: no trailing non-digit characters.)
Finally, about the associative arrays: There is no short code, at least not in C. You'll have to implement your own hash map or use a library. As a first draft, I'd use a linear list of strings and check them one by one. This is a very naive approach, but easy to implement. I assume that you don't start out with a lot of symbols, and you're not doing a lot of checks, so speed shouldn't be an issue. (You can sort the array and use binary search to speed it up, but you'd have to re-sort after every insertion.) Once you have the logic of your program working, you can start thinking about hash maps.
Something like this should do your job:
#include <stdio.h>
#include <string.h>
struct StringToLongLookUp {
char *str;
char *num;
};
struct StringToLongLookUp table[] =
{
{ "q" , "3" },
{ "five" , "5" },
{ "negfive" , "-5" },
{ "random294", "28" }
};
int translate_from_symbol(char **str)
{
int i;
for(i = 0; i < (sizeof(table) / sizeof(struct StringToLongLookUp)); i++)
{
if(strcmp(*str, table[i].str) == 0)
{
*str = table[i].num;
return 1; // TRUE
}
}
return 0; // FALSE
}
int main()
{
char buf[100];
char *in = buf;
char *out;
int val;
scanf("%s", in);
translate_from_symbol(&in);
val = strtol(in, &out, 10);
if (in != out)
{
printf("\nValue = %d\n", val);
}
else
{
printf("\nValue Invalid\n");
}
}
Of course, you get a long, but converting that to int shouldn't be an issue as mentioned above.

Resources