Related
Hello everyone,
I wrote an code which is remove duplicates from sorted array. I know that there are lots of people have a good know how about clean code in this platform. I want to write code especially clean code. So I wanna hear some suggestion this about. If yo critise my code I am glad.
#include <stdio.h>
int main()
{
int arr[]={1,2,2,2,3,4,4,4,5,6,7,7,7,8,8};
int arr_size = *(&arr + 1) - arr;
printf("length of array %d\n",arr_size);
int result[arr_size];
int last_item= result[0];
for (int i=0; i<arr_size;i++)
{
if(arr[i]!=last_item)
{
last_item= arr[i];
result[i]= last_item;
printf("result : %d\n", result[i]);
}
}
return 1;
}
For starters it is unclear why main returns 1 instead of 0.
Secondly you are not removing duplicate elements from an array. You are trying to copy unique elements from one array into another array.
Also it is unclear why the result array has arr_size elements as the source array.
This declaration
int last_item= result[0];
is invalid because the result array is not initialized. So it contains indeterminate values.
Also in the for loop you are using the invalid index i for the result array. So again some elements of the result array will have indeterminate values.
result[i]= last_item;
And within the for loop there should not be any call of printf. If you want to output the result array (it is already another task) then you need to use a separate loop or function.
And at last you should write a separate function that performs the task of copying unique or removing duplicate elements..
I would write a function that indeed removes duplicates from an array the following way as shown in the demonstration program below.
#include <stdio.h>
size_t remove_duplicates( int a[], size_t n )
{
size_t m = 0;
for (size_t i = 0; i < n; i++)
{
if ( i == 0 || a[i] != a[m-1])
{
if (i != m)
{
a[m] = a[i];
}
++m;
}
}
return m;
}
int main( void )
{
int arr[] = { 1,2,2,2,3,4,4,4,5,6,7,7,7,8,8 };
const size_t N = sizeof( arr ) / sizeof( *arr );
for (size_t i = 0; i < N; i++)
{
printf( "%d ", arr[i] );
}
putchar( '\n' );
size_t m = remove_duplicates( arr, N );
for (size_t i = 0; i < m; i++)
{
printf( "%d ", arr[i] );
}
putchar( '\n' );
}
The program output is
1 2 2 2 3 4 4 4 5 6 7 7 7 8 8
1 2 3 4 5 6 7 8
For some reason, the first output my program is giving, is garbage value, while the second output is correct.
This is a problem from HackerRank.
I know this question has already been asked by someone else. I just want to know what the problem is in my code.
#include <stdio.h>
int main()
{
int index,query;
int count1 = 0;
scanf("%d%d",&index,&query);
for(int i=0;i<index;i++)
{
int b;
scanf("%d",&b);
int A[index][b];
for(int j=0;j<b;j++)
{
scanf("%d",&A[i][j]);
}
count1++;
if(count1<index)
{
continue;
}
int count2=0;
while(count2<query)
{
int d,e;
scanf("%d%d",&d,&e);
printf("%d\n",A[d][e]);
count2++;
}
}
return 0;
}
If the input is:
2 2
3 1 5 4
5 1 2 8 9 3
0 1
1 3
Then the output should be:
5
9
But instead, my output is:
garbage
9
Disclaimer
I didn't even click the link, so I do not know if the solution is correct, but assuming that you got the logic right..
The problem
is that you populate in stages a local to the body of the for loop 2D array, which at the end of your processing, you expect to have it accessible (I mean the complete matrix, populated from every single iteration of the for loop).
Instead, you get only the last's iteration declared array, that's why you get only the A[1][3] element right, and not the A[0][1], since the 2nd row is populated in the last (2nd iteration), while the 1st row is populated in the first iteration (of the firstly declared A), which goes out of scope as soon as the first iteration terminates.
The fix
So, what you need to fix this is to dynamically allocate memory for your matrix, and every time a new dimension for the columns is inputed, resize it with realloc().
I believe that the explanation I have in 2D dynamic array (C) will help you, since what you want is the number of rows fixed, and the number of columns adjustable on every iteration.
Below is an illustration based on the link I shared above, which visualizes what exactly is your matrix (a 1D array of pointers), and shows how the code below manipulates it:
Full code example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int index,query;
int count1 = 0;
scanf("%d%d",&index,&query);
// An array of `index` (e.g. 2) pointers to integers
int *A[index];
// Initialize all the pointers to NULL
for(int k = 0; k < index; ++k)
A[k] = NULL;
for(int i=0;i<index;i++)
{
int b;
scanf("%d",&b);
// Replaced your 'int A[index][b];' with the following:
// Every time a new number of columns (that's 'b') is read,
// we need to adjust the numbers of columns our matrix ('A') has.
// That means, that for every pointer (row), we need to re-allocate
// the number of columns it points to, which is basically a 1D array, of dimension 'b'
for(int k = 0; k < index; ++k)
A[k] = realloc(A[k], b * sizeof(int) );
for(int j=0;j<b;j++)
{
scanf("%d",&A[i][j]);
}
count1 ++;
if(count1<index)
{
continue;
}
int count2=0;
while(count2<query)
{
int d,e;
scanf("%d%d",&d,&e);
printf("%d\n",A[d][e]);
count2++;
}
}
// Free the dynamically allocated memory
for(int k = 0; k < index; ++k)
free(A[k]);
return 0;
}
Output (for the input provided):
5
9
Pro-tip: The typical methodology of calling realloc() is to use a specific pointer for the reallocation, test that pointer and, if everything worked out ok, change the old pointer, as explained in Does realloc overwrite old contents?, which I didn't do in that post for the sake of being "laconic".
The C VLA is not suitable here. It seems you need to allocate memory dynamically. The only VLA that can be used is an array of pointers to other arrays. All other arrays should be allocated dynamically.
Something like the following.
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
size_t number_of_arrays;
size_t number_of_queries;
scanf( "%zu%zu", &number_of_arrays, &number_of_queries );
int **a = malloc( number_of_arrays * sizeof( int * ) );
for ( size_t i = 0; i < number_of_arrays; i++ )
{
size_t size;
scanf( "%zu", &size );
a[i] = malloc( size * sizeof( int ) );
for ( size_t j = 0; j < size; j++ ) scanf( "%d", &a[i][j] );
}
for ( size_t i = 0; i < number_of_queries; i++ )
{
size_t array_index;
size_t element_index;
scanf( "%zu%zu", &array_index, &element_index );
printf( "%d\n", a[array_index][element_index] );
}
for ( size_t i = 0; i < number_of_arrays; i++ ) free( a[i] );
free( a );
}
If to input
2 2
3 1 5 4
5 1 2 8 9 3
0 1
1 3
then the program output will be
5
9
As for your code then it is invalid. For example the variable b is not initialized so the declaration of the array has undefined behavior.
int b;
scanf("%d",&b);
int A[index][b];
^^^
Hint : Variable sized arrays need to be dynamically allocated, here's how to it in C
int rows;
scanf("%d",&rows);
//2D array
int**A = malloc(sizeof(int*)*rows); //allocate number of rows
//for each row allocate number of colums
for(int i = 0; i < rows; i++)
{
int cols;
scanf("%d",&cols);
A[i] = malloc(sizeof(int)*cols);
}
I'm using Atom editor (1.24.0 x64), with gpp-compiler (3.0.7, GCC in MinGW). Is there any other additional useful information I can add here about the system environment? By the way, I only have one semester in programming, so I don't know how to debug yet.
Introduction to the problem
I'm trying to sum up the values in a table generated using a 2d array. There are 3 sums in one double while loop. The executed sums are:
All elements in the table are added up. No problem here.
All elements in the same row are added up. Problem here. The returned values are different than the expected. They are different in value and what I think is memory garbage.
All elements in the same column are added up. Problem here too. Same problem as above.
What I expect are the correct values, of course. I really don't know where's the problem. I've already tried different approaches. I can't think on anything more that changing some loops here and there or printing the results to see how the loops are behaving. When I print out the results for the columns and the rows what I've got is what I think are the memory addresses (6487568, etc.).
Results and expected results
Here you can see the results:
2 3 4
5 8 0
7 5 6
The sum of every element in the chart is: 40
The sum of every element per row is:
8 //Should add up to 9
12 //Should add up to 13
4200743 //Should add up to 18
The sum of every element per column is:
15 16 4200611
//Should add up to:
//14 16 10
Code
The problem I think is somewere here:
/*This sums up the the elements, for the entire table,
for every single row and for every single column.*/
while (row < ROWS)
{
column = 0;
while (column < COLUMNS)
{
sum += array[row][column];
sumRow[row] += array[row][column];
sumColumn[column] += array[row][column];
column++;
}
row++;
}
Here's the full code. For some reason the online compiler is not returning the expected result of 40 when adding all the elements, but 29. And the other results are also different.
I've tried the additional approches unsucessfuly:
sum += array[row][column];
sumRow[row][COLUMNS+1] += array[row][column];
sumColumn[ROWS+1][column] += array[row][column];
Another:
sum += array[row][column];
sumRow[row] += array[row][column];
sumColumn[column] += array[row][column];
As a side note: I suspect that it is not allowed to make this type of sum in C, but since I'm just a beginner in programming I really don't know. I've already looked in the internet about if this is possible or not without success.
When an array or matrix is created their elements have a random value. And sumRow[row] += array[row][column]; in first iteration sumRow[row] can non-zero value before summation. So initialize it with zero and it should run fine. Same case with ones too.
It seems you forgot to initialize with zeroes the arrays sumRow and sumColumn.
If the arrays are not Variable Length Arrays then you can initialize them when they are declared. For example
enum { ROWS = 3, COLUMNS = 3 };
int sumRow[ROWS] = { 0 };
int sumColumn[COLUMNS] = { 0 };
Take into account that for accumulators it is better to use the type long long int instead of int,
For example
enum { ROWS = 3, COLUMNS = 3 };
long long int sumRow[ROWS] = { 0 };
long long int sumColumn[COLUMNS] = { 0 };
If the arrays are Variable Length Arrays then you may not initialize them when they are declared. In this case you can use the standard function memset declared in the header <string.h>.
Here is a demonstrative program.
#include <stdio.h>
#include <string.h>
void output_sums( size_t rows, size_t cols, int a[rows][cols] )
{
long long int sumRow[rows];
long long int sumColumn[cols];
long long int sum = 0;
size_t i, j;
memset( sumRow, 0, rows * sizeof( long long int ) );
memset( sumColumn, 0, cols * sizeof( long long int ) );
i = 0;
while ( i < rows)
{
j = 0;
while ( j < cols )
{
sum += a[i][j];
sumRow[i] += a[i][j];
sumColumn[j] += a[i][j];
j++;
}
i++;
}
for ( i = 0; i < rows; i++ )
{
for ( j = 0; j < cols; j++ )
{
printf( "%d\t", a[i][j] );
}
putchar( '\n' );
}
printf( "\nThe sum of every element in the chart is: %lld\n", sum );
puts( "\nThe sum of every element per row is:" );
for ( i = 0; i < rows; i++ )
{
printf( "%lld\n", sumRow[i] );
}
puts( "\nThe sum of every element per column is:" );
for ( j = 0; j < cols; j++ )
{
printf( "%lld\t", sumColumn[j] );
}
}
#define N 3
int main(void)
{
int a[N][N] =
{
{ 2, 3, 4 },
{ 5, 8, 0 },
{ 7, 5, 6 }
};
output_sums( N, N, a );
return 0;
}
Its output is
2 3 4
5 8 0
7 5 6
The sum of every element in the chart is: 40
The sum of every element per row is:
9
13
18
The sum of every element per column is:
14 16 10
EDIT: After you provided a reference to your original code then apart from using non-initialized arrays the size of the arrays are also incorrect:
int sumColumn[2], sumRow[2],
^^^ ^^^
Try not to use magic numbers. Use instaed named constants.
sumRow and sumColumn are not initialized to zero before you start accumulating sums in them
memset() these variables to all zeros before using them
I asked the same problem two times (see here Getting segmentation fault while using malloc ) and improved my code. But I am unable to allocate memory for larger value of m and n . The heart of my code is :
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i,j,n,m,p = 0 ;
int sum[100000] = {0};
scanf("%d%d%d",&n,&m,&p);
/*for ( i = 0 ; i < n ; i++ )
{
for( j = 0 ; j < m ; j++ )
{
a[i][j] = j + 1 ;
}
}*/
int **a = malloc( n * sizeof *a );
for(i=0; i<n; i++)
{
a[i] = malloc( m * sizeof **a);
for(j=0; j<m; j++){
a[i][j] = j + 1 ;
}
}
while ( p-- )
{
//printf("I am in while loop\n");
scanf("%d%d",&i,&j);
{
a[i-1][j-1] += 1 ;
}
}
/*for ( i = 0 ; i < n ; i++ )
{
for( j = 0 ; j < m ; j++ )
{
printf("%d ",a[i][j]);
}
printf("\n");
}*/
for ( i = 0 ; i < n ; i++ )
{
for( j = 0 ; j < m - 1; j++ )
{
p = a[i][j+1] - a[i][j];
if ( p < 0 )
{
sum[i] = -1 ;
break;
}
else
{
sum[i]+=p;
}
//printf("%d ",p);
}
}
for ( i = 0 ; i < n ; i++ )
{
printf("%d\n",sum[i] );
}
return 0;
}
The constraints are:
1 ≤ n, m, p ≤ 10 ^ 5
I am still getting run time error for larger value. I know I am allocating 10 GB of memory at a time, but it is the requirement of the problem. My question is whether it is possible in C to allocate this much memory at a time or not ? If it is possible then please tell me. If not then should I study C++.
Unless I misunderstood the question, you actually need much more than 10GB, don't you? You want to store 10^10 array elements, and each element is the size of a pointer. On a 64-bit system, won't each element be 8 bytes and you will need 80GB of memory rather than 10GB?
The main part of your problem is dealing with an array of (potentially) 100.000×100.000 items. Such big sizes of problems are often found in programming contests. They serve as traps for those who stick to simplistic solutions. When such number appears it usually means one needs to put some effort in optimizing data structures OR algorithm OR ...the problem itself.
You haven't provided the original problem and you try to make others to solve an allocation issue. That seems a kind of X-Y problem to me (see Meta Stack Exchange – What is the XY problem?) — you are struggling to allocate ten billion integer variables, but you didn't check if you actually need them.
Let's see what your program tries to do. First it reads the size of problem: values m and n, which define the array size, and value p which is a number of additional input lines to read. Then it tries to allocate an array and fill its rows with consecutive natural numbers from 1 to m, corresponding to the column number (by mathematical convention those values start form 1, unlike indices in C language, which start from 0).
Next it loads p pairs of indices and for each pair it increments the indicated item of the array.
Then it scans each row of the array, calculates a difference between adjacent items and verifies if the difference is positive or at least zero: if so, it accumulates the calculated difference in a sum[] array, otherwise (that is if the difference is negative) it abandons the row and sets the corresponding sum[i] to -1 to indicate some kind of 'failure'.
Finally it prints the calculated sums.
Now, let's start from the end: do you really need the sum[] array? Well, no, you don't. Each sum is calculated in a single pass along the array's row and then not used anymore. Those sums aren't read nor overwritten, they are not used in any further calculations—they just sit there and wait to be printed. And they eventually get printed in the same order in which the were calculated. So...? So you don't need to store them! Just print each sum as soon as it is calculated and forget it:
for ( i = 0 ; i < n ; i++ )
{
int *row = a[i];
int sum = 0;
for( j = 0 ; j < m - 1; j++ )
{
// calculate and test diff, then...
diff = row[j+1] - row[j];
if ( diff < 0 )
....
else
sum += diff;
}
printf("%d\n", sum); // sum is done
}
Hey, wait... Do you see what your sum is? It's a sum of all diffs, and the sum of diffs is...? It is a difference between the last and the first item! So you don't need to iterate it, just calculate it at once and then decide if the value ought to be cancelled:
for ( i = 0 ; i < n ; i++ )
{
int *row = a[i];
int sum = row[m-1] - row[0];
for( j = 0 ; j < m - 1; j++ )
if ( row[j+1] - row[j] < 0 ) {
sum = -1;
break;
}
printf("%d\n", sum);
}
Okay, that was a minor optimization. Now let's step backwards in the code and ask the next question: — Do you really need the a array? What do you need it for?
— BLAH, what a damn DUMB STUPID QUESTION! you yell, of course I need it! I need it to store my data!
— Oh, really?... And why do you need to store your data, my friend?
— Sigh... I need my data to calculate my results. Can't you see?
Well, see, I can't. Instead I can see you don't need to store your data. At least not all your data.
How do you think, could you calculate your results without the a array in a special case p==0? Of course you could! The a array is initialized in such a way that for every item a[i][j]==j+1, so you know that the difference between every two adjacent items is 1 hence is positive, so the sum in each row is (m-1)*1. And we have calculated that, right now, without using a, right?
And how about p==1? In this case we added 1 to some item in the array. Suppose it was a[3][5]. How did that change the result? First, we know that only the row number 3 was affected. Next, incrementing the item on position 5 increased the difference a[3][5]-a[3][4] and decreased a[3][6]-a[3][5]. So during the last phase we don't need a – if we stored those p data items of increments, we can immediately restore any a[i][j]==j+1 and apply the increments. Again, without actually using the stored values of a, right?
And similary for bigger values p – all you need to store are pairs of indices loaded in while(p--) loop. And that will be at most one hundred thousand items, not ten billion items to store, because p is guaranteed to not exceed 1e5.
Of course there are some additional difficulties in this solution. But they certainly can be solved.
First, you should not scan all (possibly up to 1e5) items on each virtual a[][] access, as that would make the whole program incredibly slow, far beyond what is acceptable. So those '+1' patches should be organized in some fast-access data structure, for example a sorted array for binary search, or a Binary Search Tree, or possibly some hash-map.
Next, when processing the i-th row, you need only patches for that row. So you can keep those increments grouped by i so that you can easily find a bigger group which contains just the portion you need.
Additionally, you might aggregate those data: when you read the same pair of indices, don't store another +1 patch, instead modify the previous patch to +2. That complicates the loading routine a bit, as you need to seek for data and either update what was stored before, or add a new item if not found. However, it saves you unnecessary scanning of the tree or the array for duplicating indices.
Yet another minor optimization: when you scan a row, you use every item twice, once as a the minuend, then as a subtrahend (except the first and last item, which are used only once). So the code might look something like this:
for ( i = 0 ; i < n ; i++ )
{
// int *row = a[i]; // no a[][], no row anymore
int item_last = m + sumOfPatches( i, m-1 );
int item_first = 1 + sumOfPatches( i, 0 );
int sum = item_last - item_first;
int item_prev = item_first;
for( j = 0 ; j < m - 1; j++ )
{
// a[i][j+1] was originally initialized to (j+2)
int item_next = j+2 + sumOfPatches( i, j+1 )
if ( item_next - item_prev < 0 )
{
sum = -1;
break;
}
// the item which is 'next' in current iteration
// will be a 'prev' in the next iteration
item_prev = item_next;
}
printf("%d\n", sum);
}
As a final optimisation you could remove j+2 term from item_next calculation, because this part increases by one for each iteration, so when subtracting item_next - item_prev it reduces just to a constant diffference (j+2)-(j+1) == 1.
The relevant part of source code would then look like:
int patch_last = sumOfPatches( i, m-1 );
int patch_first = sumOfPatches( i, 0 );
int sum = (m + patch_last) - (1 + patch_first);
int patch_prev = patch_first;
for( j = 0 ; j < m - 1; j++ )
{
int patch_next = sumOfPatches( i, j+1 );
if ( 1 + patch_next - patch_prev < 0 )
{
sum = -1;
break;
}
patch_prev = patch_next;
}
HTH (although it's rather 'a very, very late answer'...)
You should test if malloc returns null, it does when it can't alloc.
With a 64 bits operating system and a 64 bits compiler, allocating 10 GB should be possible. Though as you fill-in the memory as you allocate it, you must have at least 10 GB or virtual memory (swap space counts as memory, though this will be slow).
I want to declare a three dimensional array of strings
where each row has two strings.
Here I am able to declare it:
char *szArray[][2] = {
{"string1", "string2"},
{"string3", "string4"},
{"string5", "string6"},
{0, 0}
};
I want to do the same thing but number of rows are dynamically allocated.
Here you can assume 1st dimension is dynamically decided.
2nd dimension is 2,
3rd dimension is 25.
Tried in many ways no luck :(.
Thanks in advance !
First what you have in your question is not a 3-dimensional array of char but a 2-dimensional array of pointers to char. In C, pointers and arrays are not the same thing.
To answer your question, the simplest way in modern C, C99, is to use variable length arrays, VLA, for your purpose. For a 3-dimensional array you'd do
char szData[x][y][z];
where x, y and z are variables or expressions that are only determined at run time when you hit that declaration.
The inconvenience of VLA are that you have to be careful that they don't become too large for your stack, and that you have to initialize them by assignment to the individual entries (here by a nested for-loop).
To stay with your example of 2-d array of strings
char* szData[x][y];
and then you'd have to assign either individual strings to each of the pointers or to set them to 0.
for (size_t i = 0; i < x; ++i)
for (size_t j = 0; j < y; ++j)
szData[i][j] = 0;
int n = 0 ;
printf("Enter the number of rows\n");
scanf("%d",&n);
char *** szData = (char *** )malloc(n * sizeof(char ** )) ;
//Allocate memroy for each row
for(int i = 0 ; i < n ; i++ )
{
szData[i] = (char ** ) malloc(2 * sizeof(char * )) ;
for ( int j = 0 ; j < 2 ; j++ )
{
szData[i][j] = (char *) malloc (25 * sizeof(char));
}
}
//Assign some data
for( int i = 0 ; i < n ; i++ )
{
sprintf(szData[i][0],"string%d", i);
sprintf(szData[i][1],"string1%d", i);
}
//print all the elements
for( int i = 0 ; i < n ; i++ )
{
printf("%s\n",szData[i][0]);
printf("%s\n",szData[i][1]);
}
//free memory here
for(int i = 0 ; i < n ; i++ )
{
for ( int j = 0 ; j < 2 ; j++ )
{
delete szData[i][j];
}
}
for(int i = 0 ; i < n ; i++ )
{
delete szData[i];
}
delete szData;
I didnt get any error:
#include <stdio.h>
int main(){
char *szArray[][2] = { {"string1", "string2"}, {"string3", "string4"}, {"string5", "string6"}, {0, 0} };
printf("%s\n", szArray[0][0]);
printf("%s\n", szArray[2][0]);
}
Here is the output:
$ gcc test.c
$ ./a.exe
string1
string5
But you cannot print szArray[3][0][0] because it is 0, if you want to initialize the value to whatever, you can set to "\0" instead of just 0
Ok, no compiler here to double check, but you can do this a number of ways. The most straight forward would be to declare a Vector of char[25][3] and let c++ do it for you. Something like Vector foo and then just push_back your dynamic elements. Without a compiler though, I'm not 100% certain that this would work as there are funky rules when it comes to multi-dimensional arrays. You can always undimensionalize your array as a first pass just to get it working as well - something like a Vector and start adding how ever you want. You can also do the vector of vector of char approach and have jagged arrays of chars where and of the 3 dimensions can be dynamic, and this would probably even be more memory efficent. Lots of choices here.