Convert *char or char to bits - c

How do I convert * char or char to bits ?
For example:
Here 's my declarations
uint64_t blocks[64];
char * word = "hello";
How do I store the word hello in bytes inside blocks[0] ?
I tried this
int e;
int a = strlen(word);
for (e = 0; e < a; e++) {
blocks[0] |= !!word[e] >> 8;
}
Also, how will I reverse the process?

"I want to copy the bits in a char into a uint64_t."
Try using memcpy:
void * memcpy(void * dst, const void * src, size_t n)
e.g.
memcpy(blocks, word, strlen(word));
More than one string
Regarding your comment which I interpret to be about copying more than one string:
memcpy copies n bytes from src to dst, so if we want to copy several strings in succession, we need to make sure calls to memcpy have src set to the end of the last string we copied, assuming we want to copy "hello" and then "world" into blocks and end up with the bytes that represent "helloworld".
// if you have a char** words and uint64_t blocks[64]; or similar
uint64_t blocks[64];
const char *words[2] = { "hello", "world" };
size_t offset = 0, len;
int num_words = sizeof words / sizeof words[0], n;
for (n = 0; n < num_words && offset < sizeof blocks; ++n) {
len = strlen(words[n]);
memcpy(((void *)blocks) + offset, words[n], len); // note the void * cast
offset += len;
}
This should be easily adaptable to a situation where you are reading in the strings rather than having an array of array of chars.
Getting a string back again
To take blocks and get a char * with all the bytes in it, we need to remember that strings in C are null terminated, so if we want to treat the result as a string, it needs a null on the end. The last offset you have once you are done copying (from above) could be used to add this.
char new_word[100];
memcpy(new_word, blocks, sizeof new_word);
new_word[offset] = 0;
We don't have to copy the data to treat this as a char *, by the way; We could just cast...
char * new_word = (char *)blocks;
...but remember that if you do this, modifying new_word will also modify blocks.

Related

How to find the length of a string char[] in c without using a library. (Not even c standard)

I want to use no libraries at all (not even c standard) and find how long a string is in an array of characters.
It's a matter of counting the characters in the array before you find the first \0, something like:
unsigned int StrLen(char *str) {
unsigned int len = 0;
while (*str != '\0') {
str++;
len++;
}
return len;
}
The answer you want is probably paxdiablo's, but here is another way albeit much more restricted. You can use sizeof for your statically allocated arrays.
char str[] = "12345";
unsigned int size = sizeof str; // will return 6: 5 +1 for null-termiantor
Beware that this method doesn't look for the null-terminator, instead it returns the allocated memory, so:
char arr[10] = { 0 };
arr[0] = 'a';
arr[1] = '\0';
unsigned int size = sizeof arr; // will return 10, not 2.
It also won't work with dynamically allocated arrays
char *arr = malloc( 5 * sizeof *arr );
unsigned int size = sizeof arr; // is the same as sizeof *char
// simply returns the size of a char pointer in your system.

allocate dynamic memory for char array

I have to print some values stored in the struct to single char array , I am not getting an simple method to allocate a memory for a variable array values .
below snnipet of the code which I need to do
struct types {
char *name;
char *address;
char * descrption;
};
int main ()
{
int numberofUser = 10;
struct types allUsers[numberofUser];
//Assume here I filled all the user details by allocation memory.
// now I need to print these values in the formated string like below
char* outputString;
int i ;
for(i =0 ; i<numberofUser;i++)
{
sprintf(outputString,"<start>name=%s,add=%s,des=%s",allUsers[i].name,allUsers[i].address,allUsers[i].descrption);
}
}
How to allocate memory for the output string which can hold all structure values
Define the format string and store it in a variable of its own.
char const* formatString = "<start>name=%s,add=%s,des=%s";
Get the length of the format string.
size_t formatStringLen = strlen(formatString);
Get the lengths of the members of the struct.
size_t nameLen = strlen(allUser[i].name);
size_t addLen = strlen(allUser[i].address);
size_t desLen = strlen(allUser[i].description);
Allocate enough memory to hold the format string as well as the members of the struct.
// This will be more than the exact space you need but certainly
// not less than what you need and not too much more than what you
// need.
size_t totalLen = formatStringLen + nameLen + addLen + desLen;
outputString = malloc(totalLen);
Use sprintf
sprintf(outputString, formatString,
allUsers[i].name, allUsers[i].address, allUsers[i].descrption);
You need to calculate length of strings involved and allocate that much memory to it. Something like
int len = 0;
len = strlen(allUsers[i].name)
+ strlen(allUsers[i].address)
+ strlen(allUsers[i].descrption);
len += strlen("<start>name=")
+ strlen(",add=")
+ strlen(",des=");
len ++ // for '\0'
outputString = malloc(sizeof(char) * len);
Note: this is for 1 record in allUsers as strings may change in other elements.
You should check for valid pointers and should free memory after used.
The members of your structure are pointers to characters, i.e. of type char * but you need a character array to store the strings. The size of the array must be one more than the maximum length the string can have to accommodate the terminating null byte which marks the end of the string. I suggest the following changes -
#include <stdio.h>
#include <string.h>
#define NAMELEN 20+1 // max length of name + 1
#define ADDRLEN 40+1 // max length of address + 1
#define DESCLEN 80+1 // max length of description + 1
struct types {
char name[NAMELEN];
char address[ADDRLEN];
char descrption[DESCLEN];
};
int main(void) {
int numberofUser = 10;
struct types allUsers[numberofUser];
// assign values to array elements
// format string for sprintf
const char *fstr = "<start>name=%s,add=%s,des=%s";
// strlen doesn't count the null byte. macros include null byte
// so get space for 2 extra null bytes which is not needed.
int outlen = strlen(fstr) + NAMELEN + ADDRLEN + DESCLEN - 2;
// variable-length to store the output string
char outputString[outlen];
for(int i = 0; i < numberofUser; i++) {
sprintf(outputString, "<start>name=%s,add=%s,des=%s",
allUsers[i].name,
allUsers[i].address,
allUsers[i].descrption);
// print the string
printf("%s\n", outputString);
}
return 0;
}
If your compiler supports C99 then it shall contain function snprintf. To allocate and set your string, you can use the following code:
char *outputString;
int len;
outputString = NULL;
len = 0;
for(;;) {
// this loop is executed only two times
len = 1 + snprintf(outputString, len, "<start>name=%s,add=%s,des=%s",allUsers[i].name,allUsers[i].address,allUsers[i].descrption);
if (outputString != NULL) break; // success
outputString = realloc(outputString, len);
if (outputString == NULL) break; // fail
}

What's wrong with this character buffer code?

For reasons that I promise exist, I'm reading input character by character, and if a character meets certain criteria, I'm writing it into a dynamically allocated buffer. This function adds the specified character to the "end" of the specified string. When reading out of the buffer, I read the first 'size' characters.
void append(char c, char *str, int size)
{
if(size + 1 > strlen(str))
str = (char*)realloc(str,sizeof(char)*(size + 1));
str[size] = c;
}
This function, through various iterations of development has produced such errors as "corrupted double-linked list", "double free or corruption". Below is a sample of how append is supposed to be used:
// buffer is a string
// bufSize is the number of non-garbage characters at the beginning of buffer
char *buft = buffer;
int bufLoc=0;
while((buft-buffer)/sizeof(char) < bufSize)
append(*(buft==),destination,bufLoc++);
It generally works for some seemingly arbitrary number of characters, and then aborts with error. If it's not clear what the second code snippet is doing, it's just copying from the buffer into some destination string. I know there's library methods for this, but I need a bit finer control of what exactly gets copied sometimes.
Thanks in advance for any insight. I'm stumped.
This function does not append a character to a buffer.
void append(char c, char *str, int size)
{
if(size + 1 > strlen(str))
str = realloc(str, size + 1);
str[size] = c;
}
First, what is strlen(str)? You can say "it's the length of str", but that's omitting some very important details. How does it compute the length? Easy -- str must be NUL-terminated, and strlen finds the offset of the first NUL byte in it. If your buffer doesn't have a NUL byte at the end, then you can't use strlen to find its length.
Typically, you will want to keep track of the buffer's length. In order to reduce the number of reallocations, keep track of the buffer size and the amount of data in it separately.
struct buf {
char *buf;
size_t buflen;
size_t bufalloc;
};
void buf_init(struct buf *b)
{
buf->buf = NULL;
buf->buflen = 0;
buf->bufalloc = 0;
}
void buf_append(struct buf *b, int c)
{
if (buf->buflen >= buf->bufalloc) {
size_t newalloc = buf->bufalloc ? buf->bufalloc * 2 : 16;
char *newbuf = realloc(buf->buf, newalloc);
if (!newbuf)
abort();
buf->buf = newbuf;
buf->bufalloc = newalloc;
}
buf->buf[buf->buflen++] = c;
}
Another problem
This code:
str = realloc(str, size + 1);
It only changes the value of str in append -- it doesn't change the value of str in the calling function. Function arguments are local to the function, and changing them doesn't affect anything outside of the function.
Minor quibbles
This is a bit strange:
// Weird
x = (char*)realloc(str,sizeof(char)*(size + 1));
The (char *) cast is not only unnecessary, but it can actually mask an error -- if you forget to include <stdlib.h>, the cast will allow the code to compile anyway. Bummer.
And sizeof(char) is 1, by definition. So don't bother.
// Fixed
x = realloc(str, size + 1);
When you do a:
str = (char*)realloc(str,sizeof(char)*(size + 1));
the changes in str will not be reflected in the calling function, in other words the changes are local to the function as the pointer is passed by value. To fix this you can either return the value of str:
char * append(char c, char *str, int size)
{
if(size + 1 > strlen(str))
str = (char*)realloc(str,sizeof(char)*(size + 1));
str[size] = c;
return str;
}
or you can pass the pointer by address:
void append(char c, char **str, int size)
{
if(size + 1 > strlen(str))
*str = (char*)realloc(*str,sizeof(char)*(size + 1));
(*str)[size] = c;
}

c splitting a char* into an char**

I'm reading in a line from a file (char by char, using fgetc()), where all fields(firstname, lastname, ...) are seperated by an ;. What I now want to do is create a char**, add all the chars to that and replace the ; by \0 so that I effectively get a list of all the fields.
Is that actually possibly? And when I create a char**, e.g. char ** buf = malloc(80) can I treat it like a one dimensional array? If the memory returned by malloc contiguous?
EDIT
Sry, meant to replace ; by \0, bot \n.
EDIT 2
This code should demonstrate what I intend to do (may clarify things a little):
int length = 80; // initial length char *buf = malloc(length); int num_chars = 0;
// handle malloc returning NULL
// suppose we already have a FILE pointer fp for (int ch = fgetc(fp); ch != EOF && ferror(fp) == 0; ch = fgetc(fp)) {
if (length == size) { // expand array if necessary
length += 80;
buf = realloc(buf, length);
// handle realloc failure
}
if (ch == ';') {
buf[num_chars] = '\0'; // replace delimiter by null-terminator
} else {
buf[num_chars] = ch; // else put char in buf
} }
// resize the buffer to chars read buf
= realloc(buf, num_chars);
// now comes the part where I'm quite unsure if it works / is possible
char **list = (char **)buf; // and now I should be able to handle it like a list of strings?
Yes, it's possible. Yes, you can treat it as a one dimensional array. Yes, the memory is contiguous.
But you probably want:
char ** fields = malloc(sizeof(char *) * numFields);
Then you can do:
// assuming `field` is a `char *`
fields[i++] = field;
It's not exactly possible as you describe it, but something similar is possible.
More specifically, the last line of your example char **list = (char **)buf; won't do what you believe. char **list means items pointed by *list will be of the type char*, but the content of *buf are chars. Hence it won't be possible to change one into another.
You should understand that a char ** is just a pointer, it can hold nothing by itself. But the char ** can be the start address of an array of char *, each char * pointing to a field.
You will have to allocate space for the char * array using a first malloc (or you also can use a static array of char * instead of a char**. You also will have to find space for every individual field, probably performing a malloc for each field and copying it from the initial buffer. If the initial buffer is untouched after reading, it would also be possible to use it to keep the field names, but if you just replace the initial ; by a \n, you'll be missing the trailing 0 string terminator, you can't replace inplace one char by two char.
Below is a simplified example of what can be done (removed malloc part as it does not add much to the example, and makes it uselessly complex, that's another story):
#include <stdio.h>
#include <string.h>
main(){
// let's define a buffer with space enough for 100 chars
// no need to perform dynamic allocation for a small example like this
char buf[100];
const char * data = "one;two;three;four;";
// now we want an array of pointer to fields,
// here again we use a static buffer for simplicity,
// instead of a char** with a malloc
char * fields[10];
int nbfields = 0;
int i = 0;
char * start_of_field;
// let's initialize buf with some data,
// a semi-colon terminated list of strings
strcpy(buf, data);
start_of_field = buf;
// seek end of each field and
// copy addresses of field to fields (array of char*)
for (i = 0; buf[i] != 0; i++){
if (buf[i] == ';'){
buf[i] = 0;
fields[nbfields] = start_of_field;
nbfields++;
start_of_field = buf+i+1;
}
}
// Now I can address fields individually
printf("total number of fields = %d\n"
"third field is = \"%s\"\n",
nbfields, fields[2]);
}
I now want to do is create a char**, add all the chars to that
You would allocate an array of char (char*) to store the characters, not an array of char* (char**).
And when I create a char*, e.g. char * buf = malloc(80) can I treat it like a one dimensional array? If the memory returned by malloc contiguous?
Yes, malloc always returns continguous blocks. Yes, you can treat it as single-dimensional an array of char* (with 80/sizeof char* elements). But you'll need to seperately allocate memory for each string you store in this array, or create another block for storing the string data, then use your first array to store pointers into that block.
(or something else; lots of ways to skin this cat)
It may be that Helper Method wants each of the "fields" written to a nul-terminated string. I cannot tell. You can do that with strtok(). However strtok() has problems - it destroys the original string "fed" to it.
#define SPLIT_ARRSZ 20 /* max possible number of fields */
char **
split( char *result[], char *w, const char *delim)
{
int i=0;
char *p=NULL;
for(i=0, result[0]=NULL, p=strtok(w, delim); p!=NULL; p=strtok(NULL, delim), i++ )
{
result[i]=p;
result[i+1]=NULL;
}
return result;
}
void
usage_for_split(void)
{
char *result[SPLIT_ARRSZ]={NULL};
char str[]="1;2;3;4;5;6;7;8;9;This is the last field\n";
char *w=strdup(str);
int i=0;
split(result, w, ";\n");
for(i=0; result[i]!=NULL; i++)
printf("Field #%d = '%s'\n", i, result[i]);
free(w);
}

How to Concatenate 2 C strings, without overwriting any terminating Null characters?

I am trying to set up a list of file names for a parameter to SHFileOperation. I want to be able to concatenate a file name onto the char array, but i dont want to get rid of the terminating character. for example, I want this:
C:\...\0E:\...\0F:\...\0\0
when i use strcat(), it overwrites the null, so it looks like
C:\...E:\...F:\...0\
Is there any easy way to do this? or am i going to have to code a new strcat for myself?
The code is pretty straightforward. Use a helper pointer to track where the next string should start. To update the tracker pointer, increment by the length of the string +1:
const char *data[] = { "a", "b", "c" };
size_t data_count = sizeof(data) / sizeof(*data);
size_t d;
size_t buffer_size;
char *buffer;
char *next;
// calculate the size of the buffer
for (d = 0; d < data_count; ++d)
buffer_size += (strlen(data[d] + 1);
buffer_size += 1;
buffer = malloc(buffer_size);
// Next will track where we write the next string
next = buffer;
for (d = 0; d < data_count; ++d)
{
strcpy(next, data[d]);
// Update next to point to the first character after the terminating NUL
next += strlen(data[d]) + 1;
}
*next = '\0';
Use memcpy.
memcpy(dest, src1, strlen(src1)+1);
memcpy(&dest[strlen(src1)+1], src2, strlen(src2)+1);
Using the GNU stpcpy() may be slightly more elegant, if you know beforehand the maximum 'length' of the resulting char array.
char *src[] = {"C:\\foo", "E:\\bar", "F:\\foobar", 0};
char dst[MY_MAX_LEN], *p = dst;
int i;
for (i = 0; src[i]; i++)
p = stpcpy(p, src) + 1;
*p = 0;
assert(p < dst + sizeof dst);
If needed, stpcpy() can be defined as:
char *stpcpy(char * restrict dst, const char * restrict src)
{
return strcpy(dst, src) + strlen(src);
}
just use strcat to append to the original string, but add one to the offset so you're bypassing the previous string's 0 terminator.
// an example
char testString [256];
strcpy (testString, "Test1");
strcat (testString + strlen(testString)+1, "Test2");
strcat (testString + strlen(testString)+1, "Test3");
testString will now contain "Test1\0Test2\0Test3\0"

Resources