Code giving runtime error? - c

i am trying to solve leetcode question :-
https://leetcode.com/problems/largest-number/
Given a list of non negative integers, arrange them such that they form the largest number.
For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330.
i am trying to sort strings by defining comparator to compare strings by concatinating right-to-left or left-to-right.
The program is giving runtime error. Please help....
int comp(const void* a, const void* b){
int p = *((int *)a);
int q = *((int *)b);
int size = 14;
char * first = (char *)malloc(size * sizeof(char));
char * second = (char *)malloc(size * sizeof(char));
first[0] = "\0";
second[0] = "\0";
sprintf(first, "%d",p);
sprintf(first, "%d",q);
sprintf(second, "%d",q);
sprintf(second, "%d",p);
return -1*strcmp(first, second);
}
char* largestNumber(int* nums, int numsSize) {
if(numsSize <=0)
return NULL;
qsort(nums, numsSize, sizeof(int), comp);
char * result = (char*)malloc(numsSize *5*sizeof(char));
int i;
for(i=0; i<numsSize; i++)
result = strcat(result, nums[i]);
return result;
}

Allocating memory with malloc() and throwing it away is a bad practice.
Since you always allocate fixed amount of memory in comp, use regular array.
Don't do first[0] = "\0";, which is assigning an pointer to char variable.
Also remove useless sprintf, whose result is soon be overwritten.
Allocating 5 bytes for each elements may be too small if int has 4 bytes. Allocate more memory.
Initialize the buffer pointed by result before passing it to strcat().
Convert the integer to string before passing it to strcat().
They say that you shouldn't cast the result of malloc() in C.
Possible fix (not tested):
int comp(const void* a, const void* b){
int p = *((int *)a);
int q = *((int *)b);
char first[14];
char second[14];
sprintf(first, "%d", q);
sprintf(second, "%d", p);
return -1 * strcmp(first, second);
}
char* largestNumber(int* nums, int numsSize) {
if(numsSize <= 0)
return NULL;
qsort(nums, numsSize, sizeof(int), comp);
char * result = malloc(numsSize * 14 * sizeof(char));
int i;
result[0] = '\0';
for(i = 0; i < numsSize; i++) {
char num[14];
sprintf(num, "%d", nums[i]);
result = strcat(result, num);
}
return result;
}

Related

Expand a C array inside a function

This works in a main, but breaks when put into a function. I'm not sure how to reassign the pointer after passing into a function.
void expandArray(int** arr[], int* size) {
int *temp;
*temp = *arr;
*arr = (int*) malloc(*size * 2 * sizeof(int));
for (int i = 0; i < *size; i++) {
printf("assigning from temp: %d ", temp[i]);
arr[i] = temp[i];
printf("to arr: %d \n", arr[i]);
}
*size = *size * 2;
free(temp);
}
main(){
int *arr;
arr = (int*) malloc(maxSize * sizeof(int));
if ....
expandArray(arr, &arrSize);
// use bigger arr for other stuff
}
In main, arr is declared as int *arr. When main calls expandArray, it should pass a pointer to arr, which is written &arr and has type int **a.
However, you declared the parameter to expandArray as int **arr[], adding additional brackets. Those are unnecessary and change the type, and your compiler should have warned you about that. Pay attention to compiler warnings. Be sure you understand them, and resolve them before proceeding.
In expandArray, you use both arr[i] and temp[i] to access the array. However, arr[i] is not a correct way to access array elements. When the declaration of the arr parameter is corrected, it will be int **arr, and it will not be proper to refer to an element of the array as arr[i]. It will be (*arr)[i].
Commonly, to make this a little less confusion, authors will use a temporary variable to hold the pointer, so they do not need the extra asterisk:
int *NewArray = malloc(...); // Get new space.
*arr = NewArray; // Send new address to caller.
...
NewArray[i] = temp[i]; // Use temporary variable for access.
Some other points:
When calling malloc, use sizeof *p, where p is the pointer being assigned to, rather than sizeof(int). This is better because, if you later want to change the type for p, it only has to be changed in its declaration, not also in the sizeof. Then there is less likely to be a mistake where it is changed in one place and not another.
Do not cast the result of malloc. This is unnecessary in C, although it is required in C++.
main should be declared as int main(void) or int main(int argc, char *argv[]), not as main(). (C implementations may also provide for other forms.)
Use size_t for sizes of arrays, not int, and either size_t or ptrdiff_t for indices of arrays.
Overall, the code could be:
#include <stdio.h>
#include <stdlib.h>
void expandArray(int **arr, int *size)
{
// Record old pointer and size in temporary variables for convenience.
int *OldArray = arr;
size_t OldSize = *size;
// Prepare new size and pointer.
size_t NewSize = 2 * OldSize;
int *NewArray = malloc(NewSize * sizeof *NewArray);
// Handle allocation failure.
if (!NewArray)
{
fprintf(stderr, "Error, unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
// Copy data from old array to new array.
for (size_t i = 0; i < OldSize; ++i)
NewArray[i] = OldArray[i];
// Send new size and pointer to caller.
*size = NewSize;
*arr = NewArray;
// Release old memory.
free(OldArray);
}
int main(void)
{
int *arr;
arr = malloc(InitialSize * sizeof *arr);
if (...)
expandArray(&arr, &arrSize);
// use bigger arr for other stuff
}
I think the arr sould be int ** type.
void expandArray(int** arr, int* size) {
int *temp;
temp = *arr;
*arr = (int*) malloc(*size * 2 * sizeof(int));
for (int i = 0; i < *size; i++) {
printf("assigning from temp: %d ", temp[i]);
(*arr)[i] = temp[i];
printf("to arr: %d \n", (*arr)[i]);
}
*size = *size * 2;
free(temp);
}
If you just want to expand the array size, you can use realloc.
And the extended area should be initialized using memset.
void expandArray(int** arr, int* size) {
*arr = (int*) realloc(*arr, *size * 2 * sizeof(int));
memset(*arr+*size, 0, *size * sizeof(int));
*size = *size * 2;
}

Confusion with malloc. Creating an array of strings with 4 slots

int main() {
char *p[] = {"hello", "goodbye"};
char **a;
a = malloc(4 * 8);
}
I want a to have double the slots of p. How would I successfully do that without manually putting in numbers. All IK is the size of p should be there and x 2 for the double. How would I get the 8?
Using the sizeof operator which returns you the size in bytes that a
type/variable needs.
In your case
int main() {
// because "hello" and "goodbye" are const char*
const char *p[] = {"hello", "goodbye"};
size_t len_p = sizeof p / sizeof p[0];
char **a;
a = malloc( 2 * len_p * sizeof *a );
...
free(a);
}
sizeof p / sizeof p[0]; returns you the number of elements in the p array.
sizeof p returns you the total amount of bytes, sizeof p[0] returns you the
size of single element. Hence total size / size of element returns you the
number of elements. But be aware that this method only works for arrays, not
pointer. Consider this:
void add_one(int *ptr)
{
size_t len = sizeof ptr / sizeof ptr[0];
for(size_t i = 0; i < len; ++i)
ptr[i] += 1;
}
int main(void)
{
int arr[] = { 1,2 3 };
add_one(arr);
return 0;
}
is wrong, because ptr is pointer, not an array, so sizeof ptr returns you
the size of a pointer, not the total amount of bytes needed by arr. That's why
when you write a function that takes a pointer where you pass an array, the
function should also take the size of the array, otherwise the size cannot be
calculated, for example:
void add_one(int *ptr, size_t len)
{
for(size_t i = 0; i < len; ++i)
ptr[i] += 1;
}
int main(void)
{
int arr[] = { 1,2 3 };
add_one(arr, sizeof arr / sizeof arr[0]);
return 0;
}
I think what you are asking is how to figure out how many strings have been put in p. To do this, you can count the number of elements in p :
char *p[] = { "hello", "goodbye" };
printf("%zu\n", sizeof(p) / sizeof(*p));
sizeof(p) is the total size of p
sizeof(*p) is the size of a single element of p
so dividing them gives you the number of elements in p
To malloc() a second array, twice as large :
int main() {
char *p[] = { "hello", "goodbye", "lala" };
size_t size = sizeof(p) / sizeof(*p);
char **a;
a = malloc(size * 2 * sizeof(*a));
}
void allocarr(char** matrix, int bytes, int slots)
{
int i = 0;
while(i <= slots)
{
matrix[i] = (char*)calloc(1, bytes);
++i;
}
}
...
char** s = malloc(4*sizeof(char*);
s = allocarr(s, 512, 4);

C Malloc Multidimensional Char Array

I would like to dynamically allocate (malloc) a multidimensional character array in C. The array would have the following format:
char *array[3][2] = {
{"one","two"},
{"three","four"},
{"five","six"}
};
Before the array would be created, I would already know the number of rows and the lengths of all of the characters arrays in the multidimensional array.
How would I malloc such a character array?
Thanks in advance!
This is one way to allocate a two dimensional array of char *.
Afterwards, you can assign the contents like a[1][2] = "foo";
Note that the elements of the array are initialized to (char *)0.
#include <stdio.h>
#include <stdlib.h>
char ***alloc_array(int x, int y) {
char ***a = calloc(x, sizeof(char **));
for(int i = 0; i != x; i++) {
a[i] = calloc(y, sizeof(char *));
}
return a;
}
int main() {
char ***a = alloc_array(3, 2);
a[2][1] = "foo";
printf("%s\n", a[2][1]);
}
[Charlies-MacBook-Pro:~] crb% cc xx.c
[Charlies-MacBook-Pro:~] crb% a.out
foo
First of all, arrays are typically stored in Row Major form, so in reality you have a vector six elements long, each entry is a char * ptr. That is, the elements labelled by row, column are similar to:
char *r1c1, *r1c2, *r2c1, *r2c2, *r3c1, *r3c1;
Thus, do a SIMPLE malloc of:
char *matrix = malloc(3*2*sizeof(char *));
Then set the elements as:
matrix[0] = "one";
matrix[1] = "two";
matrix[2] = "three";
matrix[3] = "four";
matrix[4] = "five";
matrix[5] = "six";
Finally, to test this write a nested loop as:
for (int r=0; r<3; r++)
{
for (int c=0; c<2; c++);
{
printf("%s\n",matrix[r][c]);
}
}
Note, how a matrix is treated first as a vector then as a matrix. C doesn't care!!
char *array[3][2] is nothing but a two dimensional array of pointers. Hence you need the storage space of 3*2*sizeof(char *) to store the pointers.
As you mentioned, the pointers are actually pointing to zero-terminated strings and you may like the strings to be malloc'ed as well. Assuming the total length of all the strings to be N (including zero-termination), the storage space needed is (3*2*sizeof(char *) + N).
Allocate memory for the above mentioned size and the copy the strings yourselves as below.
In the following code, we assume that the number of columns (2) is a constant
char *(*dst)[2] = (char *(*)[2]) malloc(3*2*sizeof(char *) + N);
char * s = ((char *) dst) + (3*2*sizeof(char *));
for (i = 0; i < 3; i++)
{
for (j = 0; j < 2; j++)
{
strcpy(s, src[i][j]);
dst[i][j] = s;
s += strlen(s)+1;
}
}
NOTE: In the above code, 'dst' is a pointer that points to the first row of the 2D array of char *.
If the number of columns is not constant, the syntax changes a bit, but the storage size is the same.
char **dst = (char **) malloc(3*2*sizeof(char *) + N);
char * s = ((char *) dst) + (3*2*sizeof(char *));
for (i = 0; i < 3; i++)
{
for (j = 0; j < 2; j++)
{
strcpy(s, src[i][j]);
dst[i*2 + j] = s; /* 2 is the number of columns */
s += strlen(s)+1;
}
}
NOTE: Here 'dst' is a pointer that points to the first element of 1D array of char * and the 2D indexing is done manually.
The above examples assume that the string lengths will not change after allocation. If the strings can change at any point in time after allocation, then it is better to allocate for each string separately.
Keep it simple, Sheldon. The answer you've selected uses a char ***, which is not even close to the equivalent of a char *[2][3]. The difference is in the number of allocations... An array only ever requires one.
For example, here's how I'd retro-fit the answer you selected. Notice how much simpler it is?
#include <stdio.h>
#include <stdlib.h>
void *alloc_array(size_t x, size_t y) {
char *(*a)[y] = calloc(x, sizeof *a);
return a;
}
int main() {
char *(*a)[2] = alloc_array(3, 2);
a[2][1] = "foo";
printf("%s\n", a[2][1]);
}
In case you arrive in this page, wanting to create an array like int myarray[n][M] (which is slighly different from the question since they want an array of string), where M is fixed and n can vary (for example if you want an array of coordinates...), then you can just do:
int (*p)[M] = malloc(n*sizeof *p);
and then use p[i][j] as before. Then, you will get sizeof p[i] = M*sizeof(int):
#include <stdio.h>
#include <stdlib.h>
#define M 6
int main(int argc, char *argv[])
{
int n = 4;
int (*p)[M] = malloc(n*sizeof *p);
printf("Size of int: %lu\n", sizeof(int));
printf("n = %d, M = %d\n", n, M);
printf("Size of p: %lu (=8 because pointer in 64bits = 8 bytes)\n", sizeof p);
printf("Size of *p: %lu (=M*sizeof(int) because each case is an array of length M)\n", sizeof *p);
printf("Size of p[0]: %lu (=M*sizeof(int) because each case is an array of length M)\n", sizeof p[0]);
// Assign
for (int i=0; i<n; i++) {
for (int j=0; j<M; j++) {
(p[i])[j] = i*10+j;
}
}
// Display
for (int i=0; i<n; i++) {
for (int j=0; j<M; j++) {
printf("%2d; ", (p[i])[j]);
}
printf("\n");
}
return 0;
}
which gives:
Size of int: 4
n = 4, M = 6
Size of p: 8 (=8 because pointer in 64bits = 8 bytes)
Size of *p: 24 (=M*sizeof(int) because each case is an array of length M)
Size of p[0]: 24 (=M*sizeof(int) because each case is an array of length M)
0; 1; 2; 3; 4; 5;
10; 11; 12; 13; 14; 15;
20; 21; 22; 23; 24; 25;
30; 31; 32; 33; 34; 35;

C qsort() with dynamic n by 2 multi-dimensional array

First, I defined a dynamic array with 2 columns and 10 row. The integer number is set to 10 here just for example.
int** array;
int number = 10;
array = malloc(number * sizeof(int*));
for (i = 0; i < number; i++)
array[i] = malloc(2 * sizeof(int));
Then I try to use qsort() on it.
qsort( array, number, sizeof array[0], compare );
This is my compare function. It sorts by the integer values in the first column, then sorts by the second column while preserving the order in the first column. E.g. "0 2, 1 7, 0 1" will become "0 1, 0 2, 1 7".
int compare ( const void *pa, const void *pb ) {
int (*a)[1] = pa;
int (*b)[1] = pb;
if ( (a[0][0] < b[0][0]) || (a[0][0] == b[0][0])&&(a[1][0] < b[1][0]) ) return -1;
if ( (a[0][0] > b[0][0]) || (a[0][0] == b[0][0])&&(a[1][0] > b[1][0]) ) return +1;
return 0;
}
Question
This worked with a static array. I know it doesn't work now because I have a dynamic array, which is an array of pointers.
How can I adapt this code to work with the dynamically created multi-dimensional array?
sample code
#include <stdio.h>
#include <stdlib.h>
int compare ( const void *pa, const void *pb ) {
const int *a = *(const int **)pa;
const int *b = *(const int **)pb;
if(a[0] == b[0])
return a[1] - b[1];
else
return a[0] - b[0];
}
/*
#define NUMCMP(x,y) (((x) < (y)) ? -1 : ((x) > (y)) ? 1 : 0)
int compare ( const void *pa, const void *pb ) {
const int (*a)[2] = *(const int (**)[2])pa;
const int (*b)[2] = *(const int (**)[2])pb;
int tmp;
if((tmp=NUMCMP((*a)[0], (*b)[0]))==0)
return NUMCMP((*a)[1], (*b)[1]);
else
return tmp;
}
*/
int main(void){
int **array;
int number = 10;
int i;
array = malloc(number * sizeof(int*));
for (i = 0; i < number; i++){
array[i] = malloc(2 * sizeof(int));
array[i][0] = rand()%20;
array[i][1] = rand()%20;
}
for(i = 0;i < number;++i)
printf("%2d, %2d\n", array[i][0], array[i][1]);
printf("\n");
qsort(array, number, sizeof array[0], compare);
for(i = 0;i < number;++i)
printf("%2d, %2d\n", array[i][0], array[i][1]);
return 0;
}
what *(const int **)pa
array = {(int *), (int *), (int *), ... , (int *) }
qsort need each element address for element (for swap, etc. Because the size and number and start address of the element since only the given information).
E.g &(int *), &(int *)
so (int **) pass to function compare.
call compare(int **, int **) &(int*) meant at arg int**
compare function prototypeis cmp(const void*, const void*)
cast (const int**)pa is cast to passed original pointer.
*((const int **)pa) is dereference original element pointer(int*)
Since you now have an array of pointers, the arguments to your comparison function are going to be pointers to pointers. Use them like this:
int *const *a = pa;
int *const *b = pb;
Now you have a and b as two pointers into the array you're sorting. Each one points to a single element that the sort function is asking you to examine. You can access these elements as *a and *b or a[0] and b[0] but should not ever use a[1] or b[1]. If the sort function asks you to compare the first element in the array (*a) and the fifth element in the array (*b), a[1] and b[1] are the second and sixth elements of the array - completely irrelevant to the comparison you're supposed to be doing.
After the first level of dereferencing, you're allowed to do whatever you need to do to examine the elements being compared. Since your array elements are themselves pointers to arrays (of 2 int each), the ints can be accessed as a[0][0] a[0][1] b[0][0] b[0][1]. Notice this is the opposite order from your a[1][0] and b[1][0].
Writing them as (*a)[0] would provide a reminder that the first level of indirection is a "single-element-access-only" pointer. I'm undecided on whether this makes the whole thing clearer.
I came across this thread in search of a ditto problem of mine, and I lastly end-up doing the below thing.
static int compareMatrixElements(const void *p1, const void *p2)
{
return ((*(int const *) p1) - (*(int const *) p2));
}
void sortMatrix(int** matrix, int r, int c)
{
int sort_matrix[r][c];
for(int i = 0; i < r; i++) {
memcpy(sort_matrix[i], matrix[i], c * sizeof(int));
}
qsort(sort_matrix, r*c, sizeof(int), compareMatrixElements);
for(int i = 0; i < r; i++) {
memcpy(matrix[i], sort_matrix[i], c * sizeof(int));
}
}
In the above code of mine I used qsort API directly, one can use this api or any other sort algo on a contiguous memory, but what If you are having a matrix whose rows are pointer to the memory of its columns (like in my case as well as described in the question of this thread). Hence I copied such matrix into a contiguous memory, ran sort on that contiguous memory and copied back the sorted elements to the matrix.
The above solution worked for me, I thought it might be helpful others so I posted it, suggest any improvement for the same.
const int *a = *(const int **)pa;
const int *b = *(const int **)pb;
#BLUEPIXY, this is not correct.
Just enough
const int *a = pa;
const int *b = pb;
becouse pa is const void * (array[0]) and it very well cast to const int *
const int (*a)[2] = *(const int (**)[2])pa;
const int (*b)[2] = *(const int (**)[2])pb;
#BLUEPIXY, this is not correct. Just enough
const int (*a)[2] = (int(*)[])pa;
const int (*b)[2] = (int(*)[])pb;
sizeof array[0] will be "2 * sizeof(int)", for this static array.
int array[10][2];
sizeof array[0] will be "sizeof(int*)", for this pointer-to-pointer.
sizeof array[0][0] will be "sizeof(int)", for this pointer-to-pointer.
int **array;
So, First thing is you cannot use "qsort( array, number, sizeof array[0], compare );" in case of pointer-to-pointer implementation.

triple pointers, arrays, and malloc

My code compiles just fine, but I'm still a little rough on the pointer and array concepts. I would appreciate your help very much.
void initialize(int individual_count, int family_count, char ***indiIDs,
char ***names, char ***spousesIDs, char ***childIDs)
//so here I declared two int variables and four triple pointers,
// which are pointer to a pointer to a pointer to an integer, correct?
{
int i;
//malloc allocates memory space and returns the address of the
// first byte to the pointer *indiIDs,right?
(*indiIDs) = (char**)malloc(sizeof(char*) * individual_count);
(*names) = (char**)malloc(sizeof(char*) * individual_count);
for(i = 0; i <individual_count; i++)
{
(*indiIDs)[i] = (char*)malloc(sizeof(char) * 20);
(*names)[i] = NULL;
}
//*indiIDs[i] is an array of pointers, correct? so what exactly
// is the difference between mallocing and returning to *indiIDs
// and then to *indiIDs[i] as seen here?
(*spousesIDs) = (char**)malloc(sizeof(char*) * family_count);
(*childIDs) = (char**)malloc(sizeof(char*) * family_count);
for(i = 0; i < family_count; i++)
{
(*spousesIDs)[i] = (char*)malloc(sizeof(char) * 40);
//since spousesIDs[][] is a 2D array, would *spousesIDs[][]
// indicate a triple array then?
(*spousesIDs)[i][0] = '\0';
(*childIDs)[i] = NULL;
}
}
Your example doesn't show a 3D array, but a 2D array:
void init2D(char * ** x, int w, int h)
{
(*x) = (char**)malloc(sizeof(char*) * w);
for (i=0; i<w; i++) (*x)[i] = (char*)malloc(sizeof(char) * h);
}
The reason it has an additional * as a function parameter, is because C doesn't have pass-by-refence like C++
It's used this way:
void main ()
{
char ** lines = 0;
init2D (&lines, 4, 256); // char[256] x 4
}

Resources