Why is the argument to malloc i+1 in this C code? - c

Usually a malloc contains sizeof , but this one doesn't and has i+1 instead:
int main ()
{
int i,n;
char * buffer;
printf ("How long do you want the string? ");
scanf ("%d", &i);
buffer = (char*) malloc (i+1);
if (buffer==NULL) exit (1);

If you wanted to allocate an array of some type, you would normally multiply the number of elements you wanted by the size of that type, because malloc takes the size of the array in bytes.
However, an array of char is a special case; you do not need to multiply the number of elements you want by sizeof(char), because sizeof(char) is defined by the Standard to always be 1, and multiplication by 1 yields the other operand.
The + 1 is to make room for the NUL terminator. If you want a string of length n, your array has to be of length n + 1; n spaces for the n characters of the string, and 1 space for the terminator.
By the way, you shouldn't cast the return value of malloc. It will make your code easier to change in the future.

C strings are null-terminated, see:
http://en.wikipedia.org/wiki/Null-terminated_string
E.g. "abc" is represented as "abc" + NUL. Thus, for a string of length i, you need to allocate i + 1. As you are allocating chars, sizeof(char) is 1, so you actually need to allocate 1 * (i + 1), but that's the same.

If its allocating for a string you need enough memory for the number of characters + 1 extra for the null character that denotes the end of the string (\0)

Related

Convert char String to an int but not possible to convert a char from an char string to an int?

char input[5] = "12345";
printf("Convert to int valid %d", atoi(input));
printf("Convert to int invalid %d", atoi(input[1])); // program crash
Is there a solution to convert an char "slice" of an char string into an int?
Short description:
User inputs a string with values for example: 1, 2 3 4 ,5
Iam formating that string to 12345
With each number i want to continue to work with the index of an array.
If you mean "how to access a substring in the char [] array", you can use pointer arithmetic:
char input[6] = "12345";
printf("strtol(input + 1) = %d\n", strtol(input + 1, NULL, 10)); // Output = "2345";
Few things to note though:
Your array should be 6 elements long to hold the null terminator
atoi shouldn't be used at all; strtol is a better function for the task of converting a string to a signed integer; see here for more info.
Also, to convert a single character to an int:
if(isdigit(c))
{
c -= '0';
}
The relation that a textual representation of a digit is exactly '0' higher than the numeric value of that digit is guaranteed to hold for every character set supported by C.
To properly convert an arbitrary slice, you have to either make a copy or modify the string by inserting a \0 after the slice. The latter may not be an option, depending on where the string is stored.
To make a copy, allocate an array big enough to hold the slice and a \0. If you know the size of the slice at compile time, you can allocate on the stack:
char slice[2];
Otherwise, you'll have to allocate dynamically:
char *slice;
slice = malloc(2);
Stack allocated slices do not need to be deallocated, but dynamically allocated ones should be freed as soon as they are no longer needed:
free(slice);
Once you have the slice allocated, copy the portion of interest and terminate it with \0:
strncpy(slice, s + 1, 1);
slice[1] = '\0';
atoi(slice);
This technique will pretty much always work.
If your slice always ends with the string, you don't need to make a copy: you just need to pass a pointer to the start of the slice:
atoi(s + 1);
Modifying the string itself probably won't work, unless it's in writeable memory. If you're sure this is the case, you can do something like:
char tmp;
tmp = s[1];
s[1] = '\0';
atoi(s);
s[1] = tmp;
If you were sure but the memory wasn't writeable, your program will seg-fault.
For the special case where your slice is exactly one character long, you can use the fact that characters are numbers:
s[0] - '0'
Note that '0' !='\0' and that this won't work if your machine uses EBCDIC or similar.

Size of formatted string

I am struggling to understand what happens during snprintf.
Let's say I have two numbers:
int i =11; int k = 3;
I want to format them like this "[%02d] %03d\t" and use snprintf.
Afterwards I use the resulting string with write().
snprintf needs the length/bytes n.
I do not understand what is the length I need to provide...
I have 2 theories:
a) It is
sizeof(int)*2
b) I check how many chars the formatted string will contain by counting the digits of the two integers and adding the other chars that the output will have:
2*sizeof(char) + 1*sizeof(char) + 2*sizeof(char) + 3*sizeof(char)+ 1*sizeof(char)
-> digits of i + digits of k + zeros added to first int + zeros added to second int + tab
I am struggling to understand what is the "n" I have to give to snprintf
It is the buffer size
According to a documentation:
Maximum number of bytes to be used in the buffer. The generated string
has a length of at most n-1, leaving space for the additional
terminating null character. size_t is an unsigned integral type.
Suppose you write to an array such as this:
char buf[32];
The buffer can hold 32 chars (including the null terminator). Therefore we call the function like this:
snprintf (buf, 32, "[%02d] %03d\t", i, k);
You can also check the return value to see how many chars have been written (or would have been written). In this case, if it's bigger than 32, then that would mean that some characters had to be discarded because they didn't fit.
Pass 0 and NULL first to obtain an exact amount
int n = snprintf(NULL, 0, "[%02d] %03d\t", i, k);
Then you know you need n + 1
char *buf = malloc(n + 1);
snprintf(buf, n + 1, "[%02d] %03d\t", i, k);
free(buf);
See it on ideone: https://ideone.com/pt0cOQ
n is the size of the string you're passing into snprintf, so it knows when to stop writing to the buffer. This is to prevent a category of errors knows as buffer overflows. snprintf will write n - 1 characters into the passed-in buffer and then terminate it with the null character.

Print one character from string

I'm facing an issue connected with printing one char from string in c.
The function takes from users two variables - number (number which should print character from string) and string. When I put as a string "Martin" and number is 5 then the output is "i". But when the number is larger than the string length something goes wrong and I actually don't know what's wrong.
PS. If the number is longer than string size it should print "Nothing".
void printLetter() {
char * string = (char*)malloc(sizeof(char));
int n;
printf("Number:\n");
scanf("%i", &n);
printf("String:\n");
scanf("%s", string);
if(n > strlen(string)) {
printf("nothing");
} else {
printf("%c\n", string[n+1]);
}
free(string);
}
There is no need for dynamic allocation here, since you do not know the length of the string in advance, so just do:
void printLetter() {
char string[100]; // example size 100
...
scanf("%99s", string); // read no more than your array can hold
}
A fun exercise would be to count the length of the string, allocate dynamically exactly as mush space as you need (+1 for the null terminator), copy string to that dynamically allocated space, use it as you wish, and then free it.
Moreover this:
printf("%c\n", string[n+1]);
should be written as this:
printf("%c\n", string[n-1]);
since you do not want to go out bounds of your array (and cause Undefined Behavior), or print two characters next of the requested character, since when I ask for the 1st character, you should print string[0], when I ask for the 2nd, you should print string[1], and so on. So you see why we need to print string[n-1], when the user asks for the n-th letter.
By the way, it's common to use a variable named i, and not n as in your case, when dealing with an index. ;)
In your code, this:
char * string = malloc(sizeof(char));
allocates memory for just one character, which is no good, since even if the string had one letter only, where would you put the null terminator? You know that strings in C should (almost) always be NULL terminated.
In order to allocate dynamically memory for a string of size N, you should do:
char * string = malloc((N + 1) * sizeof(char));
where you allocate space for N characters, plus 1 for the NULL terminator.
Couple of problems...
sizeof(char) is generally 1 byte. Hence malloc() is allocating only one byte of memory to string. Perhaps a larger block of memory is required? "Martin", for example, will require at least 6 bytes, plus the string termination character (seven bytes total).
printf("%c\n", string[n+1]) is perhaps not quite right...
String: Martin\0
strlen= 6
Offset: 0123456
n = 5... [n+1] = 6
The character being output is the string terminator '\0' at index 6.
This might work better:
void printLetter() {
char * string = malloc(100 * sizeof(char));
int n;
printf("Number:\n");
scanf("%i", &n);
printf("String:\n");
scanf("%s", string);
if(n > strlen(string)) {
printf("nothing");
} else {
printf("%c\n", string[n-1]);
}
free(string);
}
You are facing buffer overflow.
Take a look to this question, so it will show you how to manage your memory properly in such situation: How to prevent scanf causing a buffer overflow in C?
Alternatively you can ask for number of letter and allocate only that much memory + 1. Then fgets(string, n,stdin); because you don't need rest of the string :-)

what is the length of this array? c language

char msg[100] = {’C’,’P’,’R’,‘E’,‘\0’,‘2’,‘8’, ‘8’,‘\0’};
int my_length = 0xFFFFFFFF;
my_length = strlen(msg);
I thought it is nine, however, the answer is 4. anyone can explain? thanks
strlen will stop counting as soon as it hits a null terminator (as C uses null terminated strings and expects to only find them at the end of a string).
You have four characters before your first null terminator, therefore the length is 4.
strlen returns 4 because the (first) string in msg is terminated by the \0 at msg[4]. However, the array msg has a length of 100 chars because it was declared as such.
Remember that in C, a string is simply a sequence of character values followed by a zero-valued terminator. Strings are stored in arrays of char (or wchar_t for wide strings), but not every array of char (or wchar_t) is a string. To store a string that's N characters long, you need an array with at least N + 1 elements to account for the terminator.
strlen returns the number of characters in the string starting at the specified address up to the zero terminator.
To get the size (in bytes) of the msg array, use the sizeof operator:
char msg[100] = {'C','P','R','E','\0','2','8','8','\0'};
size_t my_length = strlen( msg );
size_t my_size = sizeof msg;
if ( my_length >= my_size )
// whoopsie
In this case, you're actually storing two strings in one array ("CPRE" and "288").
The size of the msg array is 100 (as given by the declaration).
The length of the string "CPRE" starting at msg[0] is 4, since you have a zero terminator in the fifth element of the array ('\0' == 0).
The length of the string "288" starting at msg[5] is 3 since you have another zero terminator in the ninth element of the array.
Maybe it is typo in your
char msg[100] = {’C’,’P’,’R’,‘E’,‘\0’,‘2’,‘8’, ‘8’,‘\0’};
and you wanted
char msg[100] = {’C’,’P’,’R’,‘E’,‘0’,‘2’,‘8’, ‘8’,‘\0’};
(plainly: CPRE0288), so binary 0 (instead of the character representation of 0 , i. e. '0') prematurely finishes your string.
You cannot assume that the return value of strlen represents the size of an array.
strlen will take a pointer to the start of a string and increment the pointer while looking for a null terminator; once it finds that, it returns the counter (i.e. number of increments before the null was found).
You declared msg to be of length 100, but only populated 9 elements in the array. sizeof(msg) will be 100.
Are you actually asking "how can I find out how many values are initialized in an array"? There's really no answer to that.

Convert array of bytes to hexadecimal string in plain old C

I am looking into a method to convert a byte array to a hexadecimal string here is what i coded :
unsigned char buffer[] = {0xAA,0xBB,0x01,0xAB,0x11,0x12,0x13,0x22,0x11,0x14};
int _tmain(int argc, _TCHAR* argv[])
{
char * asta = (char*)malloc(16);
memset(asta,0,16);
int k;
for (k = 0; k < 16 ; k++)
{
sprintf(&asta[k],"%X",buffer[4 + k]);
}
printf("%s",asta);
_getch();
}
Only the first byte is converted correctly the rest are not. How can i fix the code ?
You have 10 bytes in your array, so your buffer needs at least 21 bytes (2 hex digits are needed for each byte + 1 for the null terminator).
I don't understand what you are doing here:
sprintf(&asta[k],"%X",buffer[4 + k]);
Why are you starting with the fifth byte in the buffer? Also, each byte in your buffer takes two bytes in the string, so you need to print to asta[2 * k].
Putting it together you get something like:
char * asta = (char*)calloc(2 * sizeof buffer + 1, sizeof(char)); // calloc automatically zeros asta
int k;
for (k = 0; k < sizeof buffer ; k++)
{
sprintf(&asta[2 * k],"%02X", (unsigned int)buffer[k]); // Not sure if the cast is needed
}
printf("%s",asta);
You have to remember that two-digit hexadecimal numbers will still be two digits when you print it as a string, i.e. it will take up two characters.
In the loop, the second iteration will overwrite the second character of the string, the third iteration will overwrite the third characters, etc.
Also, since each two-digit number will use two characters, you must allocate memory for 32 characters, plus one for the string terminating '\0' character.
And as noted in the comments, you are accessing data outside of your array.

Resources