I am novice on the topic, I have unsinged char *buffer
I am trying to inspect it at 3 bytes at a time
I think maybe this can be solved with a 2 dimensional array.
so I tried this -
unsigned char *bytes[3] = {};
*bytes = buffer;
but I see that's a notation to create array of 3 elements of type unsigned char *
is there any way to achieve this without having to memcpy
any pointers are greatly appreciated.
this approach seems to work
typedef struct utf8 {
unsigned char bytes[3];
};
typedef struct utf8 utf8x;
utf8x *xx = (utf8x *) buffer; //buffer is a return from fread (unsinged char *)
if (xx->bytes[0] == 0xe0) {
printf("scratch");
}
however I am still trying to figure out how to compare all the bytes, I guess if I cast xx->bytes to return 3 bytes it should work.
You want to compare three bytes of a buffer at once. You can do this using memcmp() (which a good compiler will optimize out so there is no actual function call). For example:
utf8x *xx = (utf8x *) buff;
if (memcmp(&xx->bytes[0], "\100\50\10", 3) == 0) {
printf("scratch");
}
That will print scratch if the first three bytes are \100 \50 \10.
Related
I need to store a list of names in C. I decided a good way to do this would be to use double pointers (or pointers-to-pointers).
So I will have an array of names. Each array value is a pointer to another array: the name, stored as a character array.
The names might look like
unsigned char *name = "Joseph";
etc.
And then I would have a list of names (double pointer), to which I could (dynamically) assign each name (single pointer).
(type) **listOfNames;
My question is: what type should the double pointer be? Since it is a pointer to a pointer, I was thinking that it must be large enough to hold an arbitrary memory address: unsigned long, maybe? Or is there another type meant specifically for double pointers?
Alternatively — is there a better way of storing a variable-length array or variable-length strings?
If you have a collection of unsigned char * values:
unsigned char *name_0 = "Joseph";
unsigned char *name_1 = "Helen";
unsigned char *name_2 = "Maximillian";
Then you can create:
unsigned char *data[] = { name_0, name_1, name_2 };
unsigned char **listOfNames = data;
Note that you need to allocate space for the list of pointers — in my code, that's the data array. You could use malloc() instead, but you'd need to remember to code the matching free() at some point.
Adding appropriate const qualifications is left as an exercise in frustration to the interested reader.
If you are reading a variable length list of names from a file a run time, with (presumably) one name per line, then you'd do best with POSIX getline() and strdup().
There must be a number of other questions that deal with this scenario, so I'll be terse with this code:
char **read_file(FILE *fp)
{
char *buffer = 0;
size_t bufsiz = 0;
char **lines = 0;
size_t n_lines = 0;
size_t n_alloc = 0;
while (getline(&buffer, &bufsiz, fp) > 0)
{
if (n_lines + 1 >= n_alloc)
{
size_t new_num = (n_alloc + 1) * 2;
size_t new_size = new_num * sizeof(*lines);
char **new_lines = realloc(lines, new_size);
if (new_lines == 0)
{
free(buffer);
free(lines);
return(0);
}
lines = new_lines;
n_alloc = new_num;
}
lines[n_lines++] = strdup(buffer); // Includes newline!
}
lines[n_lines] = 0; // Null terminate list of strings
free(buffer); // Release input line's memory
return lines;
}
Note that the code uses plain char and not unsigned char. You face some issues if you use unsigned char because neither getline() nor strdup() expects to work with unsigned char. While you can cast your way around the issue, it is messy to do so.
I'm new here, and I need some help. :)
I am working on a program that has to write and read a binary file. I have to add lectures to it, they look like:
COURSECODE;COURSENAME;MAXAPPLICANTS;ACTUALAPPLICANTS;
I could write that in a file without any problems using char*.
My question is: how do I read that back in a struct if the records are non-fixed size? (e.g.: coursename can be Linear Algebra or Analysis -> length is non-determined) I also need to modify the actual applicants number, how do I find the character position of it, and the current line?
I'd be happy with ideas, and I would appreciate any source code as well, I was programming in C++ and C is a hard step-back for me.
Thank you in advance!
Your structure looks like
struct student {
char *coursecode;
char *coursename;
char *max_applicants;
char *actual_applicants;
};
Just add another member into your structure say int size which stores total size of structure.
Every time when you read from binary file you should read first 4 bytes you will get complete size of record,then see how many characters are there into record,read that much and tokenize string by ; you will find your records.
without termination characters it is impossible.
If you dedicate some character to split data apart, then its possible.
for instance, 3 strings can be told apart by their \0. so you read until \0, three times.
You could read the file into a char* buffer, then replace any ; with \0 (the string termination character) and finally you take pointers of the begins of the fields into your struct:
struct student {
char *coursecode;
char *coursename;
char *max_applicants;
char *actual_applicants;
};
You might want to parse numeric fields with atoi first.
Piece of advice #1: if you're Hindi and you ever re-born, start by learning C, only then transition to C++.
Piece of advice #2: so if I understand correctly, you have four strings in a row, separated by semi-colons. Then you can use strtok_r() to split up each line and put the contents of the file in an array of structs (all error checking omitted for clarity, but you should definitely have some):
typedef struct {
char *code;
char *name;
int max_appl;
int cur_appl;
} Course;
char buf[1024];
FILE *f = fopen("courses.txt", "r");
size_t size = 0;
size_t allocsize = 8;
Course *c = malloc(allocsize * sizeof(*c));
char *end;
while (fgets(buf, sizeof(buf), f) != NULL) {
if (size >= allocsize) {
allocsize <<= 1;
c = realloc(c, allocsize * sizeof(*c));
}
c[size].code = strdup(strtok_r(buf, ";", &end));
c[size].name = strdup(strtok_r(NULL, ";", &end));
c[size].max_appl = strtol(strtok_r(NULL, ";", &end), NULL, 10);
c[size].cur_appl = strtol(strtok_r(NULL, "\n", &end), NULL, 10);
size++;
}
int i;
for (i = 0; i < size; i++) {
Course *p = c + i;
printf("%s\n%s\n%d\n%d\n\n", p->code, p->name, p->max_appl, p->cur_appl);
free(p->code);
free(p->name);
}
free(c);
fclose(f);
I'm very new to C, I'm getting stuck using the strncpy function.\
Here's an example of what I'm working with:
int main()
{
const char *s = "how";
struct test {
char *name;
};
struct test *t1 = malloc(sizeof(struct test));
strncpy(t1->name, s, sizeof(*s));
t1->name[NAMESIZE] = '\0';
printf("%s\n", t1->name);
}
I have a const char *, I need to set the "name" value of test to the const char. I'm having a really tough time figuring this out. Is this even the correct approach?
Thank you very much!
Well, you allocate the structure, but not the string inside the structure. You need to do that before you copy to it. Even when you do, you will probably overwrite unallocated memory when you attempt to set the string terminator.
And, due to a hight intake ow wine, I just noticed you actually only copy one character, but it's still undefined behavior.
Let's take this one step at a time:
struct test *t1 = malloc(sizeof(struct test));
this allocates space for a struct test; enough space for the pointer name, but not any memory for the pointer to point to. At a minimum, you'll want to do the following:
t1->name = malloc(strlen(s) + 1);
Having done that, you can proceed to copy the string. However, you already computed the length of the string once to allocate the memory; there's no sense in doing it again implicitly by calling strncpy. Instead, do the following:
const size_t len = strlen(s) + 1; // +1 accounts for terminating NUL
t1->name = malloc(len);
memcpy(t1->name, s, len);
In general, try to use this basic pattern; compute the length of strings once when they come into your code, but then use explicit-sized memory buffers and the mem* operations instead of implicit-length strings with str* operations. It is at least as safe (and often safer) and more efficient if done properly.
You might use strncpy if t1->name was a fixed-size array instead (though many people prefer to use strlcpy). That would look like the following:
struct test { char name[MAXSIZE]; };
struct test *t1 = malloc(sizeof *t1);
strncpy(t1->name, s, MAXSIZE - 1);
t1->name[MAXSIZE-1] = 0; // force NUL-termination
Note that the size argument to strncpy should always be the size of the destination, not the source, to avoid writing outside the bounds of the destination buffer.
Without any attempt at completeness or educational direction, here's a version of your code that should work. You can play "spot the difference" and search for an explanation for each one separately on this site.
int main()
{
const char s[] = "how"; // s is an array, const char[4]
struct test{ char name[NAMESIZE]; }; // test::name is an array
struct test * t1 = malloc(sizeof *t1); // DRY
strncpy(t1->name, s, NAMESIZE); // size of the destination
t1->name[NAMESIZE - 1] = '\0'; // because strncpy is evil
printf("%s\n", t1->name);
free(t1); // clean up
}
strncpy() is always wrong
if the result is too long, the target string will not be nul-terminated
if the target is too long (the third argument) , the trailing end will be completely padded with NULs. This will waste a lot of cycles if you have large buffers and short strings.
Instead, you cound use memcpy() or strcpy, (or in your case even strdup() )
int main()
{
const char *s = "how";
struct test {
char *name;
};
struct test *t1
size_t len;
t1 = malloc(sizeof *t1);
#if USE_STRDUP
t1->name = strdup(s);
#else
len = strlen(s);
t1->name = malloc (1+len);
memcpy(t1->name, s, len);
t1->name[len] = '\0';
#endif
printf("%s\n", t1->name);
return 0;
}
Initially I want to convert this uint8_t array to a char array in c. I have been a little stuck trying to resolve this problem. My first alternative solution is to copy another type value to the temporary one, copy the tmp value to a writable char, and then remove tmp value from memory. By the way this is used to accompany a blake hash function. Here is my code snippet:
char * bl(char *input)
{
uint8_t output[64];
char msg[]= "";
char *tmp;
int dInt;
memset(output,0,64);
tmp = (char*) malloc(64);
if (!tmp){
exit( 1);
}
dInt = strlen(input);
if (dInt > 0xffff){
exit( 1);
}
uint8_t data[dInt];
memset(data,0, dInt);
strlcpy(data,input,dInt);
uint64_t dLen =dInt;
blake512_hash(output, data,dLen);
int k;
for (k=0;k<64;k++){
tmp[k] = output[k]; //does this "copy" is buggy code?
}
memcpy(msg, tmp,64);
//so here I can to delete tmp value
// I dont want there were left unused value in memory
// delete tmp;
free(tmp);
return msg;
}
I think the code above is still not efficient, so what are your opinion, hints and the fixes?
Thank you very much before!
First of all, you should never return a pointer to a local variable since the variable will be destroyed by the time the function exits. You should probably want to pass the output array to bl function and use that to output the string.
For most cases(if uint8_t IS char, which is usually the case), memcpy(msg, output, 64) should be sufficient. If you want to be strict about it(quite frankly blake512_hash shouldn't return uint8_t array in the first place if you are expecting char array as the output all the time), you could simply call msg[k] = (char)tmp[k] in your for loop and remove memcpy.
A bit much is wrong here.
dInt = strlen(input) + 1; // dInt is the size of the string including the terminating '\0'.
strlcpy indeed uses the size, not strlen.
msg = tmp; and not freeing tmp. As msg is const char* "" (in C++ terms).
I am new to C and working on it since two months. I have a structure shown below:
struct profile_t
{
unsigned char length;
unsigned char type;
unsigned char *data;
};
typedef struct profile_datagram_t
{
unsigned char *src;
unsigned char *dst;
unsigned char ver;
unsigned char n;
struct profile_t profiles[MAXPROFILES];
} header;
header outObj;
Now the values inside the elements of the structure are read as outObj.src[i], outObj.dst[i], and outObj.profiles[i].type.
Now I want to call a function and pass the values read by me to a function which is actually a Berkeley DB.
void main()
{
struct pearson_record {
unsigned char src[6];
unsigned char dst[6];
unsigned char type;
};
DB *dbp;
int ret;
if ((ret = db_create(&dbp, dbenv, 0)) !=0)
handle_error(ret);
if ((ret = dbp->open(dbp, NULL, "pearson.db", NULL, DB_BTREE, DB_CREATE, 0600)) !=0)
handle_error(ret);
const DBT *pkey;
const DBT *pdata;
struct pearson_record p;
DBT data, key;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
memset(&s, 0, sizeof(struct pearson_record));
Now the above code is written by looking at a example from the DB reference guide. but i don't understand what is const DBT. Also they have added the value inside structure using memcopy which I know is the right way, but now I want to memcopy the values passed which are mentioned above and store them in the structure pearson_record. How should I go with this?? Any kind of help would be appreciated.
Please post the complete code. You mention "they memcopy" (which I assume you refer to memcpy), but all I see is a bunch of memset(*,0). Hope you're not confusing them.
Also "they have added the value inside structure using memcopy which I know is the right way" is not entirely true. It's not necessarily wrong, BUT... char* is basically interpreted as a C string. that is an array of bytes which represent characters which MUST be null terminated (that is the last character must be 0, equivalent to '\0'). The proper way to copy strings is using strcpy() (or strcpy_s on windows), the difference is memcpy is faster and used in other situations (such as pointers\buffer management).
unsigned char* is not so used (at least I never saw it till now). As a note read about char, unsigned char, signed char, char[] and char* (not that it changes your code in any way, but just to make sure you understand the differences).
As for copying data, I assume you mean src, dst and type from pearson_record to header, correct ? If so, for the sake of simplicity I wanted to suggest memcpy but you say that each element is accessed as [i]. Does that mean header.src is an array of more than one pearson_record.src or does header.src[i] correspond to pearson_record.src[i] ? This is slightly unclear to me.
There is a difference between char* src and char* *src.