If I create one array of character pointers of some size like:
char* temp[10];
//need intialisation here..
temp[0] = "BLAH";
temp[1] = "BLAH";
temp[3] = "BLAH";
.
.
.
temp[9] = "BLAH";
//Need reinitialise..
temp[10] = "BLAH";
temp[11] = "BLAH";
How do I initialise it?
How to re-initialise it with size 20 after some time?
Are malloc() and calloc() useful to do this? If yes then how to use with array of pointers to character?
[EDITED]
My code and requirement,
Basically i want read file in c but without wasting single character...
Here are the code to read data from text file,
FILE *ptr_file;
/* Allocate space for ten strings */
/* Allocate space for ten strings */
char** list = (char **)malloc(10 * sizeof(char));
/* Reallocate so there's now space for 20 strings */
/* And initialize the new entries */
ptr_file =fopen(LogFileCharName,"rb");
if (!ptr_file)
return 1;
int __index = 0;
wchar_t CurrentString[1000];
while(fgetws (CurrentString , 1000 , ptr_file) != NULL)
{
char* errorDes;
errorDes = new char[1000];
wcstombs(errorDes, CurrentString, 1000);
list[__index] = errorDes;
if( __index>10)
{
(char**)realloc(list, 20 * sizeof(char *));
}
__index++;
}
now when size exceeded 10 then in just need to resize that are.
for this i am using win32 console application type of microsoft visual studio.
You don't use arrays, but pointers and allocate on the heap, and then reallocate when needed:
/* Allocate space for ten strings */
char **temp = malloc(10 * sizeof(char *));
temp[0] = "Hello 1";
/* ... */
temp[9] = "Hello 10";
/* Reallocate so there's now space for 20 strings */
temp = realloc(temp, 20 * sizeof(char *));
/* And initialize the new entries */
temp[10] = "Hello 11";
As for initialization, it depends on what the contents of the strings are. Either you make it point to an already existing string (either string literals like in my example above, or other strings), or you allocate space for the strings on the heap as well.
Maybe something like this:
for (int i = 0; i < 10; i++)
{
char temp_string[10];
/* Create strings in the form "Hello 1" to "Hello 10" */
sprintf(temp_string, "Hello %d", i + 1);
/* Duplicate the temporary string */
temp[i] = strdup(temp_string);
}
Note: If you use e.g. strdup or malloc/calloc to allocate the actual strings, you of course have to free them as well.
After your updated question, I see a couple of problems with your code:
The first is that when do the check __index>10 then you're already two indexes out of bounds for the array. The check should be __index==9.
Doing the change above will also solve your other problem, that you will continuously reallocate once the index goes to 11 or higher.
Since you use new for the actual strings in the array, you have to use delete when freeing the actual strings.
Since you use new, you are using C++, for which there are much better facilities to handle things like this:
// Declare and open file
wifstream ifs(LogFileCharName);
std::vector<std::string> list;
std::wstring CurrentString;
while (std::getline(ifs, CurrentString))
{
// Get the needed length of the destination string
size_t length = wcstombs(nullptr, CurrentString.c_str(), 0);
char* tmp = new char[length + 1];
// Do the actual conversion
wcstombs(tmp, CurrentString.c_str(), length + 1);
// Add to list
list.emplace_back(tmp);
delete [] tmp;
}
Related
So I'm trying to make a char**, I fully understand how it works in the background and all that stuff but I don't seem to understand how to write the code for it. I want to make a pointer to an array of chars which has a name in it. I need help with storing a string in it (using strcpy() ) and print it after that.
char** name = (char**)malloc((strlen("MyName") + 1) * sizeof(char*));
strcpy(name, "MyName"); // I get an error right here
If you really want a pointer to an char array, you could do the following:
char** name = (char**)malloc(sizeof(char*)); //initialize the pointer
*name = (char*)malloc((strlen("MyName") + 1) * sizeof(char)); //initialize the array
strcpy(*name, "MyName");
So I'm trying to make a char**, I fully understand how it works in the
background and all that stuff but I don't seem to understand how to
write the code for it.
Umm... No, not quite.
To declare a pointer-to-char, you simply decalre:
char *name = malloc (strlen("MyName") + 1);
Why? When you make your call to malloc, malloc allocates a block of memory providing strlen("MyName") + 1 bytes and returns the starting address to that block of memory -- which you assign to name. You then can copy "MyName" to name (with 1-byte remaining for the nul-terminating character). The approach would be:
size_t len = strlen ("MyName");
char *name = malloc (len + 1); /* allocate len + 1 bytes */
if (name == NULL) { /* validate EVERY allocation */
perror ("malloc-name");
/* handle error by returning or exiting */
}
memcpy (name, "MyName", len + 1); /* no need to scan again for \0 */
/* do something with name - here */
free (name); /* don't forget to free name when you are done */
What then does char** do?
When you are dealing with a pointer-to-pointer-to-char, you must first allocate for some number of pointers, then you can allocate and assign a block of memory to each of the pointers and use each pointer just as you have used name above.
For example:
/* array of ponters to string-literals for your source of strings */
char *band[] = { "George", "Ringo", "Paul", "John" };
char **names;
size_t nmembers = sizeof band / sizeof *band;
/* allocate nmembers pointers */
names = malloc (nmembers * sizeof *names);
if (names == NULL) { /* validate EVERY allocation */
perror ("malloc-name_pointers");
/* handle error by returning or exiting */
}
/* now loop allocating for each name and copy */
for (size_t i = 0; i < nmembers; i++) {
size_t len = strlen (band[i]); /* get length */
names[i] = malloc (len + 1); /* allocate */
if (names[i] == NULL) { /* validate EVERY allocation */
perror ("malloc-names[i]");
/* handle error by returning or exiting */
}
memcpy (names[i], band[i], len + 1);/* no need to scan again for \0 */
}
/* output each */
for (size_t i = 0; i < nmembers; i++)
printf ("member[%zu]: %s\n", i + 1, names[i]);
Freeing names is a two step process. You must free the memory allocated to each of the names pointers and then free the pointers themselves, e.g.
for (size_t i = 0; i < nmembers; i++)
free (names[i]); /* free each allocated names[i] */
free (names); /* free pointers */
Now hopefully you more closely "... fully understand how it works". Let me know if you have any questions.
First thing you should understand is that declaring a variable as a single pointer or a double pointer (or any other n pointer) doesn't actually tell whether the underlying variable holds a single value or an array of values.
Single pointer points to a memory address on which actual value is stored. Double pointer points to a memory address on which single pointer is stored, and so on.
Now, to make a pointer to an array of char pointers you can use a single char pointer (char*) but I recommend to use double char pointer (char**) for maintainability purposes.
Consider the following code:
char** names = (char**)malloc(100 * sizeof(char*));
It will allocate memory space for 100 char pointers (char*) on heap and return you a double pointer (char**) to the first single pointer (char*) in that memory space. This means you will be able to save 100 char pointers (or 100 names in your case) inside that memory space. Then you can use them like this:
char* name0 = "First Name"; // Saved on stack
char* name1 = malloc((strlen("Second Name") + 1) * sizeof(char)); // Saved on heap
strcpy(name1, "Second Name");
names[0] = name0;
names[1] = name1;
Also, please note that when saving a string on heap you need to add one more place for null character (manually).
I have to make a function which replaces each word (x), with another word(y), in a given text(**string). Can I replace them directly in the given text? Or should I make a new array and make the replacements there? However and don't know how to continue.
The code I wrote is:
void operation_2(char x[100], char y[100], char **string, int N)
{
int len = 0;
char *word;
char s[12] = " .,?!\"';:";
char **newstring = (char **)malloc(N * sizeof(char *));
for (i = 0; i<= N; i++) {
word = strtok(string[i], s);
while (word != NULL) {
if (strcmp(word, x) == 0) {
len = strlen(string[i]) - strlen(x) + strlen(y);
newstring[i] = (char *)malloc((len + 1) * sizeof(char));
If you create a new string, it'll be able to take any string (string literal, an array on the stack, a static array, an array on the heap) as input, but it won't be as memory efficient.
If you want maximum memory efficiency, then you can modify the target string in-place, but you'll have restrictions depending on where the input string is stored.
string literal or possibly a const static array: you can't do anything do anything with it
stack, or static: you can shrink it
heap: you can realloc it (shrink it or expand it)
The memmove function might come in handy if you decide to modify the string in place.
Keep in mind however, that:
There's no such thing as array arguments in C. They always decay to pointers.
strtok will modify it's input, so you'd need to make at least one copy if you decide to go with strtok
I am trying to allocate memory for an array of C strings. I can guarantee that the strings fit within MAX_STRING_LENGTH characters, but I don't know at compile time how many strings will be in the array (this is computed dynamically). When I use the code...
char *strings[MAX_STRING_LENGTH] = malloc( sizeof(char *) * numstrings );
...the compiler complains that this is an invalid initializer. When I use the code...
char strings[MAX_STRING_LENGTH][] = malloc( sizeof(char *) * numstrings );
...the compiler complains about an incomplete element type. What am I doing wrong here, and how can I allocate memory for this array?
char (*strings)[MAX_STRING_LENGTH] = malloc(sizeof *strings * num_strings);
will allocate a num_strings x MAX_STRING_LENGTH array of char as a contiguous chunk so that you don't have to do multiple levels of allocation.
strcpy(strings[i], "This is a test");
printf("%s\n", strings[j]);
etc. When you're done you only have to free(strings);.
The main drawbacks with this method are that you may not have enough memory to satisfy the request if num_strings is very large, and that you'll have some internal fragmentation if most of your strings are shorter than MAX_STRING_LENGTH.
With this declaration:
char *strings[MAX_STRING_LENGTH] = malloc(sizeof(char *) * numstrings);
It reads as if you're defining an array of C strings, whose count - not the individual string lengths - is MAX_STRING_LENGTH.
Better to define a **char, like so:
char **strings = malloc(sizeof(char *) * numstrings);
Later in your code, when you're ready to add a string to e.g. slot 5:
strings[5] = malloc(sizeof(char) * MAX_STRING_LENGTH));
or in an init loop such as:
for (i = 0; i < numstrings; i++)
strings[i] = malloc(sizeof(char) * MAX_STRING_LENGTH);
And, if at some point you need room for more strings, use realloc to grow the initial memory allocation.
char **strings;
strings=(char **) malloc(number of strings);
strings[i]=(char *) malloc(MAX_STRING_LENGTH);
If it is truly dynamic, then it may need to be something like this:
char **strings = malloc( sizeof(char*) * numstrings );
for ( int i = 0; i < numstrings; i++ )
strings[i] = malloc( MAX_STRING_LENGTH );
It is also possible to allocate it all in one chunk (makes freeing it easier) and then assign the individual pointers in the array to computed positions in the allocated buffer. That, though, adds some complexity that may not exceed the benefit.
I receive a char * buffer which have the lenght of 10.
But I want to concat the whole content in my struct which have an variable char *.
typedef struct{
char *buffer;
//..
}file_entry;
file_entry real[128];
int fs_write(char *buffer, int size, int file) {
//every time this function is called buffer have 10 of lenght only
// I want to concat the whole text in my char* in my struct
}
Something like this :
real[i].buffer += buffer;
How can I do this in C ?
In general, do the following (adjust and add error checking as you see fit)
// real[i].buffer += buffer;
// Determine new size
int newSize = strlen(real[i].buffer) + strlen(buffer) + 1;
// Allocate new buffer
char * newBuffer = (char *)malloc(newSize);
// do the copy and concat
strcpy(newBuffer,real[i].buffer);
strcat(newBuffer,buffer); // or strncat
// release old buffer
free(real[i].buffer);
// store new pointer
real[i].buffer = newBuffer;
You can use strcat(3) to concatenate strings. Make sure you have allocated enough space at the destination!
Note that just calling strcat() a bunch of times will result in a Schlemiel the Painter's algorithm. Keeping track of the total length in your structure (or elsewhere, if you prefer) will help you out with that.
I am not clear. Do you want:
to concatenate every one of the 10 character buffers you receive into one array, pointed at by one real[0].buffer, or
do you want each 10 character buffer to be pointed at by a different real[i].buffer, or
something else?
You will need to allocate enough space for the copy of the buffer:
#include <stdlib.h>
//...
int size = 10+1; // need to allocate enough space for a terminating '\0'
char* buff = (char *)malloc(size);
if (buff == NULL) {
fprintf(stderr, "Error: Failed to allocate %d bytes in file: %s, line %d\n",
size, __FILE__, __LINE__ );
exit(1);
}
buff[0] = '\0'; // terminate the string so that strcat can work, if needed
//...
real[i].buffer = buff; // now buffer points at some space
//...
strncpy(real[i].buffer, buffer, size-1);
I've never used malloc to store more than values but I have to use strdup to order the lines of an input file and I dont get a way to make it work.
I though using strdup() to get a pointer to each line and later, put each one into a space according to the number of lines reserved with malloc().
I dont know if I have to do it like reserved memory was an array to pointers, I mean using char** and later put each pointer to each strdup into reserved space.
I though something like this:
char **buffer;
char *pointertostring;
char *line; // line got using fgets
*buffer = (char*)malloc(sizeof(char*));
pointertostring = strdup(line);
I don't know what to do after that, I don't even know if this is correct, in that case, what should I do to store the pointer to the string in a position of buffer?
Regards
If I understand your requirement correctly. You'll have to do something like:
char **buffer;
char line[MAX_LINE_LEN]; // line got using fgets
int count; // to keep track of line number.
// allocate one char pointer for each line in the file.
buffer = (char**)malloc(sizeof(char*) * MAX_LINES);
count = 0; // initilize count.
// iterate till there are lines in the file...read the line using fgets.
while(fgets(line,MAX_LINE_LEN,stdin)) {
// copy the line using strdup and make the buffer pointer number 'count'
// point to it
buffer[count++] = strdup(line);
}
....
....
// once done using the memory you need to free it.
for(count=0;count<MAX_LINES;count++) {
free(buffer[count]);
}
....
....
Your buffer will only hold one pointer. You need something like:
char **buffer;
char *pString;
int linecount;
buffer = (char **)malloc(sizeof(char *)*MAXIMUM_LINES);
linecount = 0;
while (linecount < MAXIMUM_LINES) {
pString = fgets(...);
buffer[linecount++] = strdup(pString);
}