Exercise with array and pointer - arrays

I am a beginner in C. I want to write a function to return an array containing all elements common to two given arrays containing distinct positive integers.
Sample input/output is in the following table:
|input parameters | return |
| ---------- | -------- |
|{1, 8, 3, 2}, {4, 2, 6, 1} | {1, 2} |
|{1, 8, 3, 2, 6}, {2, 6, 1} | {2, 6, 1} |
|{1, 3, 7, 9}, {7, 1, 9, 3} | {1, 3, 7, 9}|
|{1, 2}, {3, 4} | {} |
|{}, {1, 2, 3} | {} |
|{1, 2}, {} | {} |
|{1, 2}, null | null |
|null, {} | null |
|null, null | null |
int f(int first[], int second[], int first_len, int second_len, int result_len)
{
if (first == NULL || second == NULL)
{
return NULL;
}
if (first_len == 0 || second_len == 0) return malloc(0);
int min = (first_len < second_len) ? first_len : second_len;
int *a, *b;
if (min == first_len)
{
a = first;
b = second;
}
else
{
a = second;
b = first;
}
int *c = malloc(min);
int k = 0;
for (int i = 0; i <sizeof(*a); i++)
{
for (int j = 0; j < sizeof(*b) ; j++)
{
if (a[i] == b[j])
{
c[k] = a[i];
k++;
}
}
}
int *retArray = malloc(k * result_len);
result_len = sizeof(retArray)/sizeof(*retArray);
for (int t = 0; t < result_len; t++)
{
retArray[t] = c[t];
}
return retArray;
}
int main()
{
int first[] = {1,3,8,9};
int second[] = {3,5,8};
int result_len;
int first_len = sizeof(first)/sizeof(*first);
int second_len = sizeof(second)/sizeof(*second);
printf("%d\n", f(first,second,first_len,first_len,result_len));
return 0;
}
This code doesn't give the result that I need can anyone help me out?

Without discussing the actual algorithmic exercise, the confusion here seems to be in the return type. You can't return more than one value in C code. The value can however be struct or a pointer to allocated memory. Code is worth a thousand words so consider the following example:
#include <stdio.h>
#include <stdlib.h>
void foo(char *arr)
{
// fill the given memory location with requested data
arr[0] = '4';
arr[1] = '2';
arr[2] = '0';
// note absent or empty return;
}
int main()
{
// allocate some space for return value
char *arr = malloc(3 * sizeof(char));
// tell the function where to store the result by passing the arr pointer
foo(arr);
// the function has filled the array with some data
printf("%c%c%c\n", arr[0], arr[1], arr[2]);
// don't forget to free the allocated memory when it's no longer in use
free(arr);
return 0;
}
This technique is generally called 'returning by reference', as you are using a reference (pointer) to return the data as opposed to 'returning by value' when you directly return the number (or other data type).
You can of course also allocate the new block of memory in the function and then return the pointer like so:
char *foo()
{
char *arr = malloc(3 * sizeof(char));
// fill with requested data
return arr;
}
Although this makes it easier to forget to free the memory IMO.

Related

pointer to pointer as 2d array

My background is Java therefore I'm not used to pointers, the following code throws error and I can't see way:
#include <stdio.h>
#define DIM 2
void sort_intervals(int** intervals, int n);
int main()
{
int a[3][DIM] = {
{1, 6} ,
{4, 9} ,
{3,17} };
sort_intervals(a, 3);
return 0;
}
void sort_intervals(int** intervals, int n)
{
printf("%d ", intervals[0][0]);//<--- error here
}
Error: Access violation reading location
I'm not allowed to change the function signiture
Then you need an array of pointers that point to arrays.
int a_1[DIM] = {1, 6};
int a_2[DIM] = { ... };
int a_3[DIM] = { ... };
int *a[3] = { a_1, a_2, a_3, }; // array of 3 pointers
sort_intervals(a, 3);
or exactly equivalent using compound literals you can:
int *a[3] = { (int[DIM]){1, 6}, (int[DIM]){2, 7}, (int[DIM]){3, 17}};
sort_intervals(a, 3);
even:
sort_intervals((int*[3]){
(int[DIM]){1, 6},
(int[DIM]){2, 7},
(int[DIM]){3, 17},
}, 3);
I am assuming you can change main function.
You could also initialize a as double pointer such as:
int **a = (int**)calloc(3, sizeof(int*)); //setting a as array of 3 pointers
for (int i = 0; i < 3; i++)
*a = (int*) calloc(DIM, sizeof(int)); //assigning pointer to a[0], a[1] and a[2]
Here a is array of 3 integer pointers. a[0],a[1] and a[2] are int pointers.
You can modify a as a[0][0] = 5;
If you can't change the signature as you explained in your comment, then you can get it done using a jagged array:
#define DIM 2
void sort_intervals(int** intervals, int n);
int main()
{
int **a = malloc(3 * sizeof(int*));
for (int i = 0; i < 3; i++) {
a[i] = malloc(DIM * sizeof(int));
}
a[0][0] = 1; a[0][1] = 6;
a[1][0] = 4; a[1][1] = 9;
a[2][0] = 3; a[2][1] = 17;
sort_intervals(a, 3);
for (int i = 0; i < 3; i++) {
free(a[i]);
}
free(a);
return 0;
}
void sort_intervals(int** intervals, int n)
{
printf("%d ", intervals[2][0]);//<--- error here
}

Search in array of char* in c

I am trying to work out what is wrong with the process of scanning the char* star value.
struct Property {
unsigned int shift;
int mask;
char * str[4];
}
human [] = {
{0, 1, {"fe", "ma"}},
{1, 1, {"du", "cl"}},
{2, 1, {"nh", "ha"}},
{3, 1, {"sk", "tr"}},
{4, 3, {"bn", "rd", "bw", "bk"}},
{6, 3, {"bu", "ge", "gy", "da"}},
};
int find(char* w){
int i;
int j;
for (i = 0; i < (sizeof(human)/ sizeof(struct Property)); i++){
for (j = 0; j < 4 ; j++){
if (human[i].str[j] == w)
return i;
}
}
}
int main(){
char* w ;
scanf("%s", w);
int k = find(w);
printf("k is %d", k);
return 0;
}
Clion compiler says that 'pointer parameter w can be pointer to const'. So in my main() I tried to use my function scanning w as array or char*.
Upd with suggestions.
struct Property {
unsigned int shift;
int mask;
char * st[4];
} human [] = {
{0, 1, {"fe", "ma"}},
{1, 1, {"du", "cl"}},
{2, 1, {"nh", "ha"}},
{3, 1, {"sk", "tr"}},
{4, 3, {"bn", "rd", "bw", "bk"}},
{6, 3, {"bu", "ge", "gy", "da"}},
};
int find(char* w)
{
int i;
int j;
for (i = 0; i < (sizeof(human)/ sizeof(struct Property)); i++)
{
for (j = 0; j < 4 ; j++)
{
if ((strcmp(human[i].st[j], w)) == 0)
return i;
else
continue;
}
}
return -1;
}
int main()
{
char* w = malloc(sizeof(char*));
scanf("%99s", w);
int k = find(w);
if (k != -1 )
printf("k is %d", k);
if (k == -1) { printf("%s","Error");}
return 0;
}
Still no output.I truly believe, that something is still wrong
There are couple of problems -
Allocate memory to w. Other wise passing an uninitialized pointer to scanf is Undefined behavior. (You can allocate the memory dynamically too)
char w[100];
if( scanf("%99s",w) != 1 ){
/* Handle error */
}
Comparing two strings can be done using strcmp. Using == operator is not the correct way.
if ( strcmp(human[i].str[j], w) == 0 )
Also you should always return something from the function. It is supposed to return something even if nothing matches. But you didn't follow that contract. Compiler complained.
for(..){
...
}
return -1; /* denoting invalid index - search failed*/
You can easily make the argument passed as const char * because you are not changing it's value (the content of the string).

Can I use pointer to print out arrays of int array just like arrays of string?

If I want to print out array of string like:
char juices_A[][12] = { "dragonfruit", "waterberry", "sharonfruit", };
I can simply use juices_A[0],juices_A[1],juices_A[3], respectively as a pointer to string "dragonfruit", "waterberry", "sharonfruit", and print them out.
But what if I want to print out array of int array like:
int data[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
I can not simply use data[0],data[1],data[2] as pointer to { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, I need to adopt a more complicated way to print them out. I need to use loop inside loop. So I want to know why I can not use pointer in the int situation? I read on book "Array variables are like pointers.." so I assume int array variable data[0],data[1],data[2] are also like pointers...
#include <stdio.h>
int main() {
int i_A = 0;
char juices_A[][12] = { "dragonfruit", "waterberry", "sharonfruit", };
for (; i_A < 3; i_A++)
printf("%s;", juices_A[i_A]);
puts("");
int i_B = 0;
int data[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
for (; i_B < 3; i_B++) {
int i_C = 0;
for (; i_C < 3; i_C++)
printf("%i,", data[i_B][i_C]);
printf(";");
}
return 0;
}
the result is:
dragonfruit;waterberry;sharonfruit;
1,2,3,;4,5,6,;7,8,9,;
You can use access arrays like pointers and vice versa.
Here's the output from the program below:
dragonfruit;waterberry;sharonfruit;
{ { 1, 2, 3, }, { 4, 5, 6, }, { 7, 8, 9, }, }
Here's a modification to your code:
#include <stdio.h>
#define ROW_WIDTH 3
#define TABLE_HEIGHT 3
int main(void) {
char *juices[] = { "dragonfruit", "waterberry", "sharonfruit", };
int data[TABLE_HEIGHT][ROW_WIDTH] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
for (int n = 0; n < ROW_WIDTH; n++)
printf("%s;", juices[n]);
int *ip = (int *)data;
printf("\n{ ");
for (int i = 0; i < TABLE_HEIGHT; i++) {
printf("{ ");
for(int j = 0; j < ROW_WIDTH; j++) {
printf("%d, ", *ip + ((i * ROW_WIDTH) + j));
}
printf("}, ");
}
printf("}\n");
return 0;
}
Strings:
-------------------------
|h | e | l | l | o | \0 |
-------------------------
|w | o | r | l | d | \0 |
------------------------
As you see this array can be stored in a 2D char array
char a[2][6];
Now a[i] gives the starting address of each row and %s prints out a string until a \0 is enountered so you can just pass the address of each row and get the contents of the row. Just like
char *p = "hello";
printf("%s\n",p);
Note:
Again if you want to read the character at a particular location you need to specify a[row][col]
Whereas
Integers:
----------------
|1 | 2 | 3 | 4 |
----------------
|5 | 6 | 7 | 8 |
----------------
Now you can have a array like
int b[2][4];
b[i] will give you the starting address of each row but in order to get the value stored in a particular location you need to specify value with b[row][col].
The difference is the sentinel condition for valid C strings is \0 and is it being used to access each row which is not the case for integers.
so I assume int array variable data[0],data[1],data[2] are also like
pointers
Yes they are pointers to each row but you need to dereference the pointer to get the value right? So if data[0] is a pointer then do data[0][column]
The char juices_A[][12] = { "dragonfruit", "waterberry", "sharonfruit" }; whenever the data is accessed it prints till \0 is reached, as strings are considered only till \0. So when we use juices_A[0] it points to start of first data till \0 is reached.But to get an individual char we need to mention both the dimensions of the array.
char juices_A[1][2] to access 't' in waterberry
But this is not the case with int as each is considered as separate entity. So we use both dimensions of the array to access it.
Even if we reduce the size of the array like char juices_A[][12] = { "dragon", "waterberry", "sharonfruit" }; when printed it outputs
dragon;waterberry;sharonfruit
But in the case of int data[3][3] = { { 1, 2}, { 4, 5, 6 }, { 7, 8, 9 } }; it outputs
1,2,0,....`
this makes the difference
#include <stdio.h>
int main()
{
int data[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int *ptr;
int lines = 3;
int columns = 3;
int i;
ptr = &data[0][0];
while (lines-- > 0) {
i = columns;
while (i-- > 0) {
printf("%d ", *ptr);
ptr += 1;
}
putchar('\n');
}
return 0;
}
or:
#include <stdio.h>
int main()
{
int data[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int *ptr;
int lines = 3;
int columns = 3;
int max = lines * columns;
ptr = &data[0][0];
while (max-- > 0) {
printf("%d ", *ptr);
ptr++;
if (max % columns == 0)
putchar('\n');
}
return 0;
}

Array of arrays, with different sizes

I'm having an array, that has arrays in every cell. For example, the big array is called arr:
int a[3] = {3, 2, 1};
int b[2] = {2, 1};
int *arr[2] = {a, b}
Now the problem is, if I want to print the small arrs, inside the big array.
Here is my code:
#include <stdio.h>
void printArr(int arr [], int n)
{
for (int i = 0 ; i < n ; i++)
{
printf("%d ", *(arr + i));
}
printf("\n");
}
int main()
{
int a[5] = {1, 8, 4, 2, 0};
int b[3] = {1, 4, 2};
int *arr [2] = {a, b};
int n = 0;
for (int i = 0 ; i < 2 ; i++)
{
printArr(*(arr + i), n);
}
}
The output is supposed to be something like this:
1 8 4 2 0
1 4 2
But I can't get the size of each array, since sizeof(*(arr + i) gives me 4, which is the size of the pointer (the name of the array), and not all the array it self.
So what can I do?
Thanks!
The Problem:
The C language only provides a way of finding the size of types.
This gives the subtle differences between applying sizeof to:
1) An array of a type such as:
int a[3];
sizeof(a); // => 3 * sizeof(int)
2) A pointer to the type:
int *ptr;
sizeof(ptr); // => sizeof(int *)
or
int a[3] = {3, 2, 1};
int b[2] = {2, 1};
int *arr[2] = {a, b};
sizeof(arr[1]); // => sizeof(int *)
Some solutions:
Store the size
As jfly proposes store the size of the arrays.
Makes finding the size a constant time operation.
Append an end marker
Adding a end marker like '\0' as used for c-style strings.
You might use INT_MAX or INT_MIN in this case.
The printArr implementation would need to change to:
void printArr(int *arr)
{
int *it = arr;
while(arr != INT_MIN);
{
printf("%d ", *it);
}
printf("\n");
}
Disadvantages:
Finding the size of the array requires iterating over the full array.
Gives the risk of an actual value colliding with the end marker value.
Advantages:
The varying sized array can be passed as a single argument.
Using iterators
Store the pointer to the first and one past the last value.
void printArr(int *begin, int *end)
{
for (int *it = begin; it != end; it++)
{
printf("%d ", *it);
}
printf("\n");
}
int *end_arr[2] = {a + 3, b + 2};
for (int i = 0 ; i < 2 ; i++)
{
printArr(arr[i], end_arr[i]);
}
Can be extended to other data structures.
Since arr is an array of pointers, so you can't get the size of array from the pointer which points to an array, you need additional size info:
int size_arr[2] = {sizeof(a) / sizeof(int), sizeof(b) / sizeof(int)};
for (int i = 0 ; i < 2 ; i++)
{
printArr(arr[i], size_arr[i]);
}

value of pointer to a char array vs plain char pointer

I am having a hard time understanding where I can use a pointer to an array,
e.g: char (*a)[10];.
So two basic questions.
Please give me a simple example of how just a pointer to an array can be used in C code.
Why would one use it as apposed to just declaring a variable as a pointer and then incrementing/decrementing the address after that point.
Say you have a database query that returns a set of strings. Further, say that you know that these strings are no longer than 9 characters in length. Only, you don't know how many elements are in the set returned by the query.
char (*a)[10] = malloc( NumRecords * sizeof *a );
if ( a == NULL )
{
/* Handle error appropriately */
return EXIT_FAILURE; /* Naive */
}
for ( i = 0 ; i < NumRecords ; ++i )
{
assert(strlen(DbRecordSet[i]) < 10);
strcpy(a[i], DbRecordSet[i]);
}
Example: how to print the elements of an array of num_row rows and 3 columns:
#include <stdio.h>
#define NUM_ROW(x) (sizeof (x) / sizeof *(x))
// print elements of an array of num_row rows and 3 columns
void print(int (*a)[3], size_t num_row)
{
size_t num_col = sizeof *a / sizeof **a;
for (int i = 0; i < num_row; i++) {
for (int j = 0; j < num_col; j++) {
printf("%d\n", a[i][j]);
}
}
}
int main(void)
{
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
int b[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print(a, NUM_ROW(a));
print(b, NUM_ROW(b));
return 0;
}
Any time you pass an expression with a multi-dimensioned array type to a function, you're going to be working with a pointer to an array:
int a[10][20];
foo(a);
void foo(int (*p)[20]) // or int p[][20]
{ ... }

Resources