I was trying to convert a decimal from [0, 255] to a 8 bit binary number, where each bit will be separated by a comma and a space. I tried the following (eventually it worked, except for the last bit does not require any separator ):
#include <stdio.h>
#include <stdlib.h>
char* atobin(int input) {
char *str = malloc(0);
int index, count = 0;
if (input > 255| input < 0) {
printf ("Input out of range. Abort.\n");
exit(EXIT_FAILURE);
}
for (index = 7; index >= 0; index--) {
*(str + (count++)) = (input >> index & 1) ? '1' : '0';
*(str + (count++)) = ',';
*(str + (count++)) = ' ';
}
*(str + count) = '\0';
return str;
}
int main(int argc, char *argv[]) {
printf("%s\n", atobin(atoi(argv[1])));
return EXIT_SUCCESS;
}
Now I have a few questions:
I used malloc(0); as far as I am concerned, it will
allocate no memory from the heap. So, how/ why is it working?
Is the declaration *(str + count) = '\0'; necessary?
Is there any way to optimize this code?
UPDATE
To carry on this experiment, I have taken the atobin function in to a .h file. This time it creates some problems.
Now I add my last question:
What should be minimum integer to be used for the parameter of malloc? Some trial-and-error method makes me guess it should me 512. Any idea?
From a malloc doc:
If size is zero, the return value depends on the particular library implementation (it may or may not be a null pointer), but the returned pointer shall not be dereferenced.
That it works for you is just luck. Try some random malloc and free afterwards and you will have a high probability - but no guarantee - that you will get a crash.
This null-terminates the string. Depends on how you want to use the string if you need it. The printf in your example needs it, because that's the only way for it to know when the string ends.
I'm sorry, I don't have time to take a closer look.
malloc(0) is valid to be used. what it returns is implementation defined. but what happens if you access a object through the pointer returned by malloc(0) is undefined behavoiur. you can read this related question.
In C since strings are character arrays terminated by \0 it is better to use *(str + count) = '\0'; statement to set the last character of string. It is working in this code but its better to set the end of string in code always. It may work if bits are set to 0 since it is same as terminating a string.
Related
I want to write a function that converts CamelCase to snake_case without using tolower.
Example: helloWorld -> hello_world
This is what I have so far, but the output is wrong because I overwrite a character in the string here: string[i-1] = '_';.
I get hell_world. I don't know how to get it to work.
void snake_case(char *string)
{
int i = strlen(string);
while (i != 0)
{
if (string[i] >= 65 && string[i] <= 90)
{
string[i] = string[i] + 32;
string[i-1] = '_';
}
i--;
}
}
This conversion means, aside from converting a character from uppercase to lowercase, inserting a character into the string. This is one way to do it:
iterate from left to right,
if an uppercase character if found, use memmove to shift all characters from this position to the end the string one position to the right, and then assigning the current character the to-be-inserted value,
stop when the null-terminator (\0) has been reached, indicating the end of the string.
Iterating from right to left is also possible, but since the choice is arbitrary, going from left to right is more idiomatic.
A basic implementation may look like this:
#include <stdio.h>
#include <string.h>
void snake_case(char *string)
{
for ( ; *string != '\0'; ++string)
{
if (*string >= 65 && *string <= 90)
{
*string += 32;
memmove(string + 1U, string, strlen(string) + 1U);
*string = '_';
}
}
}
int main(void)
{
char string[64] = "helloWorldAbcDEFgHIj";
snake_case(string);
printf("%s\n", string);
}
Output: hello_world_abc_d_e_fg_h_ij
Note that:
The size of the string to move is the length of the string plus one, to also move the null-terminator (\0).
I am assuming the function isupper is off-limits as well.
The array needs to be large enough to hold the new string, otherwise memmove will perform invalid writes!
The latter is an issue that needs to be dealt with in a serious implementation. The general problem of "writing a result of unknown length" has several solutions. For this case, they may look like this:
First determine how long the resulting string will be, reallocating the array, and only then modifying the string. Requires two passes.
Every time an uppercase character is found, reallocate the string to its current size + 1. Requires only one pass, but frequent reallocations.
Same as 2, but whenever the array is too small, reallocate the array to twice its current size. Requires a single pass, and less frequent (but larger) reallocations. Finally reallocate the array to the length of the string it actually contains.
In this case, I consider option 1 to be the best. Doing two passes is an option if the string length is known, and the algorithm can be split into two distinct parts: find the new length, and modify the string. I can add it to the answer on request.
i trying to create a function that return an array of zeros us a char array
and print this array in a file text but when i return a string an addition char was returned
this the text file string the program wrote
this my fuction :
char *zeros_maker (int kj,int kj1)
{
char *zeros;
zeros = (char *) malloc(sizeof(char)*(kj-kj1));
int i;
for(i =0;i<kj-kj1;i++)
zeros[i]='0';
printf("%s\n",zeros);
return zeros;
}
the instruction i used when i printed in the file
fprintf(pFile,"%c%s%c &",34,zeros_maker(added_zeros,0),34);
Thanks in advance
'0' in C is the value of the encoding used for the digit zero. This is not allowed to have the value 0 by the C standard.
You need to add a NUL-terminator '\0' to the end of the char array, in order for the printf function to work correctly.
Else you run the risk of it running past the end of the char array, with undefined results.
Finally, don't forget to free the allocated memory at some point in your program.
Read about how string in C are meant to be terminated.
Each string terminates with the null char '\0' (the NULL symbol ASCII value 0, not to be confused with the char '0' that has ASCII value 48). It identifies the end of the string.
zeros[kj-kj1]='\0';
Plus check always if you are accessing an element out of bound. In this case it happens if kj1> kj
Instead of for loop, you may get hand of memset.
char* zeros_maker(int kj,int kj1)
{
int len=kj-kj1;
char *zeros=malloc(sizeof(char)*(len));
memset(zeros,'0',len-1);
zeros[len-1]=0;
printf("%s\n",zeros);
//fflush(stdout);
return zeros;
}
Or if you are not fan of C-style string, and it's going to be ASCII only, following could be used too. Just be careful what your are doing this way.
char* zeros_maker_pascal_form(int kj,int kj1)
{
int len=kj-kj1;
char *zeros=malloc(sizeof(char)*(len));
memset(zeros,'0',len);
for(int a=0;a<len;a++){
printf("%c",zeros[a]);
}
printf("\n");
//fflush(stdout);
return zeros;
}
Your code has a few basic issues, the main one is that it fails to terminate the string (and include space for the terminator).
Here's a fixed and cleaned-up version:
char * zeros_maker(size_t length)
{
char *s = malloc(length + 1);
if(s != NULL)
{
memset(s, '0', length);
s[length - 1] = '\0';
}
return s;
}
This has the following improvements over your code:
It simplifies the interface, just taking the number of zeroes that should be returned (the length of the returned string). Do the subtraction at the call site, where those two values make sense.
No cast of the return value from malloc(), and no scaling by sizeof (char) since I consider that pointless.
Check for NULL being returned by malloc() before using the memory.
Use memset() to set a range of bytes to a single value, that's a standard C function and much easier to know and verify than a custom loop.
Terminate the string, of course.
Call it like so:
char *zs = zeros_maker(kj - kj1);
puts(s);
free(s);
Remember to free() the string once you're done with it.
Recently I've been learning about Strings and Pointers in C and have learned that you can do some pretty cool things in C using pointer arithmetic which reversing a String is one of these things. The following is the code that I am working with:
#include <stdio.h>
#include <string.h>
void print_reverse_string(char s[])
{
size_t length = strlen(s);
char *beginning = s;
char *end = beginning + length - 1;
while(end >= beginning)
{
printf("%c", *end);
end = end - 1;
}
}
int main()
{
printf("Please enter string to reverse: ");
char input_string[20];
fgets(input_string, 20, stdin);
/* Get rid of new line character from fgets function */
input_string[strlen(input_string) - 1] = '\0';
printf("Reversed string: ");
print_reverse_string(input_string);
return 0;
}
My concern begins with the following line of code:
char *end = beginning + length - 1;
This assumes that the ending memory location of an array will always be greater than the beginning memory location. Is this something that I should be concerned about as a C programmer or can I always be guaranteed that
&randomArray[0] < &randomArray[1] < &randomArray[2] < .... < &randomArray[lastElement]
It's just that I have been reading about different memory spaces and how certain spaces grow upwards while others grow downwards, for example, the stack growing downwards and the heap growing upwards, and thought that there might be a possibility of arrays growing downward in size.
Could this occur on a certain architecture or am I overthinking this possibility?
char *end = beginning + length - 1; leads to undefined behavior when length == 0. Example: "ending memory location of an array will always be greater" may be true expect code wants it to be false. Pointer arithmetic such as beginning + length - 1 is only valid from the beginning of an object to 1 object past its end. So beginning + 0 - 1 is UB.
Subsequent (like in an array) objects' addresses compare in increasing order - regardless of their underlying values, but the arithmetic is valid only in a narrow range.
Better to do
char *end = beginning + length;
while(end > beginning) {
end = end - 1;
printf("%c", *end);
}
Side issue: Should the first character read via fgets() is '\0', the below code attempts input_string[SIZE_MAX] = '\0'
// do not use
input_string[strlen(input_string) - 1] = '\0';
// alternatives
if (*input_string) input_string[strlen(input_string) - 1] = '\0';
// or
input_string[strcspn(input_string, "\n")] = '\0';
C arrays are always allocated contiguously in memory, from lowest address to highest.
This assumes that the ending memory location of an array will always be greater than the beginning memory location.
Yes, your assumption is correct. An array stores its elements in contiguous memory locations and in increasing order.
All answers above me were correct. When you write
char input_string[20];
you get 20*sizeof(char) bytes allocated on the stack, and input_string is only a pointer pointing to the first item, and it is handled like a pointer. For example input_string[10] means *(input_string + 10), etc.
Instead of repeating others, here's a tricky solution of the same task. Recursion in C is lovely for me, or black magic for the ignorants :) Takes some time to understand it, though. Not for serious use, but for fun!
The two backsides of recursion are: danger of stack overflow, and inefficiency. Neither of them are relevant to your question.
#include <stdio.h>
void reverse()
{
int c = getchar();
if (c != '\n' && c != EOF)
{
reverse();
putchar(c);
}
else
printf("Reversed string: ");
}
int main(void)
{
printf("Please enter string to reverse: ");
reverse();
return 0;
}
I'm studying software engineering, and came across this exercise: it asks to write a recursive function in C language that receives a positive integer and an empty string, and "translates" the number into a string. Meaning that after calling the function, the string we sent would contain the number but as a string of its digits.
I wrote this function, but when I tried printing the string, it did print the number I sent, but in reverse.
This is the function:
void strnum(int n, char *str)
{
if(n)
{
strnum(n/10, str+1);
*str = n%10 + '0';
}
}
For example, I sent the number 123 on function call, and the output was 321 instead of 123.
I also tried exchanging the two lines within the if statement, and it still does the same. I can't figure out what I did wrong. Can someone help please?
NOTE: Use of while and for loop statements is not allowed for the exercise.
Note: your current implementation design is somewhat dangerous since you have no way of knowing if you are really writing in valid memory; consider implementing the function with a passed in len to know when you shouldn't try to write anymore; ie. to prevent buffer overruns.
Introduction
The problem is that you are shaving off the least significant digit, but assigning it to the most significant position in the buffer pointed to by str.
You will need to have the "off shaving" and the "assigning" synchronized, so that the least significant digit is stored at the end - and not the beginning.
Hints
Easiest solution would be to do what you currently are doing, and then later reverse the buffer, but this will require far more assignments than what is actually required.
The recommended way is to calculate the number of digits in your string, by doing this you'll know at what offset the end will be, and start assigning the least significant digit at that position.
How do I determine the number of digits of an integer in C?
The hack
Another alternative is having the recursive call modify the current value of our pointer, effectively making it assign the right value - at the right offset.
This example is mostly included because it's "fun", there are (as mentioned) other paths to walk.
#include <stdio.h>
void strnum_impl (int n, char ** str) {
if (n) {
strnum_impl (n/10, str);
**str = n%10 + '0';
(*str)++;
}
}
void strnum (int n, char * str) {
if (n == 0) { *str++ = '0'; }
else { strnum_impl (n, &str); }
*str = '\0'; /* null-terminate */
}
int main () {
char buf[256];
strnum (10240123, buf);
printf (">%s<\n", buf);
return 0;
}
>10240123<
As #Robert Harvey commented, as well as others, code is determining the least rather than the most significant digit and placing it in str[0].
It did look like fun to implement, so the below well copes with the entire range of int including INT_MIN and arbitrary sized int.
static char *strnum_helper(int n, char *str) {
str[0] = '0' - n%10;
if (n < -9) {
return strnum_helper(n/10, str - 1);
}
return str;
}
void strnum(int n, char *str) {
char buf[(sizeof n * CHAR_BIT)/3 + 3]; // Sized to any size int
if (n < 0) {
*str++ = '-';
}
else {
n = -n; // By using negative numbers, do not attempt -INT_MIN
}
buf[sizeof buf - 1] = '\0';
strcpy(str, strnum_helper(n, &buf[sizeof buf - 2]));
}
#Filip Roséen - refp pointed out the value of passing in a size. The above strnum() could be adjusted per a size limitation.
I have a char array filled with some characters. Let's say I have "HelloWorld" in my char array. (not string. taking up index of 0 to 9)
What I'm trying to do is insert a character in the middle of the array, and push the rest to the side to make room for the new character that is being inserted.
So, I can make the char array to have "Hello.World" in it.
char ch[15]; // assume it has "HelloWorld" in it
for(int i=0; i<=strlen(ch)-1; i++) {
if(ch[i]=='o' && ch[i+1]=='W') {
for(int j=strlen(ch)-1; j>=i+2; j--) {
ch[j] = ch[j-1]; // pushing process?
}
ch[i+1] = '.';
break;
}
}
Would this work? Would there be an easier way? I might just be thinking way too complicated on this.
You need to start the inner loop from strlen(ch) + 1, not strlen(ch) - 1, because you need to move the NULL-terminator to the right one place as well. Remember that strlen returns the length of the string such that string[strlen(string)] == '\0'; you can think of strlen as a function for obtaining the index of the NULL-terminator of a C-string.
If you want to move all the characters up by one, then you could do it using memmove.
#include <string.h>
char ch[15];
int make_room_at = 5;
int room_to_make = 1;
memmove(
ch + make_room_at + room_to_make,
ch + make_room_at,
15 - (make_room_at + room_to_make)
);
Simply do:
#define SHIFT 1
char bla[32] = "HelloWorld"; // We reserve enough room for this example
char *ptr = bla + 5; // pointer to "World"
memmove(ptr + SHIFT, ptr, strlen(ptr) + 1); // +1 for the trailing null
The initial starting value for the inner loop is one short. It should be something like the following. Note too that since the characters are moved to the right, a new null terminator needs to be added:
ch[strlen(ch) + 1] = '\0';
for(j=strlen(ch); j>=i+2; j--) { // note no "-1" after the strlen
Edit As far as the "Is this a good way?" part, I think it is reasonable; it just depends on the intended purpose. A couple thoughts come to mind:
Reducing the calls to strlen might be good. It could depend on how good the optimizer is (perhaps some might be optimized out). But each call to strlen require a scan of the string looking for the null terminator. In high traffic code, that can add up. So storing the initial length in a variable and then using the variable elsewhere could help.
This type of operation has the chance for buffer overflow. Always make sure the buffer is long enough (it is in the OP).
If you're going to manipulate a char array you shouldn't make it static. By doing this:
char ch[15];
you're hardcoding the array to always have 15 characters in it. Making it a pointer would be step 1:
char* ch;
This way you can modify it as need be.