Can I free only a part of a string? - c

I am filling up a string of characters and I double its size from time to time.
When I finish, I would like to free unused memory.
void fun (char **str, size_t *len) {
size_t lsi; //last_significant_index
//filling up the str and reallocating from time to time.
//*len is storing the total size of allocated memory at this point
// idea #1
free((*str)[lsi + 1]);
// idea #2
for(size_t i = lsi + 1; i < *len; i++) {
free(&(*str)[i]);
}
}
None of these ideas seem to work however
Is it even possible to do it? If so, how?
Details:
I am using this function to reallocate my strings:
static void increase_list_size(char **list, size_t *list_len)
{
size_t new_list_size = (*list_len + 1) * 2; // I am not allocating my list at the declaration, so *list_len initially equals 0.
char *new_list = malloc(sizeof(char) * new_list_size);
for (size_t i = 0; i < *list_len; i++)
{
new_list[i] = (*list)[i];
}
if (list != NULL) // I don't want to free an empty list (it wasn't allocated at the declaration!
{
free(*list);
}
(*list) = new_list;
*list_len = new_list_size;
}
As you can see, I am allocating two-times more memory every time - that's why I wanted to free unused memory at the end.
I thought there was some kind of a tricky way to do it, since I felt that you can only use free() to free whole memory block.

No, you can only free() pointers that have been returned by malloc().
You want to use realloc() to change the allocated memory size to a smaller (as well as larger) size. The contents of the array will be preserved.
Example:
#include <stdlib.h>
int main() {
char *str = malloc(100);
...
str = realloc(str, 50);
...
free(str);
}
Remember to check the return value of realloc() (as well as the one of malloc()) to ensure that the (re)allocation has not failed.

You can only free a pointer that is the result of malloc or realloc. You can't reduce the size of an allocation by freeing at an arbitrary offset from it. But you can realloc it to a smaller size: realloc(*str, lsi).

one way is to create a new string and use only space required and copy the content to this one. now you can free the previous one.
I will use this is realloc() is not allowed (sometimes in homework)
the other way is realloc() as others suggested.

You can use standard C function realloc declared in header <stdlib.h>
For example
char *s = malloc( 100 );
strcpy( s, "Hello world" );
char *p = realloc( s, strlen( s ) + 1 );
if ( p != NULL ) s = p;
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
char *s = malloc( 100 );
strcpy( s, "Hello world" );
char *p = realloc( s, strlen( s ) + 1 );
if ( p != NULL ) s = p;
puts( s );
free( s );
return 0;
}
The program output is
Hello world
Or if you want to write a separate function then it can look the following way
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void resize( char **s, size_t n )
{
char *p = realloc( *s, n );
if ( p != NULL ) *s = p;
}
int main( void )
{
char *s = malloc( 100 );
strcpy( s, "Hello world" );
resize( &s, strlen( s ) + 1 );
puts( s );
free( s );
return 0;
}
Also you can use POSIX function strdup

Related

Manipulating a string and rewriting it by the function output

For some functions for string manipulation, I try to rewrite the function output onto the original string. I came up with the general scheme of
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *char_repeater(char *str, char ch)
{
int tmp_len = strlen(str) + 1; // initial size of tmp
char *tmp = (char *)malloc(tmp_len); // initial size of tmp
// the process is normally too complicated to calculate the final length here
int j = 0;
for (int i = 0; i < strlen(str); i++)
{
tmp[j] = str[i];
j++;
if (str[i] == ch)
{
tmp[j] = str[i];
j++;
}
if (j > tmp_len)
{
tmp_len *= 2; // growth factor
tmp = realloc(tmp, tmp_len);
}
}
tmp[j] = 0;
char *output = (char *)malloc(strlen(tmp) + 1);
// output matching the final string length
strncpy(output, tmp, strlen(tmp));
output[strlen(tmp)] = 0;
free(tmp); // Is it necessary?
return output;
}
int main()
{
char *str = "This is a test";
str = char_repeater(str, 'i');
puts(str);
free(str);
return 0;
}
Although it works on simple tests, I am not sure if I am on the right track.
Is this approach safe overall?
Of course, we do not re-write the string. We simply write new data (array of the characters) at the same pointer. If output is longer than str, it will rewrite the data previously written at str, but if output is shorter, the old data remains, and we would have a memory leak. How can we free(str) within the function before outputting to its pointer?
A pair of pointers can be used to iterate through the string.
When a matching character is found, increment the length.
Allocate output as needed.
Iterate through the string again and assign the characters.
This could be done in place if str was malloced in main.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *char_repeater(char *str, char ch)
{
int tmp_len = strlen(str) + 1; // initial size of tmp
char *find = str;
while ( *find) // not at terminating zero
{
if ( *find == ch) // match
{
tmp_len++; // add one
}
++find; // advance pointer
}
char *output = NULL;
if ( NULL == ( output = malloc(tmp_len)))
{
fprintf ( stderr, "malloc peoblem\n");
exit ( 1);
}
// output matching the final string length
char *store = output; // to advance through output
find = str; // reset pointer
while ( *find) // not at terminating zero
{
*store = *find; // assign
if ( *find == ch) // match
{
++store; // advance pointer
*store = ch; // assign
}
++store; // advance pointer
++find;
}
*store = 0; // terminate
return output;
}
int main()
{
char *str = "This is a test";
str = char_repeater(str, 'i');
puts(str);
free(str);
return 0;
}
For starters the function should be declared like
char * char_repeater( const char *s, char c );
because the function does not change the passed string.
Your function is unsafe and inefficient at least because there are many dynamic memory allocations. You need to check that each dynamic memory allocation was successful. Also there are called the function strlen also too ofhen.
Also this code snippet
tmp[j] = str[i];
j++;
if (str[i] == ch)
{
tmp[j] = str[i];
j++;
}
if (j > tmp_len)
//...
can invoke undefined behavior. Imagine that the source string contains only one letter 'i'. In this case the variable tmp_len is equal to 2. So temp[0] will be equal to 'i' and temp[1] also will be equal to 'i'. In this case j equal to 2 will not be greater than tmp_len. As a result this statement
tmp[j] = 0;
will write outside the allocated memory.
And it is a bad idea to reassign the pointer str
char *str = "This is a test";
str = char_repeater(str, 'i');
As for your question whether you need to free the dynamically allocated array tmp
free(tmp); // Is it necessary?
then of course you need to free it because you allocated a new array for the result string
char *output = (char *)malloc(strlen(tmp) + 1);
And as for your another question
but if output is shorter, the old data remains, and we would have a
memory leak. How can we free(str) within the function before
outputting to its pointer?
then it does not make a sense. The function creates a new character array dynamically that you need to free and the address of the allocated array is assigned to the pointer str in main that as I already mentioned is not a good idea.
You need at first count the length of the result array that will contain duplicated characters and after that allocate memory only one time.
Here is a demonstration program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * char_repeater( const char *s, char c )
{
size_t n = 0;
for ( const char *p = s; ( p = strchr( p, c ) ) != NULL; ++p )
{
++n;
}
char *result = malloc( strlen( s ) + 1 + n );
if ( result != NULL )
{
if ( n == 0 )
{
strcpy( result, s );
}
else
{
char *p = result;
do
{
*p++ = *s;
if (*s == c ) *p++ = c;
} while ( *s++ );
}
}
return result;
}
int main( void )
{
const char *s = "This is a test";
puts( s );
char *result = char_repeater( s, 'i' );
if ( result != NULL ) puts( result );
free( result );
}
The program output is
This is a test
Thiis iis a test
My kneejerk reaction is to dislike the design. But I have reasons.
First, realloc() is actually quite efficient. If you are just allocating a few extra bytes every loop, then chances are that the standard library implementation simply increases the internal bytecount value associated with your memory. Caveats are:
Interleaving memory management.Your function here doesn’t have any, but should you start calling other routines then keeping track of all that becomes an issue. Anything that calls other memory management routines can lead to the next problem:
Fragmented memory.If at any time the available block is too small for your new request, then a much more expensive operation to obtain more memory and copy everything over becomes an issue.
Algorithmic issues are:
Mixing memory management in increases the complexity of your code.
Every occurrence of c invokes a function call with potential to be expensive. You cannot control when it is expensive and when it is not.
Worst-case options (char_repeater( "aaaaaaaaaa", 'a' )) trigger worst-case potentialities.
My recommendation is to simply make two passes.
This passes several smell tests:
Algorithmic complexity is broken down into two simpler parts:
counting space required, and
allocating and copying.
Worst-case scenarios for allocation/reallocation are reduced to a single call to malloc().
Issues with very large strings are reduced:
You need at most space for 2 large strings (not 3, possibly repeated)
Page fault / cache boundary issues are similar (or the same) for both methods
Considering there are no real downsides to using a two-pass approach, I think that using a simpler algorithm is reasonable. Here’s code:
#include <stdio.h>
#include <stdlib.h>
char * char_repeater( const char * s, char c )
{
// FIRST PASS
// (1) count occurances of c in s
size_t number_of_c = 0;
const char * p = s;
while (*p) number_of_c += (*p++ == c);
// (2) get strlen s
size_t length_of_s = p - s;
// SECOND PASS
// (3) allocate space for the resulting string
char * dest = malloc( length_of_s + number_of_c + 1 );
// (4) copy s -> dest, duplicating every occurance of c
if (dest)
{
char * d = dest;
while (*s)
if ((*d++ = *s++) == c)
*d++ = c;
*d = '\0';
}
return dest;
}
int main(void)
{
char * s = char_repeater( "Hello world!", 'o' );
puts( s );
free( s );
return 0;
}
As always, know your data
Whether or not a two-pass approach actually is better than a realloc() approach depends on more factors than what is evident in a posting on the internet.
Nevertheless, I would wager that for general purpose strings that this is a better choice.
But, even if it isn’t, I would argue that a simpler algorithm, splitting tasks into trivial sub-tasks, is far easier to read and maintain. You should only start making tricky algorithms only if you have use-case profiling saying you need to spend more attention on it.
Without that, readability and maintainability trumps all other concerns.

I can't figure out how to use double pointers

I'm trying to use dynamic memory allocation but I can't figure out pointers.
I got the first part down.
void addtext(char **wordarray)
{
char word[N];
char endword[N] = "end";
int i=0;
int words=0;
while (scanf("%19s", word), strcmp(word,endword))
{
words++;
wordarray = realloc(wordarray, words*sizeof(char *));
wordarray[words-1] = malloc (N*sizeof(char));
strcpy(wordarray[words-1], word);
}
for (i=0; i<words; i++)
printf("%s\n", wordarray[i]);
return ;
}
But I'm having trouble when I try to call the same array in a different function.
void savetext(char **wordarray)
{
FILE *savedtext;
int i=0;
savedtext = fopen("Saved Text.txt","wt");
while(wordarray[i][0]!= '\0')
{
fputs(wordarray[i++],savedtext);
fputs(" ",savedtext);
}
return ;
}
My main function looks something like this:
int main (void)
{
char **wordarray;
addtext(wordarray);
savetext(wordarray);
return 0;
}
The second part of the code is obviously wrong, but I'm not sure how to exactly how to call those functions. My previous program didn't use any memory allocation so I didn't bother with pointers.I'm really new to c so any help would be appreciated.
Oh boy. Well, you have two big problems.
First, you never allocated the first wordarray. At the very least malloc it once:
char **wordarray = malloc(1);
Or even better, use malloc instead of realloc the first time (and initialize wordarray with 0!):
wordarray = wordarray ? realloc(wordarray, words * sizeof(char *))
: malloc(words * sizeof(char *));
Second, your addtext function is receiving a copy of this array, and doing stuff with it. Whatever the stuff is, it won't be saved in your wordarray outside, in main. What you need to do is pass a pointer to the array in your function, and edit the main object through that:
void addtext(char ***wordarray)
{
// ...
}
And lastly, you have some very big performance problems, allocating buffers so often. Use a proper growing vector implementation, or if you insist on writing your own at the very least grow it by doubling the size, or even better count the words and allocate the correct size.
Also your end string is arbitrarily allocated of length N, whatever that is. You don't need that, you already know the length. In fact the string is already in the read-only section of your binary, simply get a pointer to it:
const char *endword = "end";
Perhaps refactor your program to make the string creation its own function, and for symmetry, return storage of the string as its own function.
const int STRING_SIZE = 80;
void createString(char ** strPtr, int stringSize);
void freeString(char * strPtr);
int main(int argc, char ** argv) {
char * strValue = NULL;
createString(&strValue, STRING_SIZE);
// ... do stuff ...
freeString(strValue);
}
//
// end of main
//
void createString(char ** strPtr, int stringSize) {
//
// uses pass-by-reference to return *strPtr with allocated storage
//
*strPtr = (char *) calloc(stringSize, sizeof(char));
}
void freeString(char * strPtr) {
if(strPtr == NULL) return;
free(strPtr);
strPtr = NULL;
}
For starters the program has undefined behavior at least because the pointer wordarray was not initialized and has an indeterminate value
char **wordarray;
and this indeterminate value is used in a call of the function realloc in the function addtext
wordarray = realloc(wordarray, words*sizeof(char *));
Moreover the pointer is passed to the function addtext by value. That is the function deals with a copy of the value of the pointer. So changing the copy does not influence on the value stored in the original pointer. The original pointer in main will stay unchanged.
You need to pass the pointer by reference through a pointer to it.
Another problem of the function is that the number of stored strings will not be known outside the function addtext. You need at least append the array with a null pointer that will be used as a sentinel value.
Also this condition in the while loop within the function savetext
while(wordarray[i][0]!= '\0')
does not make a sense because within the function addtext you stop entering strings when the user will enter the string "end".
while (scanf("%19s", word), strcmp(word,endword))
^^^^^^^^^^^^^^^^^^^^
So it is not necessary that the preceding entered string is an empty string.
Here is a demonstrative program that shows how for example the function addtext can be declared and defined.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 20
size_t addtext( char ***wordarray )
{
char word[N];
const char *sentinel = "end";
size_t n = 0;
int success = 1;
while ( success && scanf( "%19s", word ) == 1 && strcmp( word, sentinel ) != 0 )
{
char **tmp = realloc( *wordarray, ( n + 1 ) * sizeof( char * ) );
success = tmp != NULL;
if ( success )
{
++n;
*wordarray = tmp;
( * wordarray )[n-1] = malloc( strlen( word ) + 1 );
if ( ( *wordarray )[n-1] ) strcpy( ( *wordarray )[n-1], word );
}
}
return n;
}
int main(void)
{
char **wordarray = NULL;
size_t n = addtext( &wordarray );
for ( size_t i = 0; i < n; i++ )
{
if ( wordarray[i] != NULL ) puts( wordarray[i] );
}
for ( size_t i = 0; i < n; i++ )
{
free( wordarray[i] );
}
free( wordarray );
return 0;
}
If to enter the following sequence of strings
one
two
three
end
then the program output will be
one
two
three
Correspondingly the declaration of the function savetext should be changed. There is not sense in this case to pass the pointer wordarray to the function by reference because the pointer itself is not changed within the function. Also you need to pass the number of elements in the allocated array, So the function declaration can look at least like
void savetext( char **wordarray, size_t n );

Free(): invalid pointer in C program

I am executing following C program and getting runtime error as "free(): Invalid Pointer"
#include<stdio.h>
#include<stdlib.h>
static void freeArgs(char** args);
int main()
{
char** argv = calloc(4, 10);
int argc = 0;
argv[argc++]="yogita";
argv[argc++] ="negi";
argv[argc] = NULL;
freeArgs(argv);
return 0;
}
static void freeArgs(char** args)
{
char** af = args;
for (; *af; af++)
free(*af);
free(args);
}
Can anyone suggest me the solution?
free(*af);
tries to free memory that was not allocated through malloc/calloc:
argv[argc++]="yogita";
"yogita" is a string literal, thus not dynamically allocated. You can't free its memory.
This call
char** argv = calloc(4, 10);
(Note:it seems you mean
char** argv = calloc( 4, sizeof( char * ) );
end note)
with the magic number 10 allocates dynamically only one extent of memory of the size 4 * 10 that is equal to 40. So you need to call the function free only one time for the allocated extent. That is how many times malloc or calloc was called the same number of times free should be called.
I suspect that you meant something like the following
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void freeArgs( char **args )
{
char **af = args;
while ( *af ) free( *af++ );
free( args );
}
int main(void)
{
enum { N = 4, LEN = 10 };
char **argv = calloc( N, sizeof( char * ) );
size_t argc = 0;
argv[argc] = malloc( LEN * sizeof( char ) );
strcpy( argv[argc++], "yogita" );
argv[argc] = malloc( LEN * sizeof( char ) );
strcpy( argv[argc++], "negi" );
freeArgs( argv );
return 0;
}

wrong redimension of a string in c

I am trying to make a function that receives a dynamic string and removes from it all occurrences of the character also passed as a parameter.
The string should finally contain just enough space to contain characters not deleted
void delete(char *cad, char c){
int i, cont = 0;
char *aux = NULL;
i = 0;
while(cad[i] != '\0'){
if(cad[i] != c){
aux = (char*)realloc(aux, sizeof(char) * cont + 1);
aux[cont] = cad[i];
cont++;
}
i++;
}
cad = (char*)realloc(cad, sizeof(char) * cont);
i = 0;
while(aux[i] != '\0'){
cad[i] = aux[i];
i++;
}
}
Now I have a segmentation fault
You do not check the result of the realloc.
IMO it will be better to return the pointer to the new string instead of using double pointer. Double pointer may cause hard to track memory leaks, and function will not work with the const strings - for example string literals
You do not null character terminate the string.
In this example, I did not change your allocation algorithm but in real life more efficient will be first to count how much memory you need to allocate, allocate it and then process the string again:
char *delete(const char *cad, char c){
size_t nchars = 0;
char *aux = NULL;
char *temp;
while(*cad)
{
if(*cad != c)
{
temp = realloc(aux, sizeof(*temp) * nchars + 1);
if(temp)
{
aux = temp;
aux[nchars++] = *cad;
}
else
{
/* handle allocation error */
free(aux);
aux = NULL;
break;
}
}
cad++;
}
if(aux) aux[nchars] = 0;
return aux;
}
Some minor changes: use objects instead of types in sizeof and do not cast result of malloc. You can also add NULL pointer parameter check.
Every time you are reallocing inside the while loop, you are essentially giving the variable aux a new address each time.
I advise you to not do that and allocate the memory you want to allocate at the start of the function.
You will need to calculate how much memory you would need before allocating the memory. That is, count how much element you would delete.
If you want me to further elucidate or add a code fragment, please feel free to ask it in the comments.
Instead of many calls to realloc() I would just perform an in-place substitution of the characters; this substitution leaves unused allocated characters at the end of the string and is illustrated by the delete_no_realloc() function below.
If you want to get rid of these unused ending characters in the allocated string, then only one call to realloc() is needed as illustrated by the delete() function below.
Note that when a function uses realloc() on a parameter which is a pointer, it must obtain the address of this pointer to adjust it with the result of realloc().
/**
gcc -std=c99 -o prog_c prog_c.c \
-pedantic -Wall -Wextra -Wconversion \
-Wwrite-strings -Wold-style-definition -Wvla \
-g -O0 -UNDEBUG -fsanitize=address,undefined
**/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
size_t // new length
delete_no_realloc(char *cad,
char c)
{
size_t w=0;
for(size_t r=0; cad[r]; ++r)
{
char ch=cad[r];
if(ch!=c)
{
cad[w++]=ch; // store and advance write index
}
}
cad[w]='\0'; // ensure string termination
return w;
}
void
delete(char **cad_ptr,
char c)
{
char *cad=*cad_ptr; // forget this embarrassing indirection
size_t new_length=delete_no_realloc(cad, c);
cad=realloc(cad, new_length+1);
if(cad==NULL)
{
abort();
}
*cad_ptr=cad; // don't forget to adjust the string
}
int
main(void)
{
const char *msg="this is a message";
char *cad=malloc(strlen(msg)+1);
if(cad==NULL)
{
abort();
}
strcpy(cad, msg);
printf("before: <%s>\n", cad);
delete(&cad, 's'); // pass the address of the string
printf("after: <%s>\n", cad);
free(cad);
return 0;
}
You can simplify your delete() function by simply using a read and write index within the original string, removing all c characters found, and then make a single call to realloc() to reallocate storage to exactly fit the remaining characters.
You can do something like:
void delete (char **cad, char c)
{
if (!*cad || !**cad) /* check if cad is NULL or empty-string */
return;
size_t write = 0; /* write index */
for (size_t read = 0; (*cad)[read]; read++) { /* loop over each char in cad */
if ((*cad)[read] != c) /* if char not c */
(*cad)[write++] = (*cad)[read]; /* copy incrementing write */
}
(*cad)[write] = 0; /* nul-terminate */
void *tmp = realloc (*cad, write + 1); /* realloc to exact size */
if (!tmp) { /* validate realloc */
perror ("realloc-cad");
return;
}
*cad = tmp; /* assign reallocated block to *cad */
}
A full example would be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void delete (char **cad, char c)
{
if (!*cad || !**cad) /* check if cad is NULL or empty-string */
return;
size_t write = 0; /* write index */
for (size_t read = 0; (*cad)[read]; read++) { /* loop over each char in cad */
if ((*cad)[read] != c) /* if char not c */
(*cad)[write++] = (*cad)[read]; /* copy incrementing write */
}
(*cad)[write] = 0; /* nul-terminate */
void *tmp = realloc (*cad, write + 1); /* realloc to exact size */
if (!tmp) { /* validate realloc */
perror ("realloc-cad");
return;
}
*cad = tmp; /* assign reallocated block to *cad */
}
int main (int argc, char **argv) {
if (argc < 3) {
fputs ("usage: ./prog \"string with c\" c\n", stderr);
return 1;
}
size_t len = strlen (argv[1]);
char *s = malloc (len + 1);
if (!s) {
perror ("malloc-s");
return 1;
}
memcpy (s, argv[1], len + 1);
printf ("%s (%zu chars)\n", s, len);
delete (&s, *argv[2]);
printf ("%s (%zu chars)\n", s, strlen(s));
free (s);
}
Example Use/Output
$ ./bin/delete_c_realloc "nmyn ndogn nhasnn nnfleasnnn" n
nmyn ndogn nhasnn nnfleasnnn (28 chars)
my dog has fleas (16 chars)
Look things over and let me know if you have questions.
There are four main problems with your function implementation.
The first one is that the function accepts the pointer to the source string by value. That is the parameter cad is initialized by the value of the pointer used as an argument. As a result changing the variable cad does not influence on the original pointer.
The second one is that you are not checking whether a call of realloc was successful. As a result the function can invoke undefined behavior.
The third one is that it is inefficient to reallocate the string each time when a new character is appended.
And at last the fourth one is that the result dynamically allocated array does not contain a string because you forgot to append the terminating zero character '\0'.
If you want to change within the function a value of the original pointer you should either to return from the function the result pointer obtained in the function and assign it to the original pointer in the caller. Or you should pass the original pointer to the function by reference. In C passing by reference means passing an object (that can be a pointer) indirectly through a pointer to it.
Here is a demonstrative program that shows the function implementation when the original pointer is accepted by the function by reference.
The function also returns a pointer to the result string that can be checked in the caller whether the reallocation of dynamic memory within the function was successful.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * remove_char( char **s, char c )
{
char * result = *s;
if ( c != '\0' )
{
char *dsn = *s;
const char *src = *s;
do
{
if ( *src != c )
{
if ( dsn != src )
{
*dsn = *src;
}
++dsn;
}
} while ( *src++ );
char *tmp = realloc( *s, ( dsn - *s ) * sizeof( char ) );
if( tmp != NULL ) *s = tmp;
result = tmp;
}
return result;
}
int main(void)
{
char *s = malloc( 12 );
strcpy( s, "H#e#l#l#o!" );
puts( s );
if ( remove_char( &s, '#' ) ) puts( s );
free( s );
return 0;
}
The program output is
H#e#l#l#o!
Hello!
Another approach is to write a function that does not change the source string but creates dynamically a new string that contains the source string excluding the specified character. Such a function is more flexible because you can call it with string literals. If the source string also was dynamically allocated then the caller of the function after a successful call it can just free the source string.
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * remove_copy( const char *s, char c )
{
size_t src_len = strlen( s );
size_t dsn_len = src_len;
if ( c != '\0' )
{
for ( const char *p = s; ( p = strchr( p, c ) ) != NULL; ++p )
{
--dsn_len;
}
}
char *result = malloc( ( dsn_len + 1 ) * sizeof( char ) );
if ( result != NULL )
{
const char *src_s = s;
char *dsn_s = result;
if ( dsn_len != src_len )
{
for ( const char *p = src_s;
( p = strchr( src_s, c ) ) != NULL;
src_s = p + 1 )
{
if ( p - src_s != 0 )
{
memcpy( dsn_s, src_s, p - src_s );
dsn_s += p - src_s;
}
}
}
strcpy( dsn_s, src_s );
}
return result;
}
int main(void)
{
char s[] = "H#e#l#l#o!";
puts( s );
char *p = remove_copy( s, '#' );
if ( p != NULL ) puts( p );
free( p );
return 0;
}
The program output is the same as shown for the preceding demonstrative program that is
H#e#l#l#o!
Hello!

C Increase char array of char array size

I have a char array of char array like so:
char my_test[2][10];
As you can see I have a length of 2 and then 10. If I need to increase the first char array (2), how can this be done dynamically?
For example, half way through my application char[2] might be in use so therefore I need to use position 3 in the char array. I would then end up with this:
char store[3][10];
But keeping the data originally store in:
char store[0][10];
char store[1][10];
char store[2][10];
You should dynamically allocate memory for the array using standard C functions malloc and realloc declared in header <stdlib.h>.
Here is a demonstrative program that shows how the memory can be allocated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10
int main(void)
{
size_t n = 2;
char ( *my_test )[N] = malloc( n * sizeof( char[N] ) );
strcpy( my_test[0], "first" );
strcpy( my_test[1], "second" );
for ( size_t i = 0; i < n; i++ ) puts( my_test[i] );
putchar( '\n' );
char ( *tmp )[N] = realloc( my_test, ( n + 1 ) * sizeof( char[N] ) );
if ( tmp != NULL )
{
my_test = tmp;
strcpy( my_test[n++], "third" );
}
for ( size_t i = 0; i < n; i++ ) puts( my_test[i] );
free( my_test );
return 0;
}
The program output is
first
second
first
second
third
char my_test[2][10];
is compile-time constant, which means that the required memory to use that array is carved to the stone already before your application starts. So you will never be able to change it's size.
You'll have to use DYNAMIC allocation. Check for something called malloc and free in case you are really working with C, or with C++ new and delete are what you need. You'll also need to learn about pointers.

Resources