I would like to ask how to add one char to a buffer. For example:
char buffer[50];
char one_symbol;
How to add one_symbol to buffer? I don't know how long the buffer is at the time, so I cant just write, for example buffer[5] = one_symbol;
Thanks.
You need to do something to keep track of the length of the data in the buffer.
You have a couple of choices about how to do that. Strings store data in the buffer (a NUL byte) to signal where there data ends. Another possibility is to store the length externally:
typedef struct {
char data[50];
size_t len;
} buffer;
This latter is particularly preferable when/if you want to allow for data that itself might include NUL bytes. If you don't want your buffer size fixed at 50, you can go a step further:
typedef struct {
size_t allocated;
size_t in_use;
char data[];
};
Note that this uses a flexible array member, which was added in C99, so some older compilers don't support it.
Keep track or the buffers current size. You can do it by adding a new variable for that.
Something like:
char buffer[50];
size_t current_size = 0; /* Buffer is of size zero from the size */
/* ... */
/* Add one character to the buffer */
buffer[current_size++] = 'a';
Related
I need to be able to check in a kernel module whether or not a file descriptor, dentry, or inode falls under a certain path. To do this, I am going to have to write a function that when given a dentry or a file descriptor (not sure which, yet), will return said object's full path name.
What is the way to write a function that returns variable-length strings?
You can try like this:
char *myFunction(void)
{
char *word;
word = malloc (sizeof (some_random_length));
//add some random characters
return word;
}
You can also refer related thread: best practice for returning a variable length string in c
The typical way to do this in C, is not to return anything at all:
void func (char* buf, size_t buf_size, size_t* length);
Where buf is a pointer to the buffer which will hold the string, allocated by the caller. buf_size is the size of that buffer. And length is how much of that buffer that the function used.
You could return a pointer to buf as done by for example strcpy. But this doesn't make much sense, since the same pointer already exists in one of the parameters. It adds nothing but confusion.
(Don't use strcpy, strcat etc functions as some role model for how to write functions. Many C standard library functions have obscure prototypes, because they are so terribly old, from a time when good programming practice wasn't invented, or at least not known by Dennis Ritchie.)
There are two common approaches:
One is to have a fixed size buffer to store the result:
int makeFullPath(char *buffer,size_t max_size,...)
{
int actual_size = snprintf(buffer,max_size,...);
return actual_size;
}
Examples of standard functions which use this approach are strncpy() and snprintf(). This approach has the advantage that no dynamic memory allocation is needed, which will give better performance for time-critical functions. The downside is that it puts more responsibility on the caller to be able to determine the largest possible result size in advance or be ready to reallocate if a larger size is necessary.
The second common approach is to calculate how big of a buffer to use and allocate that many bytes internally:
// Caller eventually needs to free() the result.
char* makeFullPath(...)
{
size_t max_size = calculateFullPathSize(...);
char *buffer = malloc(max_size);
if (!buffer) return NULL;
int actual_size = snprintf(buffer,max_size,...);
assert(actual_size<max_size);
return buffer;
}
An example of a standard function that uses this approach is strdup(). The advantage is that the caller no longer needs to worry about the size, but they now need to make sure that they free the result. For a kernel module, you would use kmalloc() and kfree() instead of malloc() and free().
A less common approach is to have a static buffer:
const char *makeFullPath(char *buffer,size_t max_size,...)
{
static char buffer[MAX_PATH];
int actual_size = snprintf(buffer,MAX_PATH,...);
return buffer;
}
This avoids the caller having to worry about the size or freeing the result, and it is also efficient, but it has the downside that the caller now has to make sure that they don't call the function a second time while the result of the first call is still being used.
char *result1 = makeFullPath(...);
char *result2 = makeFullPath(...);
printf("%s",result1);
printf("%s",result2); /* oops! */
Here, the caller probably meant to print two separate strings, but they'll actually just get the second string twice. This is also problematic in multi-threaded code, and probably unusable for kernel code.
For example:
char * fn( int file_id )
{
static char res[MAX_PATH];
// fill res[]
return res;
}
/*
let do it the BSTR way (BasicString of VB)
*/
char * CopyString(char *str){
unsigned short len;
char *buff;
len=lstrlen(str);
buff=malloc(sizeof(short)+len+1);
if(buff){
((short*)buff)[0]=len+1;
buff=&((short*)buff)[1];
strcpy(buff,str);
}
return buff;
}
#define len_of_string(s) ((short*)s)[-1])
#define free_string(s) free(&((short*)s)[-1]))
int main(){
char *buff=CopyString("full_path_name");
if(buff){
printf("len of string= %d\n",len_of_string(buff));
free_string(buff);
}else{
printf("Error: malloc failed\n");
}
return 0;
}
/*
now you can imagine how to reallocate the string to a new size
*/
In C I am reading binary data from a file into a var data like this:
unsigned char *data;
data = malloc(size);
int read_size = fread(data, 1, size, fp);
I want to prepend the var data with <filename><size> of the file. How can I achieve this?
It's not a legal C string because it's binary data with null bytes potentially all over the place.
I know to make sure I allocate it with enough memory, I just can't figure out how to actually prepend it.
Allocate enough memory to data.
Copy the prefix into it.
Get a reference to just behind what had been copied in 2..
Pass this reference to fread().
Define your own data format for storage:
<uint64_t datalength><string name><char[datalength] contents>
Or for easier in-app use:
struct named_file {
char* contents;
uint64_t datasize;
char name[]; // contents begin directly after the name.
}
Allocate the struct with enough space: sizeof(named_file)+strlen(_name)+1+_datasize
strcpy(name, _name)
contents = name+strlen(name)+1
save data to contents-pointer. memcpy(), direct reading, whatever.
I have a program that is reading a file, but not saving into the structure. Once the data is read, it should be saved within the structure in order for the program to be able to use said data later. I'm having a heck of a time figuring out how to get this done.
structure
typedef struct friends_contact {
char *First_Name;
char *Last_Name;
char *home_phone;
char *cell_phone;
} fr;
Reading of the file
void ReadFile(fr *friends, int *counter, char buffer[], FILE *read) {
fseek(read, 0, SEEK_SET);
while (fscanf(read, "%s", buffer) != EOF) {
friends[*counter].First_Name = malloc(BUFFSIZE * strlen(buffer));
strcpy(friends[*counter].First_Name, buffer);
}
}
More information can be provided as needed. I just want to figure out why the information isn't saving within the structure so that it can be called on later.
What is "friends"? global variable?
What is "contacts"? It is not used in function.
May be you mix them?
BUFFSIZE * strlen(buffer) -> What do you mean? you allocate strlen(buffer) BUFFSIZE times.
Possibly it should be sizeof(char) * strlen(buffer) ?
I also think you should check the length of "buffer" after operation fscanf.
The code you use for allocating space for the char array and then copying to it makes sense but one of two things could be happening in your while() cycle: the condition is evaluated instantly to false so nothing is copied or you iterate over and over again until fscanf writes an empty string to buffer and this overwrites the content of friends[*counter].First_Name, should you increment *counter in the body of while()?
I am not used to programming in c, so I am wondering how to have an array, and then read a variable amount of variables in a file, and those these files in the array.
//how do I declare an array whose sizes varies
do {
char buffer[1000];
fscanf(file, %[^\n]\n", buffer);
//how do i add buffer to array
}while(!feof(file));
int nlines = 0
char **lines = NULL; /* Array of resulting lines */
int curline = 0;
char buffer[BUFSIZ]; /* Just alloocate this once, not each time through the loop */
do {
if (fgets(buffer, sizeof buffer, file)) { /* fgets() is the easy way to read a line */
if (curline >= nlines) { /* Have we filled up the result array? */
nlines += 1000; /* Increase size by 1,000 */
lines = realloc(lines, nlines*sizeof(*lines); /* And grow the array */
}
lines[curline] = strdup(buffer); /* Make a copy of the input line and add it to the array */
curline++;
}
}while(!feof(file));
Arrays are always fixed-size in C. You cannot change their size. What you can do is make an estimate of how much space you'll need beforehand and allocate that space dynamically (with malloc()). If you happen to run out of space, you reallocate. See the documentation for realloc() for that. Basically, you do:
buffer = realloc(size);
The new size can be larger or smaller than what you had before (meaning you can "grow" or "shrink" the array.) So if at first you want, say, space for 5000 characters, you do:
char* buffer = malloc(5000);
If later you run out of space and want an additional 2000 characters (so the new size will be 7000), you would do:
buffer = realloc(7000);
The already existing contents of buffer are preserved. Note that realloc() might not be able to really grow the memory block, so it might allocate an entirely new block first, then copy the contents of the old memory to the new block, and then free the old memory. That means that if you stored a copy of the buffer pointer elsewhere, it will point to the old memory block which doesn't exist anymore. For example:
char* ptr = buffer;
buffer = realloc(7000);
At that point, ptr is only valid if ptr == buffer, which is not guaranteed to be the case.
It appears that you are trying to read until you read a newline.
The easiest way to do this is via getline.
char *buffer = NULL;
int buffer_len;
int ret = getline(&buffer, &buffer_len, file);
...this will read one line of text from the file file (unless ret is -1, in which there's an error or you're at the end of the file).
An array where the string data is in the array entry is usually a non-optimal choice. If the complete set of data will fit comfortably in memory and there's a reasonable upper bound on the number of entries, then a pointer-array is one choice.
But first, avoid scanf %s and %[] formats without explicit lengths. Using your example buffer size of 1000, the maximum string length that you can read is 999, so:
/* Some needed data */
int n;
struct ptrarray_t
{
char **strings;
int nalloc; /* number of string pointers allocated */
int nused; /* number of string pointers used */
} pa_hdr; /* presume this was initialized previously */
...
n = fscanf(file, "%999[\n]", buffer);
if (n!=1 || getc(file)!='\n')
{
there's a problem
}
/* Now add a string to the array */
if (pa_hdr.nused < pa_hdr.nalloc)
{
int len = strlen(buffer);
char *cp = malloc(len+1);
strcpy(cp, buffer);
pa_hdr.strings[pa_hdr.nused++] = cp;
}
A reference to any string hereafter is just pa_hdr.strings[i], and a decent design will use function calls or macros to manage the header, which in turn will be in a header file and not inline. When you're done with the array, you'll need a delete function that will free all of those malloc()ed pointers.
If there are a large number of small strings, malloc() can be costly, both in time and space overhead. You might manage pools of strings in larger blocks that will live nicely with the memory allocation and paging of the host OS. Using a set of functions to effectively make an object out of this string-array will help your development. You can pick a simple strategy, as above, and optimize the implementation later.
I have got some data in a buffer and want to put those data in an array.
typedef struct chunk
{
char data[300]; /* the bufferr. */
} CHUNK;
char *buffer, CHUNK c [100];
Assuming I have got data into the buffer, how can I put 300 char per chunk? I'm new to C so please explain me with simple example.
Thanks,
Kevin
The declaration is invalid, but I think you mean:
typedef struct chunk
{
char data[300]; /* the bufferr. */
} CHUNK;
char *buffer;
CHUNK c [100];
If I understand your question correctly (which I'm far from certain that I do), the code would be something like:
int j = 0;
char *bp = buffer;
while (*bp)
{
strncpy (c [j] .data, bp, 300); // copy data into next item
bp += strlen (bp);
++ j;
}
In C, you can copy memory from one area to another using memcpy(). The prototype for memcpy() is:
void *memcpy(void *dst, const void *src, size_t n);
and the description is that it copies n bytes from src to dst, and returns dst.
So, to copy 300 bytes from b to a where both a and b point to something useful, b has at least 300 bytes of data, and a points to at least 300 bytes of space you can write to, you would do:
memcpy(a, b, 300);
Now your task should be something along the lines of:
typedef struct chunk
{
char data[300];
} CHUNK;
char *buffer;
CHUNK c[100];
size_t i;
/* make buffer point to useful data, and then: */
for (i=0; i < 300; ++i)
memcpy(c[i].data, buffer+i*300, 300);
You can use strncpy.
strncpy( data, buffer, 299 ) ;
Leaving the last index for the termination character '\0'. Or make the array size 301 and then use strncpy for 300 elements.