Problems with a dictionary implementation in c - c

So, I've been trying to implement a dictionary using an array(still haven't written DiDelete function, not relevant right now), but two problems emerged, here's the code:
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000
typedef int elementtype;
typedef struct{
int last;
elementtype elements[MAX];
}Dictionary;
void DiMakeNull(Dictionary *A)
{
(*A).last = -1;
}
int DiMember(elementtype x, Dictionary A)
{
int f,m,l;
f = 0;
l = A.last;
m = (f+l)/2;
while(f <= l )
{
if( A.elements[m] == x) return 1;
else if( A.elements[m] < x) f = m+1;
else l = m-1;
m = (f+l)/2;
}
return 0;
}
void DiInsert(elementtype x, Dictionary *A)
{
int i = 0,j;
elementtype temp;
while( ((*A).elements[i] < x) && ((*A).last >= i) )
{
i++;
}
for(j = i ; j <= (*A).last; j++)
{
(*A).elements[j+1] = (*A).elements[j];
}
(*A).elements[i] = x;
(*A).last++;
}
int DiEmpty(Dictionary A)
{
if(A.last == -1) return 1;
return 0;
}
void DiPrint(Dictionary A)
{
int i;
printf("Dict:\n");
for(i = 0; i <= A.last; i++)
printf("%d\n",A.elements[i]);
printf("End!");
}
Question 1: why does DiPrint not work? After giving a Dictionary with confirmed numbers in its' array of elements it prints out random numbers. It seems fairly simple, I don't understand what I've gotten wrong there!
Question 2: Why is it, that when a function is e.g.
void function(Dictionary *A)
can't I use the notation A->last, but insted I have to use (*A).last
Thanks in advance!
EDIT: main program looks like this:
#include <stdio.h>
#include <stdlib.h>
#include "atp_dictionary_pomocu_liste.c"
int main()
{
Dictionary A;
DiMakeNull(&A);
DiInsert(4,&A);
DiInsert(3,&A);
DiInsert(32,&A);
DiPrint(A);
return 0;
}

Well I will tell you how I debugged. I like my compiler so I compiled the code.
error: could not convert '& A' from 'Dictionary*' to 'Dictionary'
DiPrint(&A);
^
It said to me that I have type mismatch in DiPrint().
Then three changes and it worked.
void DiPrint(Dictionary* A)
{
int i;
printf("Dict:\n");
for(i = 0; i <= (*A).last; i++)
printf("%d\n",(*A).elements[i]);
printf("End!");
}
And also in answer to your question why do we need to derefence it before using? Because we passed the address of the structure. Unless we dereference it , we won't get the struct instance.
From the comment I again had to rollback the code, we need to pass the structure instance directly and so we did
DiPrint(A);
and
void DiPrint(Dictionary A)
{
int i;
printf("Dict:\n");
for(i = 0; i <= A.last; i++)
printf("%d\n",A.elements[i]);
printf("End!");
}
And this would work without those unary *'s because we are working directly on the structure instance.
Isn't A->last and (*A).last the same thing?
Yes they are. That's why when you call it DiPrint(&A) this function would also work.
void DiPrint(Dictionary* A)
{
int i;
printf("Dict:\n");
for(i = 0; i <= A->last; i++)
printf("%d\n",A->elements[i]);
printf("End!");
}

You have an error in your code; in DiPrint(Dictionary A), your function expects type Dictionary but not type Dictionary *, you need to modify this calling function part in your code, so it would be:
DiPrint(A);
Not
DiPrint(&A);
Or another solution is modifying your function to accept a pointer instead, so it would be:
void DiPrint(Dictionary* A)
{
int i;
printf("Dict:\n");
for(i = 0; i <= (*A).last; i++)
printf("%d\n",(*A).elements[i]);
printf("End!");
}

Related

C how to return arrays from multiple functions?

I am trying to make a program that first creates an array in another function, returns it and then calls another function that shuffles the contents of the array and returns it. However I am struggling to do this in C since I do not quite understand the array pointer system that has to be used here.
So far my code doesnt return the values 1-20 from makeArray() but instead returns an array full of 0s and I have a feeling it has to do with the c's array pointer system.
Any help would greatly be appreciated! Thank you in advance
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int arrShuffle();
int arrShuffle(int * arr) {
int arr[21];
// shuffle array
for(int j=0; j<20; j++) {
int randInd = (rand() % 20) + 1;
int temp = arr[j];
arr[j] = arr[randInd];
arr[randInd] = temp;
}
return arr;
}
int makeArray() {
int arr[21];
// make array of 1-20
for(int i=0; i < 20; i++) {
arr[i] = i + 1;
}
return arr;
}
void main() {
int *orgArr;
int *modArr;
srand(time(NULL));
orgArr = makeArray();
for(int i=0; i < 20; i++) {
printf("OrgArr: %d\n", orgArr);
}
modArr = arrShuffle(orgArr);
}
You cannot use variables with automatic storage (aka local ones). You must allocate the array so the memory remains valid after the function ends:
int* makeArray() {
int *arr = calloc(21, sizeof *a);
// make array of 1-20
for(int i=0; i < 20; i++) {
arr[i] = i + 1;
}
return arr;
}
Remember to release the array when it is no longer used:
int main() {
int *orgArr;
...
orgArr = makeArray();
...
free(orgArr);
}
As tstanisl pointed out in their answer, a possible solution is to use dynamic memory allocation. My answer, instead, will give you yet another solution: using an array passed by the caller.
NOTE: both solutions are valid and their usefulness depends on the specific needs of your program. There's no "right" universal solution.
void makeArray(int arr[], size_t len) {
for (size_t i = 0; i < len; i += 1) {
arr[i] = (int) (i + 1);
}
}
void cloneAndModifyArray(const int orig[], int new[], size_t len) {
for (size_t i = 0; i < len; i += 1) {
new[i] = orig[i] * 2; // or some other modification
}
}
And you use it like this:
#define ARR_LEN (100)
int main(void) {
int arr[ARR_LEN];
makeArray(arr, ARR_LEN);
int modified_arr[ARR_LEN];
cloneAndModifyArray(arr, modified_arr, ARR_LEN);
return 0;
}

Trying to return an Array in C

I've been trying to return an array in C. I'm mostly acquainted with Java (where it's comparatively easier to return an array).
This is what I'm trying to do right now:
#include <stdio.h>
#include <stdlib.h>
int * duplicates(int[],int);
int main() {
int arr[] = {3,5,6,5,9,5,10,11,3};
int n = sizeof(arr)/sizeof(arr[0]);
int * tempArray = duplicates(arr,n);
for (int i = 0; i < n; i++) {
printf("%d \t",tempArray[i]);
}
}
int * duplicates(int arr[], int n) {
int tempArray[n];
int r = 0;
int flag = 0;
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
if (arr[i] == arr[j]) {
for(int k = 0; k < r; k++) {
if(arr[i] == tempArray[k]) {
flag = 1;
}
}
if (flag == 0) {
tempArray[r++] = arr[i];
flag = 0;
} else {
break;
}
}
}
}
return tempArray;
}
And this, to no surprise - crashes my program. How I can return an array in C, because that feels like a bare-minimum, something I should know before I can move further into the language.
Yeah, just allocate the memory like here Returning an array using C
int * duplicates(int arr[], int n) {
int *tempArray;
...
tempArray = (int *)malloc(sizeof(int) * n);
if (tempArray == NULL)
return (NULL);
...
This will work. Google why you should 'dynamically allocate the memory' and 'pointer'.
the array you created inside function duplicate has automatic storage duration since it's on the stack of function unlike in java in which arrays are objects and allocated on the heap. anyway I just wanted to add some NOTE which is don't use VLA(variable length arrays) like int array[n] instead use literals like int array[50] since VLA generate a lot of assembly code(affect performance a tiny bit) and can have security problems like stack overflows or cause the program to crash. Also, not all compilers implement it(portability issues).

Simple c prog. error: invalid type arguement of unary '*'

this is my first post here and I'm very new to C.
I want to write a program that is able to print matrixes. It should look like:
----
-o--
ooo-
----
So i want that to be printed for the beginning.
My current code is:
// 4. Exercise
// Learn 2d arrays
#include <stdio.h>
char z;
char s;
char m1_ptr;
void createMatrix()
{
for(z = 0; z != 4; z++)
{
for (s = 0; s != 4; s++)
{
printf("%c", *m1_ptr);
}
printf("\n");
}
}
//------------------------------------------------------------------
int main()
{
char o = o;
char c = '-';
// And some variables for the matrix count:
char matrix_1 [4][4] ={{c,c,c,c},{c,o,c,c},{o,o,o,c},{c,c,c,c}};
char *m1_ptr = &matrix_1 [z][s];
createMatrix(matrix_1 [0][0]);
/* for(z = 0; z != 4; z++)
{
for (s = 0; s != 4; s++)
{
printf("%c", matrix_1 [z][s]);
}
printf("\n");
}
*/
return 0;
}
It works if I put the void function into the main, but since there are much more matrixes coming I want to do that in an extra function to make it more readable.
If I compile that I get the error message:
"Line17: Error: invalid type argument of unary '*' ('have int')"
(edit: line 17 is where it says "printf("c......")
I looked at other questions, but since I only understand super simple programs yet that didn't work out for me.
Does anyone know how that could be fixed?
(It would be nice if the answer explains why, since I have very little experience with pointers)
I think your looking for something like this:
#include <stdio.h>
#define ROW 4
#define COLUMN 4
void printMatrix(int rowLength, int columnLength, char matrix[rowLength][columnLength]) {
int rowCount, columnCount;
for(rowCount = 0; rowCount < rowLength; rowCount++) {
for(columnCount = 0; columnCount < columnLength; columnCount++)
printf("%c", matrix[rowCount][columnCount]);
printf("\n");
}
}
int main() {
char o = 'o';
char c = '-';
char matrix_1 [ROW][COLUMN] = {
{c,c,c,c},
{c,o,c,c},
{o,o,o,c},
{c,c,c,c}
};
printMatrix(ROW, COLUMN, matrix_1);
return 0;
}
It prints the pattern you want
#include <stdio.h>
void displayMatrix( char pMatrix[rCount][cCount], int rCount, int cCount )
{
for(int i = 0; i < rCount; i++ ) // one loop for each row
{
for (int j = 0; j < cCount; j++) // one loop for each column
{
printf("%c", pMatrix[i][j]);
}
printf("\n"); // prep for next row
}
}
//------------------------------------------------------------------
static const o = 'o';
static const c = '-';
int main()
{
// And some variables for the matrix count:
char matrix_1 [][] ={{c,c,c,c},{c,o,c,c},{o,o,o,c},{c,c,c,c}};
displayMatrix(matrix_1,
sizeof( matrix_1) / sizeof(matrix_1[0]), // = number of rows
sizeof( matrix_1[0]) ); // = number of columns
return 0;
}

C reshape 1d to 2d

I want to reshape an array of length L to one of MxN, however rather than create new memory by copying the elements over in for loops I'd like to do some pointer casting to allow me to access the array with double subscripting (array[X][Y]) .
I've googled around for ages and couldn't find anything helpful.
Any help would really be appreciated.
EDIT: The array of interest is on the heap not stack.
Pointer casting doesn't seem like a good idea here. But if the number of columns is known before run-time, one option I often encounter is to simply define a macro e.g.
#define arrayName(i,j) arrayName[((i)*N) + (j)]
Or
#define ELEMENT(arrayName, i,j) (arrayName)[((i)*N) + (j)]
if you want it to be more flexible.
unions are your friends:
#include <stdio.h>
#define M 5
#define N 4
typedef union {
int a1[M * N];
int a2[M][N];
} U;
int main()
{
U u;
int i, j;
for (i = 0; i < M * N; ++i)
{
u.a1[i] = i;
}
for (i = 0; i < M; ++i)
{
for (j = 0; j < N; ++j)
{
printf("%8d", u.a2[i][j]);
}
printf("\n");
}
return 0;
}
typedefs are your friends:
#include <stdio.h>
#include <stdlib.h>
#define M 5
#define N 4
typedef int Array1D[M * N];
typedef int Array2D[M][N];
int main()
{
Array1D *a1 = malloc(sizeof(*a1));
Array2D *a2 = (Array2D *)a1;
int i, j;
for (i = 0; i < M * N; ++i)
{
(*a1)[i] = i;
}
for (i = 0; i < M; ++i)
{
for (j = 0; j < N; ++j)
{
printf("%8d", (*a2)[i][j]);
}
printf("\n");
}
free(a1);
return 0;
}
Note: above code has now been updated to use heap allocation so as not to break strict aliasing rules.
By the way if you want it super dynamic (as in no sizes are known at compile-time) you can do this by not copying all the values but by creating an index for the 2nd dimension like so:
#include <stdio.h>
#include <stdlib.h>
const int FULL = 100;
const int X = 10;
const int Y = 10;
int *dim1;
int **nested;
int main(void) {
dim1 = malloc(sizeof(int)*FULL);
nested = malloc(sizeof(int*)*X);
for(int i=0; i<X;i++)
{
nested[i] = &dim1[Y*i];
}
dim1[15] = 42;
printf("nested[1][5]: %d",nested[1][5]);
free(nested);
free(dim1);
return 0;
}

C: Function to generate random string and add it to struct

Coming from some experience with Java/C#, I'm struggling to get my head around some parts of C. I have an array of structs. These structs, at the moment, have only one member (I'll be adding others down the track) - an array of chars. This array is a string of 6 characters - two letters, four digits (e.g. XY1234).
The follow code produces the objectCode I'm looking for:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define LETTERS_IN_ALPHABET 26
typedef struct object {
char objectCode[6];
} object_t;
void GetRandomSeed() {
srand((unsigned)time(NULL));
}
char RandomLetter() {
return 'A' + rand() % LETTERS_IN_ALPHABET;
}
int RandomDigit() {
return rand() % 10;
}
int main() {
GetRandomSeed();
object_t object1;
for (int i = 0; i < 2; i++) {
object1.objectCode[i] = RandomLetter();
}
for (int i = 2; i < 6; i++) {
object1.objectCode[i] = '0' + RandomDigit();
}
// Print objectCode string to screen
for (int i = 0; i < 6; i++) {
printf("%c", object1.objectCode[i]);
}
printf("\n");
return 0;
}
I'm trying to wrap the for loops (the ones randomly generating the code) in a function. However, the print out of my attempt to do this is just gibberish:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define LETTERS_IN_ALPHABET 26
typedef struct object {
char objectCode[6];
} object_t;
void GetRandomSeed() {
srand((unsigned)time(NULL));
}
char RandomLetter() {
return 'A' + rand() % LETTERS_IN_ALPHABET;
}
int RandomDigit() {
return rand() % 10;
}
void GenerateCode(object_t object) {
for (int i = 0; i < 2; i++) {
object.objectCode[i] = RandomLetter();
}
for (int i = 2; i < 6; i++) {
object.objectCode[i] = '0' + RandomDigit();
}
}
int main() {
GetRandomSeed();
object_t object1;
// Print objectCode string to screen
for (int i = 0; i < 6; i++) {
printf("%c", object1.objectCode[i]);
}
printf("\n");
return 0;
}
I'm bit of an infant when it comes to C so I really appreciate any help you can give. Thanks.
You're missing the call to GenerateCode on main, that's the reason the print output is gibberish.
However another issue is that on the GenerateCode function, the parameter is by value and the function won't modify the original struct on main. In C, all and every parameters are by value. You should pass a pointer to the struct:
void GenerateCode(object_t* object) {
for (int i = 0; i < 2; i++) {
object->objectCode[i] = RandomLetter();
}
for (int i = 2; i < 6; i++) {
object->objectCode[i] = '0' + RandomDigit();
}
}
int main() {
// ...
object_t object1;
GenerateCode(&object1);
}
Because you pass in an object by value to GenerateCode() the function modifies only the value on the stack (ie: the parameter itself), not the actual object you want to change. use a pointer:
void GenerateCode(object_t* object) {
for (int i = 0; i < 2; i++) {
object->objectCode[i] = RandomLetter();
}
for (int i = 2; i < 6; i++) {
object->objectCode[i] = '0' + RandomDigit();
}
}
and call it like:
GenerateCode(&object1);

Resources