I want to write a computer programme that will do the following things :
1a. It will make an array 3 characters long.
£££
2a. It will then initialize the array with the string "{_}" and will call the array zero.
0 = {_}
[The array is called 0 because it has 1 _ stick and because 2^0 = 1.]
1b. It will then ask the user to press Enter.
' '
2b. Once the user presses Enter it will lengthen the array such that its new length is one plus two times the previous length.
{_}££££
3b. It will then change the last '}' character into ',' .
{_,££££
4b. Make a side by side copy of the previous array.
{,{}£
5b. Put a '}' at the end of the array and call it one.
1 = {,{}}
[The array is called 1 because it has 2 _ sticks and because 2^1 = 2.]
It it then repeat the same process as in b so that the end result is -
5c.
2 = {,{},{,{}}}
[The array is called 2 because it has 4 _ sticks and because 2^2 = 4.]
So, this is my algorithm. I will produce the end results of a couple more iterations -
3 = {,{},{,{}},{,{},{,{}}}}
4 = {,{},{,{}},{,{},{,{}}},{,{},{,{}},{,{},{,{}}}}}
5= {,{},{,{}},{,{},{,{}}},{,{},{,{}},{,{},{,{}}}},{,{},{,{}},{,{},{,{}}},{,{},{,{}},{,{},{,{}}}}}}
And so on.
I wrote the following in order to get the aforementioned job done -
#include <stdio.h>
#include <stdlib.h>
void print_vno ( int * pv_number , int * pv_length , char * pv_vno ) {
printf ( "%d =\n" , *pv_number ) ;
for ( int i = 0 ; i < *pv_length ; i++ )
{ printf ( "%c" , *( pv_vno + i ) ) ; }
printf ( "\n" ) ;
}
void generate_vno ( int * gv_number , int * gv_length , char * gv_vno ) {
*gv_number = *gv_number + 1 ;
int old_length = *gv_length ;
*gv_length = 2 * ( *gv_length ) + 1 ;
gv_vno = realloc ( gv_vno , *gv_length ) ;
for ( int i = 0 ; i < old_length ; i++ )
{ *( gv_vno + i + old_length ) = *( gv_vno + i ) ; }
*( gv_vno + old_length - 1 ) = ',' ;
*( gv_vno + *gv_length - 1 ) = '}' ;
print_vno ( gv_number , gv_length , gv_vno ) ;
}
int main ( ) {
int number = 0 , length = 3 ;
char * vno = malloc ( length ) , zero [] = "{_}" ;
for ( int i = 0 ; i < length ; i++ )
{ *( vno + i ) = zero [i] ; }
print_vno ( &number , &length , vno ) ;
start :
printf ( "\nPress Enter for successive Von Neumann Ordinals, " ) ;
printf ( "or press X then Enter to exit.\n" ) ;
char enter ;
scanf ( "%c" , &enter ) ;
if ( enter != 'x' )
{ generate_vno ( &number , &length , vno ) ;
goto start ; }
free ( vno ) ;
return 0 ; }
The problem I am having is as follows -
If I run the code here, it counts up to 10 then crashes and gives this error message- "** Process exited due to resource limitations **".
If I run the code here, it counts up to 4 then crashes and gives this error message- "free(): double free detected in tcache 2 Aborted".
I suspect there is something wrong with the usage of malloc, realloc and free.
My question is- how can I make it count up to 20?
Thank you.
realloc
but you don't save the new pointer so that it's visible outside generate_vno
. If realloc
reallocates the data, the original pointer will have been free'd but you use the same pointer in all calls so you get undefined behavior. You need to send in a char**
to generate_vno
in order for the function to be able to store the new pointer.scanf
.*(x + y)
instead of the idiomatic x[y]
.goto
where a loop would work fine.X
to quit, but only a lowercase x
is actually working.#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// no pointers unless needed:
void print_vno(int pv_number, int pv_length, const char *pv_vno) {
printf("%d =\n", pv_number);
for (int i = 0; i < pv_length; i++) {
putchar(pv_vno[i]); // pv_vno[i] instead of *(pv_vno + i)
}
putchar('\n');
}
// `gv_vno` is now a `char**`:
void generate_vno(int *gv_number, int *gv_length, char **gv_vno) {
*gv_number = *gv_number + 1;
int old_length = *gv_length;
*gv_length = 2 * (*gv_length) + 1;
char *new_nvo = realloc(*gv_vno, *gv_length);
if (new_nvo == NULL) { // check if realloc succeeded
perror("malloc");
free(*gv_vno);
exit(1);
}
*gv_vno = new_nvo; // save the new pointer
for (int i = 0; i < old_length; i++) {
new_nvo[i + old_length] = new_nvo[i];
}
new_nvo[old_length - 1] = ',';
new_nvo[*gv_length - 1] = '}';
print_vno(*gv_number, *gv_length, new_nvo);
}
int main() {
int length = 3;
int number = 0;
char zero[] = "{_}";
char *vno = malloc(length);
if (vno == NULL) return 1;
memcpy(vno, zero, length);
print_vno(number, length, vno);
for (;;) { // loop instead of a label and goto:
printf("\nPress Enter for successive Von Neumann Ordinals, ");
printf("or press X then Enter to exit.\n");
char enter;
// check that scanf succeeds and allow both `x` and `X` to quit:
if (scanf("%c", &enter) != 1 || tolower((unsigned char)enter) == 'x')
break;
generate_vno(&number, &length, &vno);
}
free(vno);
}