Converting Static 2D Array to Dynamic Array in C - arrays

We were asked to convert 2D static array to dynamic array. So I will need to create an array of pointers in which every pointer points to a different row. I have written this code but my code breaks when i=1 on line *(dynamicStr[i] + v) = rowStr[v]; Additionally, if I enable free(ptr); section my debugger gets stuck there for 6 or 7 times and then contiunes.
EDIT: In the end, I solved the problem with appying the answers #dodooft and #Viktor Terziev gave.
#include <stdio.h>
#include <stdlib.h>
void toDynamic(int x,int y, char toDyna[x][y]);
void toDynamic2(int x,int y, char toDyna[x][y]);
int main()
{
char toDyna[7][12] = {
"JOHN",
"MARK",
"PIERCEPIERCE",
"20",
"ROSIE",
"ALEX",
"MARLYN"
};
int x = 7;
int y = 12;
toDynamic2(x, y, toDyna);
return 0;
}
void toDynamic2(int x,int y, char toDyna[x][y]){
char *dynamicStr[x];
int rowToCheck = 0;
int size;
char *ptr;
int c;
for(int i = 0; i < x; i++){
printf("i: %d\n",i);
c = 0;
size = strlen(toDyna[rowToCheck]);
ptr = (char*) malloc(size * sizeof(char));
for(int j = 0; j < y; j++){
if(toDyna[i][j] != '\0'){
*(ptr+c) = toDyna[i][j];
c++;
} else{
break;
}
}
*(ptr+size) = '\0';
printf(" ");
char rowStr[size];
for(int v = 0; v < size; v++){
rowStr[v] = *(ptr+v);
printf("Added Char: %c\n", rowStr[v]);
*(dynamicStr[i] + v) = rowStr[v];
}
//free(ptr);
//printf("\n%s\n", rowStr);
//dynamicStr[i] = &rowStr;
rowToCheck++;
}
for(int i = 0; i < x; i++){
printf("%s\n", dynamicStr[i]);
}
}
EDIT: This is the working verion of the code:
#include <stdio.h>
#include <stdlib.h>
char** toDynamic(int x,int y, char toDyna[x][y]);
void free2DArray(int x, char **dynamicStr);
int main()
{
char toDyna[7][12] = {
"JOHN",
"MARK",
"PIERCEPIERCE",
"20",
"ROSIE",
"ALEX",
"MARLYN"
};
int x = 7;
int y = 12;
char **dynamicArr;
dynamicArr = toDynamic(x, y, toDyna);
free2DArray(x, dynamicArr);
return 0;
}
char** toDynamic(int x,int y, char toDyna[x][y]){
printf("Q2\n");
char **dynamicStr;
int rowToCheck = 0;
int size;
int c;
dynamicStr = (char*)malloc(x * sizeof(char*));
for(int i = 0; i < x; i++){
dynamicStr[i] = (char*)malloc(y * sizeof(char));
c = 0;
size = strlen(toDyna[rowToCheck]);
char *ptr = (char*) malloc((size + 1) * sizeof(char));
for(int j = 0; j < y; j++){
if(toDyna[i][j] != '\0'){
*(ptr+c) = toDyna[i][j];
c++;
} else{
break;
}
}
*(ptr+size) = '\0';
dynamicStr[i] = ptr;
rowToCheck++;
}
for(int i = 0; i < x; i++){
printf("%s\n", dynamicStr[i]);
}
printf("----------------------------\n");
return dynamicStr;
}
void free2DArray(int x, char **dynamicStr){
printf("Q3\n");
for(int i = 0; i < x; i++){
free(dynamicStr[i]);
printf("dynamicStr %d freed\n", i);
}
free(dynamicStr);
printf("dynamicStr array freed\n");
printf("----------------------------\n");
}

You define dynamicStr as an array of char pointers, when you are trying to assign a value to it with *(dynamicStr[i] + v) = rowStr[v]; you are basically copying the value of rowStr[v] to the address that is pointed by dynamicStr[i] + v. That address is not defined in your code, so you got a segfault.
If you are trying to fill dynamicStr with pointers to new arrays with dynamic memory, you should try something like
dynamicStr[i] = ptr;
where ptr is the pointer returned by the malloc call to the i-th row. Also, as you are working with strings you can use strcpy to copy the data from the static array to the dynamic one.

Its much easier than you think, please refer to strcpy documentation and strlen documentation, and (if you use my code) don't forget to free your memory.
char * * toDynamic2(size_t n, size_t m, char strings[n][m])
{
char * * arr = malloc(n * sizeof(char*));
for(size_t i = 0; i < n; ++i)
{
size_t size = strlen(strings[i]);
arr[i] = malloc((size + 1) * sizeof(char));
strcpy(arr[i], strings[i]);
}
for(size_t i = 0; i < n; ++i)
{
printf("%s\n", arr[i]);
}
return arr;
}

Related

Function allocate and modify many (more than one) arrays in C [duplicate]

This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Closed 2 years ago.
A C function can modify more than one variable by an illusion of pass-by-reference (a pass-by-value of address as explained by Ely), e.g.:
#include <stdio.h>
void function(int *pa, int *pb) {
*pa *= *pa;
*pb *= *pb;
}
int main(void) {
int a = 1, b = 2;
function(&a, &b);
printf("a = %d\nb = %d\n", a, b);
return 0;
}
which outputs
a = 1
b = 4
It is also possible to modify a whole range of variables by returning a pointer to an array, e.g.:
#include <stdlib.h>
#include <stdio.h>
int *function(int *ptr_size) {
int n = 6; // arbitrary ptr_size
int *array = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; ++i)
array[i] = i * i;
//
*ptr_size = n;
return array;
}
int main(void) {
int size = 0;
int *array = function(&size);
printf("size = %d\n", size);
for (int i = 0; i < size; ++i)
printf("array[%d] = %d\n", i, array[i]);
free(array);
array = NULL;
return 0;
}
which outputs :
size = 6
array[0] = 0
array[1] = 1
array[2] = 4
array[3] = 9
array[4] = 16
array[5] = 25
But what if I want a function that modify more than one (dynamic allocated) array ?
I tried this
#include <stdlib.h>
#include <stdio.h>
void function(int *array, int *ptr_asize, int *brray, int *ptr_bsize) {
int size = 6;
array = (int *)malloc(size * sizeof(int));
brray = (int *)malloc(size * sizeof(int));
for (int i = 0; i < size; ++i) {
array[i] = i * i;
brray[i] = i * i * i;
}
*ptr_asize = size;
*ptr_bsize = size;
}
int main(void) {
int asize, bsize;
int *array, *brray;
function(array, &asize, brray, &bsize);
// array
printf("asize = %d\n", asize);
for (int i = 0; i < asize; ++i)
printf("array[%d] = %d\n", i, array[i]);
free(array);
array = NULL;
// brray
printf("bsize = %d\n", bsize);
for (int i = 0; i < bsize; ++i)
printf("brray[%d] = %d\n", i, brray[i]);
free(brray);
brray = NULL;
//
return 0;
}
but it makes a segmentation fault.
That is not very surprising, how main would know about how much memory has been allocated to array and brray?
So my question is: is it possible in C that a function allocate and modify more than one array, and those changes remain in main?
PS: A solution would be to allocate a new abrray that contains both array and brray (int **function(...) { ... return abrray; }), but I would like to know if it is possible to a function to modify two (or more) arrays, and that changes remain in main.
Pass a pointer to pointer, like this:
void func(int** array, int** brray, size_t size_a, size_t size_b) {
*array = malloc(size_a * sizeof(int));
*brray = malloc(size_b * sizeof(int));
}
Call it like:
int *arr, *brr;
func(&arr, &brr, 2, 5);
As explained by iTs.SL4y3r, it is possible by passing pointer to pointer.
Here is a minimal working example :
#include <stdlib.h>
#include <stdio.h>
void function(int **array, int *ptr_asize, int **brray, int *ptr_bsize) {
int size = 6;
*array = malloc(size * sizeof(int));
*brray = malloc(size * sizeof(int));
for (int i = 0; i < size; ++i) {
(*array)[i] = i * i;
(*brray)[i] = i * i * i;
}
*ptr_asize = size;
*ptr_bsize = size;
}
int main() {
int asize, bsize;
int *array, *brray;
function(&array, &asize, &brray, &bsize);
// array
printf("asize = %d\n", asize);
for (int i = 0; i < asize; ++i)
printf("array[%d] = %d\n", i, array[i]);
free(array);
array = NULL;
// brray
printf("bsize = %d\n", bsize);
for (int i = 0; i < bsize; ++i)
printf("brray[%d] = %d\n", i, brray[i]);
free(brray);
brray = NULL;
//
return 0;
}
which outputs :
asize = 6
array[0] = 0
array[1] = 1
array[2] = 4
array[3] = 9
array[4] = 16
array[5] = 25
bsize = 6
brray[0] = 0
brray[1] = 1
brray[2] = 8
brray[3] = 27
brray[4] = 64
brray[5] = 125

Return two pointers from a function in c

I know that you can return a pointer to the first element of an array in c by doing:
#include <stdlib.h>
#include <stdio.h>
int *my_func(void);
int main(void)
{
int *a;
int i;
a = my_func();
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, a[i]);
}
free(a);
return 0;
}
int *my_func(void)
{
int *array;
int i;
array = calloc(3, sizeof(int));
for(i = 0; i < 3; i++)
{
array[i] = i;
}
return array;
}
But if I wanted to return two pointers instead of just one, I tried:
#include <stdlib.h>
#include <stdio.h>
int *my_func(int *);
int main(void)
{
int *a;
int *b;
int i;
a = my_func(b);
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, a[i]);
printf("b[%d] = %d\n", i, b[i]);
}
free(a);
free(b);
return 0;
}
int *my_func(int *array2)
{
int *array;
int i;
array = calloc(3, sizeof(int));
array2 = calloc(3, sizeof(int));
for(i = 0; i < 3; i++)
{
array[i] = i;
array2[i] = i;
}
return array;
}
But this seg faults on the printf for b. I ran it through valgrind and it says that there is an invalid read of size 4 at the printf for b, which means I'm doing something screwy with the b pointer. I was just wondering what the best way to "return" a second pointer to an array was in c? I'm asking because I would like to do it this way rather than use a global variable (I'm not opposed to them, as they are useful at times, I just prefer not to use them if possible). The other questions I've seen on this site used statically allocated arrays, but I haven't yet stumbled across a question that was using dynamic allocation. Thanks in advance!
I can think of three (and a half) simple ways to return multiple items of any kind from a C-function. The ways are described below. It looks like a lot of text, but this answer is mostly code, so read on:
Pass in an output argument as you have done, but do it correctly. You have to allocate space for an int * in main() and then pass the pointer to that to my_func.
In main():
a = my_func(&b);
my_func() becomes:
int *my_func(int **array2)
{
int *array;
int i;
array = calloc(3, sizeof(int));
*array2 = calloc(3, sizeof(int));
for(i = 0; i < 3; i++)
{
array[i] = i;
(*array2)[i] = i;
}
return array;
}
Make your function allocate array of two pointers to the int arrays you are trying to allocate. This will require an additional allocation of two int pointers, but may be worth the trouble.
main() then becomes:
int main(void)
{
int **ab;
int i;
ab = my_func(b);
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, ab[0][i]);
printf("b[%d] = %d\n", i, ab[1][i]);
}
free(ab[0]);
free(ab[1]);
free(ab);
return 0;
}
my_func() then becomes:
int **my_func(void)
{
int **arrays;
int i, j;
arrays = calloc(2, sizeof(int *));
arrays[0] = calloc(3, sizeof(int));
arrays[1] = calloc(3, sizeof(int));
for(j = 0; j < 2; j++)
{
for(i = 0; i < 3; i++)
{
arrays[j][i] = i;
}
}
return arrays;
}
Return a structure or structure pointer. You will need to define the structure, and decide whether you want to return the structure itself, a newly allocated pointer to it, or pass it in as a pointer and have my_func() fill it in for you.
The structure definition would look something like this:
struct x
{
int *a;
int *b;
}
You would then rephrase your current functions as one of the following three options:
Direct passing of structure (not recommended for general use):
int main(void)
{
struct x ab;
int i;
ab = my_func();
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, ab.a[i]);
printf("b[%d] = %d\n", i, ab.b[i]);
}
free(ab.a);
free(ab.b);
return 0;
}
struct x my_func(void)
{
struct x ab;
int i;
ab.a = calloc(3, sizeof(int));
ab.b = calloc(3, sizeof(int));
for(i = 0; i < 3; i++)
{
ab.a[i] = i;
ab.b[i] = i;
}
return ab;
}
Return a pointer to a dynamically allocated structure (this is a pretty good option in general):
int main(void)
{
struct x *ab;
int i;
ab = my_func();
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, ab->a[i]);
printf("b[%d] = %d\n", i, ab->b[i]);
}
free(ab->a);
free(ab->b);
free(ab);
return 0;
}
struct x *my_func(void)
{
struct x *ab;
int i;
ab = malloc(sizeof(struct x));
ab->a = calloc(3, sizeof(int));
ab->b = calloc(3, sizeof(int));
for(i = 0; i < 3; i++)
{
ab->a[i] = i;
ab->b[i] = i;
}
return ab;
}
Allocate the structure in main() and fill it in in my_func via a passed-in pointer. This option is often used in a way where my_func would allocate the structure if you pass in a NULL pointer, otherwise it would return whatever you passed in. The version of my_func shown here has no return value for simplicity:
int main(void)
{
struct x ab;
int i;
my_func(&ab);
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, ab.a[i]);
printf("b[%d] = %d\n", i, ab.b[i]);
}
free(ab.a);
free(ab.b);
return 0;
}
void my_func(struct x *ab)
{
int i;
ab->a = calloc(3, sizeof(int));
ab->b = calloc(3, sizeof(int));
for(i = 0; i < 3; i++)
{
ab->a[i] = i;
ab->b[i] = i;
}
return;
}
For all the examples shown here, don't forget to update the declaration of my_func at the top of the file, although I am sure any reasonable compiler will remind you if you forget.
Keep in mind also that these are just three options I pulled out of my brain at a moments notice. While they are likely to cover 99% of any use cases you may come up against any time soon, there are (probably lots of) other options out there.
Function parameters are its local variables. Functions deal with copies of values of the supplied arguments.
You can imagine your function definition and its call the following way
a = my_func(b);
int *my_func( /* int *array2 */ )
{
int *array2 = b;
//...
}
So any changes of the local variable array2 inside the function do not influence on the original argument b.
For such a function definition you have to pass the argument by reference that is the function should be declared like
int *my_func( int **array2 );
^^
There are many ways to implement the function. You could define a structure of two pointers as for example
struct Pair
{
int *a;
int *b;
};
and use it as the return type of the function
struct Pair my_func( void );
Another approach is to pass to the function an array of pointers to the original pointers.
The function can look as it is shown in the demonstrative program.
#include <stdio.h>
#include <stdlib.h>
size_t multiple_alloc( int ** a[], size_t n, size_t m )
{
for ( size_t i = 0; i < n; i++ ) *a[i] = NULL;
size_t k = 0;
for ( ; k < n && ( *a[k] = malloc( m * sizeof( int ) ) ) != NULL; k++ )
{
for ( size_t i = 0; i < m; i++ ) ( *a[k] )[i] = i;
}
return k;
}
#define N 2
#define M 3
int main(void)
{
int *a;
int *b;
multiple_alloc( ( int ** [] ) { &a, &b }, N, M );
if ( a )
{
for ( size_t i = 0; i < M; i++ ) printf( "%d ", a[i] );
putchar( '\n' );
}
if ( b )
{
for ( size_t i = 0; i < M; i++ ) printf( "%d ", b[i] );
putchar( '\n' );
}
free( a );
free( b );
return 0;
}
The program output is
0 1 2
0 1 2
#include <stdlib.h>
#include <stdio.h>
int *my_func(int **);
int main(void)
{
int *a;
int *b;
int i;
b=(int *)malloc(sizeof(int));
a = my_func(&b);
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, a[i]);
printf("b[%d] = %d\n", i, b[i]);
}
free(a);
free(b);
return 0;
}
int *my_func(int **array2)
{
int *array;
int i;
array = calloc(3, sizeof(int));
*array2 =calloc(3,sizeof(int));
for(i = 0; i < 3; i++)
{
array[i] = i;
*((*array2)+i)=i;//or (*array2)[i]
}
return array;
}
Pass the pointer by reference. Because its the same logic as, to manipulate an integer block you need to pass a pointer to it. Similarly, to manipulate a pointer, you will have to pass a pointer to it(i.e. pointer to pointer).

wrong allocate memory matrix C?

I'm developing a program that read from CSV file and calculate score with a method "calculateMLpa". The method receive array of char and array of 10 float, and transform array of float in matrix 3x3. When read the position 3rd number from array, insert in matrix the 4th number and same for 6th number.
I.E.
array value[]={0.000000;123.814934;234.000000;100.000000;166.000000; 203.086639;383.000000;186.000000;338.000000;173.098419 }
array traj[]={"0-0";"0-1";"0-2";"1-0";"1-1";"1-2";"2-0";"2-1";"2-2"}
Xn_val[]={"0","1","2"}
When transform in matrix the result is:
123.814934 234.000000 166.000000
166.000000 203.086639 186.000000
186.000000 338.000000 173.098419
While the expected for [0;2] is 100.000000 and for [1;2]=383.000000, but when print the currently value of traj it's correct.
How can I fix this problem?
The code is all here:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <math.h>
#include <stdbool.h>
#include <ctype.h>
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
int csv_parse ( char *line, int size )
{
char *p;
char *dp;
int inquote;
int na;
int nTo_comma;
char prevc = ',';
char *list[256];
dp = NULL;
// inquote = 0;
na = 0;
prevc = ';';
nTo_comma=0;
for ( p = line; *p != '\n'; p++ )
{
nTo_comma++;
list[nTo_comma] = p;
if(*p == prevc)
{
printf("%s\t", list);
return na;
}
}
printf("\n");
return na;
}
double calculateMLpa(const char *Xn_val[], char *traj[], float value[], double alphaxixj, double tauxi, int sz, int dim) {
double mlx = 0;
double v;
double alphaxi;
char *state;
int i;
int p;
int j;
int k;
// int sz = sizeof(Xn_val) / sizeof(int);
// int dim = sizeof(traj) / sizeof(char);
double trns[sz][sz];
double m[sz];
char *trat="-";
// m[xi] values: the number of transitions leaving the state xi
printf("%d %d \n",sz,dim);
int cont=0;
for (i = 0; i <= sz; i++) {
m[i] = 0.0;
for (j = 0; j <= sz; j++) {
v = 0.0;
int newlength = strlen(Xn_val[i])+strlen(trat)+strlen(Xn_val[j])+1;
state = malloc(sizeof(char)*newlength);
if(state != NULL){
state[0] = '\0';
strcat(state,Xn_val[i]);
strcat(state,trat);
strcat(state,Xn_val[j]);
printf("%s ",state);
}else {
printf(stderr,"malloc failed!\n");
}
// for (k=0; k<=dim;++k){
if (traj[cont] != NULL ){
if (strcmp(traj[cont],state)==0){
v = value[cont+1];
printf("%f \n",v);
}
}
trns[i][j] = v;
printf("%f - \n",trns[i][j]);
if (strcmp(Xn_val[i],Xn_val[j])!=0)
m[i] = m[i] + v;
cont++;
}
}
for (i=0;i<=sz;++i){
for(j=0;j<=sz;++j){
printf("%f ",trns[i][j]);
}
printf("\n");
}
for (p=0;p<=sz;++p){
printf("%f - \n",m[p]);
}
printf("%f %f\n",trns[0][1],trns[0][2]);
alphaxi = alphaxixj * (((double) sz) - 1.0);
alphaxi = alphaxixj;
printf("%d ",sz);
for (i = 0; i <= sz; i++) {
for (j = 0; j <= sz; j++) {
// xi!=xj
if (strcmp(Xn_val[i], Xn_val[j])!=0) {
mlx = mlx + lgamma(alphaxixj + trns[i][j]) - lgamma(alphaxixj);
}
// xi
else {
mlx = mlx + lgamma(alphaxi) - lgamma(alphaxi + m[i]);
mlx = mlx + lgamma(alphaxi + m[i] + 1.0)+ (alphaxi + 1.0) * log(tauxi);
mlx = mlx - lgamma(alphaxi + 1.0)- (alphaxi + m[i] + 1.0) * log(tauxi + trns[i][j]);
}
}
}
return (mlx);
}
#define MAXFLDS 200 /* maximum possible number of fields */
#define MAXFLDSIZE 32 /* longest possible field + 1 = 31 byte field */
void parse(char *record, char *delim, char arr[][MAXFLDSIZE], int *fldcnt) {
char*p = strtok(record, delim);
int fld = 0;
while (p) {
strcpy(arr[fld], p);
fld++;
p = strtok('\0', delim);
}
*fldcnt = fld;
}
void main() {
printf("inizio\n");
FILE *pf;
int N=20;
bool first=true;
const char *a[]={"0","1","2"};
char *traject[]={"0-0","0-1","0-2","1-0","1-1","1-2","2-0","2-1","2-2"};
double bs=0;
char *trat="-";
pf=fopen("//home//user//prova.csv","r");
float array[10][10];
float *t;
char *str= "hello";
char *state;
t = (float *)malloc(N * sizeof(float));
int f=0;
if (pf)
{
size_t i, j, k;
char buffer[BUFSIZ], *ptr;
/*
* Read each line from the file.
*/
for ( i = 0; fgets(buffer, sizeof buffer, pf); ++i )
{
/*
* Parse the comma-separated values from each line into 'array'.
*/
for ( j = 0, ptr = buffer; j < ARRAYSIZE(*array); ++j, ++ptr )
{
array[i][j] = strtof(ptr, &ptr);
}
}
fclose(pf);}
else /* fopen() returned NULL */
{
perror(pf);
}
for(f=0; f<10; ++f){
if(f==0){}
else if(f==1 && array[f][8]==0)
array[f][8]=123.8149353;
t[f]=array[f][8];
//printf("%f \n",t[f]);
}
for (f=0;f<10; ++f){
printf("%f - ",t[f]);
}
//printf("%s, %s, %s \n",a[0],a[1],a[2]);
printf("start\n");
int sz = sizeof(a) / sizeof(char);
int dim = sizeof(traject) / sizeof(char);
printf("%d , %d \n",sz,dim);
bs=calculateMLpa(a,traject,t,1.0,0.1,sz,dim);
printf("done \n");
printf("%f ",bs);
}
EDIT
I try to pass array size
sz=sizeof(a)/sizeof(char)
dim = sizeof(traject) / sizeof(char);
but their value is 24 and 72 respectively, and the execution stops at 0-2 value 100.000000
Arrays passed to functions decay to pointers to the start of the array. So
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
Will not return anything meaningful when checking for its size in that case
To fix, pass the Array size as an additional Argument.
One major problem is that when you pass arrays to functions, they decay to pointers, and the sizeof trick you use to get the array size will not work.
You need to pass the actual array sizes as arguments.

Append a character to a list n times

I want to create random data for testing. I want to fill an array with 100 strings of random length with the letter 'A'.
example:
array[0] = "AAAAA"
array[1] = "AAAAAAAA"
array[2] = "A"
...
char **create_string()
{
char **array = malloc(sizeof(**array));
srand((unsigned int)time(NULL));
int random = 0;
int i, j;
for(int i=0; i<100; i++)
{
random = rand() % 100;
for(j=0; j < random; j++)
{
array[i] = // some sort of string append that would be cheap.
}
}
}
I was looking at this C string append and they use strcat. Is there a better way to solve my problem? Since I will be running in a loop to create those random size strings.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char **create_string(size_t n) {
char **array = malloc(sizeof(char*) * n);
int i, j;
for(i=0; i<100; i++)
{
size_t sz = rand() % 100;
array[i] = malloc(sz + 1);
for(j=0; j < sz; j++) {
array[i][j] = 'A';
}
array[i][sz] = 0;
}
return array;
}
int main() {
char **array;
size_t i;
srand((unsigned int)time(NULL));
array = create_string(100);
for (i = 0; i < 100; i++)
printf("%s\n", array[i]);
return 0;
}
Alternatively, you can create a template string and copy required number of characters into each random string:
char **create_string(size_t n) {
char template[101];
char **array = malloc(sizeof(char*) * n);
int i;
for (i = 0; i < 100; i++)
template[i] = 'A';
template[100] = 0;
for(i = 0; i < n; i++) {
size_t sz = rand() % 100;
array[i] = malloc(sz + 1);
strncpy(array[i], template, sz);
array[i][sz] = 0;
}
return array;
}
This will depend on the distribution of string lengths that you want. This is a uniform distribution of string lengths, from 0 to 200.
int n = rand() % 200 * sizeof(*array);
array[i] = malloc(n + 1);
memset(array[i], 'A', n);
array[i][n] = '\0';
But you could have a Gaussian distribution, a Poisson distribution, etc.
char **create_string()
{
char **array = malloc(sizeof(char *) * 100);
srand((unisgned int)time(NULL));
int i;
for (i = 0; i <100;i++)
{
int random = rand() % 100;
array[i] = malloc(random);
memset(array[i],'A',random-1);
array[random-1] = '\0';
}
return array;
}
Problem for you to fix: what happens if random is 0? Also the random numbers will not be equaly distributed. Only modulo by a power of 2 will achieve that.
Here's an approach that doesn't put an upper bound on any individual string, but does put an exact bound on the total length of all strings. It also only calls malloc twice.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TOT_SIZE (5000) /* adjust to taste */
#define TOT_STRS (100)
char **create_strings()
{
char **array = (char**) malloc(TOT_STRS * sizeof(char *));
char *str = (char*) malloc(TOT_SIZE);
int zeros = 1;
int i;
memset(str, 'A', TOT_SIZE - 1);
str[TOT_SIZE - 1] = 0;
while (zeros < TOT_STRS)
{
int pos = rand() % TOT_SIZE;
if (str[pos] != 0)
{
str[pos] = 0;
zeros++;
}
}
array[0] = str;
for (i = 1; i < TOT_STRS; i++)
{
array[i] = array[i - 1] + strlen(array[i - 1]) + 1;
}
return array;
}
And a short test program:
int main()
{
char **a = create_strings();
int i;
for (i = 0; i < TOT_STRS; i++)
{
printf("%3d: %s\n", i, a[i]);
}
return 0;
}
This code assumes that all the random strings need to be non-overlapping. If they can overlap in memory, you only need one string, and an array of pointer to different starting points in that one string.
You do not have to allocate the real 100 strings. Firstly you just declare a long enough array char long_array[100]. and then you use random = rand() % 100; get the random. Secondly you just pass the long_array and the random to your function. Then your problem is solved.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
char **create_string(const size_t array_size,
const size_t string_size,
const unsigned char chr)
{
srand((unsigned)time(NULL));
char ** array = malloc(array_size * sizeof (char *));
size_t t;
for (t = 0; t < array_size; ++t) {
array[t] = malloc(string_size * sizeof(char));
array[t][string_size] = '\0';
memset(array[t], chr, (rand() % string_size) + 1);
}
return array;
}
main() {
char ** randstring = create_string(10, 7, 'A');
int t = 0;
for (; t < 10; ++t)
printf("%s\n", randstring[t]);
return 0;
}
Possible output
AAAAAA
AAAAA
AAAAAA
AAA
AAAAA
AAAAAA
AAAAAA
AAAAAAA
AAAA
AAAA

How to create a variable sized array, pass a variable 2d array to a function and return another 2d array?

How do you create an 2d array with variable size, pass that variable array, and return a new 2d array of different dimensions? I've been working on this for hours and I can't find a solution. I managed to create an array of pixel values for a PGM image, but now I'm trying to "rotate" the array, but this is getting incredibly complex since my compiler won't let me declare a variable-sized object.Thank you so much to those who answer.
This is the statement that calls the function. Somebody told me to use malloc since you can't create an array with variable size.
char *SpunArray = malloc(image->x * image->y * sizeof(PGMPixel));
SpunArray = Rotate90Array(image->x, image->y, CreatedArray);
This is the function:
//char * Rotate90Array(int x, int y, char *array[x][y] )
char * Rotate90Array(int x, int y, char *array )
{
printf("\nLine 179");
// These have to be swapped because the image is being rotated
char *RotatedArray = malloc(x * y * sizeof(char));
printf("\nLine 182");
int u = x - 1;
int v = y - 1;
int i = 0;
int j = 0;
printf("\nLine 187");
char *ptr;
printf("\nLine 189");
for (i = 0; i < x; i++)
{
printf("\nLine 192");
*ptr = RotatedArray[i];
printf("\nLine 194");
for (j = 0; j < y; j++)
{
printf("\nLine 197");
// *ptr = *(array[u-j][i]);
*(ptr+((j*x)+(u-i))) = *(array+((i*y)+j));
printf("\nLine 200");
ptr++;
printf("\nLine 202");
}
}
printf("\nLine 205");
return RotatedArray;
}
I'm using the MingGW gcc, and windows 8 if that helps.
You have a memory leak. Why do you creating two arrays instead one?
Do like this:
char *SpunArray = malloc(image->x * image->y * sizeof(PGMPixel));
Rotate90Array(image->x, image->y, CreatedArray, SpunArray);
void Rotate90Array(int width, int height, char *array, char *RotatedArray)
{
int i = 0;
int j = 0;
for (i = 0; i < width; i++)
{
for (j = 0; j < height; j++)
{
// check this line on correct
RotatedArray[i * height + j] = array[j * width + width - i - 1];
}
}
}
I think this code can work as expect:
char * Rotate90Array(int x, int y, char *array )
{
printf("\nLine 179");
// These have to be swapped because the image is being rotated
char *RotatedArray = malloc(x * y * sizeof(char));
printf("\nLine 182");
int u = x - 1;
int v = y - 1;
int i = 0;
int j = 0;
printf("Line 187\n");
char *ptr;
printf("Line 189\n");
ptr = RotatedArray; //I add this line
for (i = 0; i < x; i++)
{
printf("Line 192\n");
// *ptr = RotatedArray[i]; //I delete this line
printf("Line 194\n");
for (j = 0; j < y; j++)
{
printf("Line 197\n");
// *ptr = *(array[u-j][i]);
*(ptr+((j*x)+(u-i))) = *(array+((i*y)+j));
printf("Line 200\n");
// ptr++; // I delete this line
printf("Line 202\n");
}
}
printf("Line 205\n");
return RotatedArray;
}

Resources