How to get size_t from string? - c

I need to get an array size from user input. It seemed natural to me to store the input as size_t, however looking for an appropriate strto...() function I couldn't find any. I just used strtoull(), since unsigned long long is guaranteed to be at least 64 bits and I'm using C99 anyway. But I was wondering what would be the best way to get size_t from a string - say, in ANSI C.
Edit:
To clarify, I don't want the string length! The user will input the size of a large buffer in the form of a string, for instance "109302393029". I need to get that number and store as size_t. Of course I could use strtol() or even atoi(), but it seems like a clumsy hack (size_t may hold larger values than int, for instance, and I want the user to be able to input any value in the addressable space).

In case you have a string input containing the value for a size_t and you want to get the value, you can use sscanf() with %zu format specifier to read the value and store it into corresponding size_t variable.
Note: do not forget to check the success of sscanf() and family.
Pseudo-code:
size_t len = 0;
if (1 == sscanf(input, "%zu", &len))
printf("len is %zu\n", len);
However, FWIW, this won't handle the overflow case. In case of the input length being arbitaryly large which your program should be able to handle, you may want to make use of strtoumax() and check for overflow, finally casting the returned value to size_t. Please see Mr. Blue Moon's answer related to this.
However, if you don't mind another approach, instead of taking the input as sting and converting it to size_t, you can directly take the input as size_t, like
size_t arr_size = 0;
scanf("%zu", &arr_size);

You can use strtoumax() to perform the conversion:
#include <inttypes.h>
intmax_t strtoimax(const char *nptr, char **endptr, int base);
uintmax_t strtoumax(const char *nptr, char **endptr, int base);
and cast the result to size_t. This is a better approach since it helps detect overflow when arbitrarily large input is given.
The scanf() family functions can't detect integer overflow, which results in undefined behaviour.

Just get the input as unsigned int and cast it to size_t, or just:
size_t length;
scanf("%zu", &length);

Related

Create char array of integer using digits as size

I am trying to create a char array in C, to fill it with the digits of an int, but the int can be of any number of digits.
I'm using a created function called getDigits(int num), that returns a number of digits the int has.
char buffer[getDigits(number)] = "";
snprintf(buffer, sizeof(buffer),"%d",number);
but when I compile using gcc, it returns:
error: variable-sized object may not be initialized
I've tried everything. When I declare it as char fileSizeStr[5] = "";, it works. I can see the problem is rising when I try to declare the buffer size dynamically, but I would really like to know if is a way of achieving this.
The problem is exactly as your compiler is telling you; you're not allowed to initialise VLAs. Zack gave an obvious solution in the comments: Remove the initialisation. You'll find working examples in this answer, some of which do permit an initialisation, and others which don't. You'll find more information about that in comments. The following examples are ordered from most sensible (IMHO) to least sensible (which involve using malloc) for allocating storage for decimal digit sequences representing numbers.
I suggest using the same trick to determine how many bytes are necessary to store an int value as decimal digits as you'd use for octal: Divide the total number of bits in an int by 3 and add for any sign and NUL termination. digit_count could be written as a preprocessor macro like so:
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#define digit_count(num) (1 /* sign */ \
+ sizeof (num) * CHAR_BIT / 3 /* digits */ \
+ (sizeof (num) * CHAR_BIT % 3 > 0)/* remaining digit */ \
+ 1) /* NUL terminator */
int main(void) {
short short_number = -32767;
int int_number = 32767;
char short_buffer[digit_count(short_number)] = { 0 }; /* initialisation permitted here */
char int_buffer[digit_count(int_number)];
sprintf(short_buffer, "%d", short_number);
sprintf(int_buffer, "%d", int_number);
}
As you can see, one powerful benefit here is that digit_count can be used for any type of integer without modification: char, short, int, long, long long, and the corresponding unsigned types.
One minor downside by comparison is that you waste a few bytes of storage, particularly for small values like 1. In many cases, the simplicity of this solution more than makes up for this; The code required to count the decimal digits at runtime will occupy more space in memory than is wasted here.
If you're prepared to throw away the simplicity and generic qualities of the above code, and you really want to count the number of decimal digits, Zacks advice applies: Remove the initialisation. Here's an example:
#include <stddef.h>
#include <stdio.h>
size_t digit_count(int num) {
return snprintf(NULL, 0, "%d", num) + 1;
}
int main(void) {
int number = 32767;
char buffer[digit_count(number)]; /* Erroneous initialisation removed as per Zacks advice */
sprintf(buffer, "%d", number);
}
In response to the malloc recommendations: The least horrible way to solve this problem is to avoid unnecessary code (eg. calls to malloc and later on free). If you don't have to return the object from a function, then don't use malloc! Otherwise, consider storing into a buffer provided by the caller (via arguments) so that the caller can choose which type of storage to use. It's very rare that this isn't an appropriate alternative to using malloc.
If you do decide to use malloc and free for this, however, do it the least horrible way. Avoid typecasts on the return value of malloc and multiplications by sizeof (char) (which is always 1). The following code is an example. Use either of the above methods to calculate the length:
char *buffer = malloc(digit_count(number)); /* Initialisation of malloc bytes not possible */
sprintf(buffer, "%d", number);
... and don't forget to free(buffer); when you're done with it.
try something like:
char* buffer =(char *)malloc(getDigits(number)*sizeof(char));
malloc and calloc are used to dinamic allocation.
For my money, there is one solution which has gone unmentioned but which is actually simpler than any of the above. There is a combined allocating version of sprintf called "asprintf" available on Linux and most BSD variants. It determines the necessary size, mallocs the memory, and returns the filled string into the first argument.
char * a;
asprintf(&a, "%d", 132);
// use a
free(a);
Using a stack allocated array certainly removes the need for the free, but this completely obviates the need to ever separately calculate the size.
below may help
char* buffer;
buffer = (char*)malloc(number * sizeof(char));
You'll need to use malloc to allocate a dynamic amount of memory.
Initializing the way you did is allowed only if the size is known at compile time.

How store a number starting with 0 in C

Id just thought id ask this question to see whether it can actually be done.
if i want to store a number like "00000000000001", What would be the best way?
bearing in mind that this also has to be incrememted on a regular basis.
Im thinking either there is a way to do this with the integer or i have to convert to a char array somewhere along the line. This would be fine but its a pain to try and increment a string.
I would store it as an integer and only convert to the formatted version with leading zeros on demand when you need to produce output, for example with printf, sprintf etc.
It's far easier that way than storing a string and trying to perform arithmetic on strings. Not least because you have extra formatting requirements about your strings.
If for some reason it is awkward to store an integer as your master data do it like this.
Store the string as your master data.
Whenever you need to perform arithmetic, convert from string to integer.
When the arithmetic is complete, convert back to string and store.
You should simply store the number using an appropriate type (say, unsigned int), so that doing operations like 'increment by one' are easy - only bother worrying about leading zeros when displaying the number.
sprintf can actually do this for you:
unsigned int i = 1;
char buffer[64];
sprintf( buf, "%014u", i );
This prints '00000000000001'.
You could store it in a integer variable (provided there's an integer type that's wide enough for your needs). When printing, simply format the number to have the correct number of leading zeros.
#include <stdlib.h> // for itoa() call
#include <stdio.h> // for printf() call
int main() {
int num = 123;
char buf[5];
// convert 123 to string [buf]
itoa(num, buf, 10);
// print our string
printf("%s\n", buf);
return 0;
}

One liner to find length of a variable

I just stumbled upon the idea that since printf returns the no.of characters it has printed to the output stream why not use it to find length of any variable in c?
The code goes something like this,
#include<stdio.h>
int main()
{
char *a="Length";
int i=1000;
printf("Size: %d\n",printf("%d\n",i)-1);
printf("String Size: %d",printf("%s\n",a)-1);
return 1;
}
Am I right? I am not concerned about where it is being used. just wanted to know if my understanding is right.
What do you mean by "length of any variable"? You mean the number of bytes used to store the variable (which better achieved with the sizeof and strlen functions) or the byte length of the string representation of the variables?
For the latter one, you should be careful, since you can use format options to actually modify the results. Consider the following example:
float num = 10.0f;
printf("%.10f", num); // return value should be 13
printf("%f", num); // return value depends on the implementation of printf and the float value supplied
Also you have to consider that there are other representations than the decimal one.
As others have already stated, printf has the side effect that it actually writes to stdout. If you do not want this, you can use snprintf to write to a buffer and not to stdout:
char buffer[256];
int x = 10;
snprintf(buffer, sizeof(buffer), "%d", x); // return value is '2'
"One liner to find length of a variable"
Not possible unless its builtin to your compiler, or you define a wild and hairy macro half a page long with a few enums to state your type...
For strings, (which you cannot use sizeof on...) see: https://stackoverflow.com/a/22128415/3370790

How to convert int to char/string and vice versa in linux(gcc)?

I want to know the method of converting an integer into char/string and vice-versa also.
I have already used sprintf(&charvar,"%d",&intvar) but it produces wrong output, possibly garbage.
i have also heard atoi() in gcc has bugs.Reference:GCC atoi bug
What is the other method to convert string/char back to int ?
Actually i want to send an integer from one machine to another using SOCK_STREAM .
//EDIT : I forgot to tell that sprintf() does conversion and returns positive value.
If you want to send an integer to another machine you can send it as binary data, just by sending the intvar directly to the stream, you don't have to convert it to a char first. That will only introduce problems with knowing the length of the data as different values generate different lengths of strings.
Please read the manual of 'sprintf' and 'sscanf', and maybe their safer versions are proper for you.
Remove the ampersand before intvar:
sprintf(&charvar,"%d",intvar)
Two notes:
Here, I assume that &charvar is of correct type, which it probably isn't.
Even though it might not make much difference here, it's a good to get into the habit of using snprintf in preference to sprintf.
Here's some example code:
int intvar = ...;
char str[16];
snprintf(str, sizeof(str), "%d", intvar);
You cannot sprintf to a variable. You need a buffer for it, because of possible several digits and the trailing zero. Moreover, the argument should be the int variable, not its address.
Example:
char buffer[256];
int i = 42;
sprintf(buffer, "%d", i);
(buffer will be filled with '4', '2' and trailing '\0').
your sprintf is wrong.You should write sprintf(string,"%d",integer);
If you want to send an integer over the network and thats why you want to convert it into string have a look at htons
with these functions you can convert an integer to network format and avoid different endianness problems!
If you just want to convert it to bytes you can do something like this:
char buf[4];
memcpy(buf,&integer,4);
If you want your string to have the value of the int then you should use sprintf.

Convert numbers with toString in Ansi C

Is it possible to use toString operator, or how to convert numbers to char arrays.
int myNumber = 27; /* or what have you */
char myBuffer[100];
snprintf(myBuffer, 100, "%d", myNumber);
There are several considerations for you to think about here. Who provides the memory to hold the string? How long do you need it for, etc? (Above it's a stack buffer of 100 bytes, which is way bigger than necessary for any integer value being printed.)
Best answer: start using Java. Or Javascript, or C#, or for the love of God almost anything but C. Only tigers lie this way.
Use the sprintf() function.
sprintf() is considered unsafe because it can lead to a buffer overflow. If it's available (and on many platforms it is), you should use snprintf() instead.
Consider the following code:
#include <stdio.h>
int main()
{
int i = 12345;
char buf[4];
sprintf(buf, "%d", i);
}
This leads to a buffer overflow. So, you have to over-allocate a buffer to the maximum size (as a string) of an int, even if you require fewer characters, since you have the possibility of an overflow. Instead, if you used snprintf(), you could specify the number of characters to write, and any more than that number would simply be truncated.
#include <stdio.h>
int main()
{
int i = 12345;
char buf[4];
snprintf(buf, 4, "%d", i);
//truncates the string to 123
}
Note that in either case, you should take care to allocate enough buffer space for any valid output. It's just that snprintf() provides you with a safety net in case you haven't considered that one edge case where your buffer would otherwise overflow.

Resources