Function call problem in data structure learning - c

function call in data structure
I want to delete the i-th element in the sequence table, and delete it by calling my own defined DelList function in the main function, but after compiling, I can't print out the value of the deleted element as expected.
The code before line 48 works fine, but it seems that the DelList function cannot be called, resulting in no deleted elements being printed.
Is there a problem with calling the DelList function? Or is there a problem with the return of the DelList function?
Thank you
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
#define OK 1
#define ERROR 0
typedef int ElemType; /*Assume that the data elements in the sequence table
are integers*/
typedef struct {
ElemType elem[MAXSIZE];
int last;
}SeqList;
int DelList(SeqList *L, int i, ElemType *e)
/*The i-th data element is deleted in the sequence table L, and its value is returned with the pointer parameter e. The legal value of i is 1 ≤ i ≤ L. last +1 */
{
int k;
if ((i < 1) || (i > L->last + 1))
{
printf("Deleting the location is not legal!");
return(ERROR);
}
*e = L->elem[i - 1]; /* Store the deleted element in the variable pointed to by e*/
for (k = i; i <= L->last; k++)
L->elem[k - 1] = L->elem[k]; /*Move the following elements forward*/
L->last--;
return(OK);
}
void main()
{
SeqList *l;
int p, r;
int *q;
int i;
l = (SeqList*)malloc(sizeof(SeqList));
q = (int*)malloc(sizeof(int));
printf("Please enter the length :");
scanf("%d", &r);
l->last = r - 1;
printf("Please enter the value of each element:\n");
for (i = 0; i <= l->last; i++)
{
scanf("%d", &l->elem[i]);
}
printf("Please enter the location of the element you want to delete:\n");
scanf("%d", &p);
DelList(l, p, q);
printf("The deleted element value is:%d\n", *q);
}
Compile can pass but not the result I want

There is a small typo causing grief:
for (k = i; i <= L->last; k++) {
// ^
Here, the k index is being incremented, but not being tested against the end of the array. After writing past the end of the array, the behavior is undefined.
Change this line to:
for (k = i; k <= L->last; k++) {
// ^
Additional remarks:
I recommend using SeqList.length instead of SeqList.last. Iterating from i <= last is much less natural than i < length. One-indexing adds to the cognitive load--you can decrement user input to normalize it before sending it into your function, which can then operate on a zero-indexed array.
Consider using dynamic memory to avoid the fixed size of the array, especially if you're taking the data from I/O. At minimum, add a bounds check to avoid overflowing the buffer.
Consider using a doubly linked list if you're planning on performing frequent deletions in the middle of the list. Array deletions other than the furthest-right element are O(n), while a doubly linked list can do it in O(1). The drawback is no random access and some overhead associated with creating nodes.
Use descriptive variable names. l, p, r, q are only going to frustrate debugging efforts.
Use #include <stdbool.h> instead of #DEFINE OK 1.
Unless you're on an old compiler, variables need not be declared at the top of scopes.
No need to cast the result of malloc() (although I realize this question started out tagged C++).
Always free allocated memory. You can declare l and q on the stack and use the & reference operator to pass the address into functions.
Use int main() and return 0; from it to notify the shell that your program successfully terminated.
Here's a possible re-write that addresses some of these points:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *data;
int length;
} SeqList;
bool list_delete(SeqList *list, int idx_to_remove, int *removed_element) {
if (idx_to_remove < 0 || idx_to_remove >= list->length) {
return false;
}
*removed_element = list->data[idx_to_remove];
list->length--;
for (int i = idx_to_remove; i < list->length; i++) {
list->data[i] = list->data[i+1];
}
return true;
}
int main() {
SeqList list;
int deleted_element;
int idx_to_delete;
printf("Please enter the length: ");
scanf("%d", &list.length);
list.data = malloc(sizeof(int) * list.length);
for (int i = 0; i < list.length; i++) {
printf("Enter the value for element %d: ", 1 + i);
scanf("%d", &list.data[i]);
}
do {
printf("Please enter the index of the element you want to delete: ");
scanf("%d", &idx_to_delete);
} while (!list_delete(&list, idx_to_delete - 1, &deleted_element));
printf("The deleted element value is: %d\n", deleted_element);
puts("The elements left in the list are:");
for (int i = 0; i < list.length; i++) {
printf("%d ", list.data[i]);
}
puts("");
free(list.data);
return 0;
}
Sample run:
Please enter the length: 4
Enter the value for element 1: 11
Enter the value for element 2: 22
Enter the value for element 3: 33
Enter the value for element 4: 44
Please enter the index of the element you want to delete: 6
Please enter the index of the element you want to delete: -1
Please enter the index of the element you want to delete: 5
Please enter the index of the element you want to delete: 4
The deleted element value is: 44
The elements left in the list are:
11 22 33

Related

0 in The Array is Causing a Semantic Error. How to Overcome?

The question is to make a program to read an integer array from the user and pass it to a function that takes two arrays - the first array with the values obtained form the user and the second array as an empty array. The objective is to append the indices of the even numbers present in the original array to the empty array and return the number of even numbers present in the original array.
If the input was:
Enter number of elements: 5
Enter element [1]: 0
Enter element [2]: 1
Enter element [3]: 2
Enter element [4]: 3
Enter element [5]: 4
Then the output shows:
37945345.
which is a garbage value inside the empty array's first element.
This is the code:
#include <stdio.h>
int evenIndices(int origArr[], int emptyArr[]) {
int i = 0, j = 0;
int evenCount = 0;
while (origArr[i] != '\0') {
if (origArr[i] % 2 == 0) {
emptyArr[j] = i;
evenCount ++;
j++;
}
i++;
}
return evenCount;
}
int main() {
int numOfElts;
printf("Enter number of elements: ");
scanf("%d", &numOfElts);
int arr[numOfElts];
for (int i = 0; i < numOfElts; i++) {
printf("Enter element [%d]: ", i + 1);
scanf("%d", &arr[i]);
}
arr[numOfElts] = '\0';
int indexArr[numOfElts];
int evenCount = evenIndices(arr, indexArr);
printf("There are %d even numbers. \n", evenCount);
printf("*** Indices With Even Numbers in Original Array *** \n");
for (int i = 0; i < evenCount - 1; i++) {
printf("%d, ", indexArr[i]);
}
printf("%d. \n", indexArr[evenCount - 1]);
return 0;
}
This code works for all numbers in array except for 0. If 0 is entered, the function assumes that it is same as '\0' and quits the loop. What is the solution to this?
For starters this assignment statement
arr[numOfElts] = '\0';
invokes undefined behavior because there is an access of memory beyond the array because the valid range of indices for the array is [0, numOfElts).
Remove this statement.
The function evenIndices should be declared like
int evenIndices( const int origArr[], int n, int emptyArr[]);
That is you need to pass the number of elements in the original array. And the first parameter should be declared with the qualifier const because the passed array is not changed within the function.
The condition in the while loop
while (origArr[i] != '\0') {
does not make a sense. The user can enter 0 as a valid value of the source array.
One of these variables, j and evenCount, is redundant.
The function can be defined the following way
int evenIndices( const int origArr[], int n, int emptyArr[])
{
int evenCount = 0;
for ( int i = 0; i < n; i++ )
{
if ( origArr[i] % 2 == 0 ) emptyArr[evenCount++] = i;
}
return evenCount;
}
And the function is called like
int evenCount = evenIndices( arr, numOfElts, indexArr );
Pay attention to that if the function returns 0 then this code snippet
for (int i = 0; i < evenCount - 1; i++) {
printf("%d, ", indexArr[i]);
}
printf("%d. \n", indexArr[evenCount - 1]);
will produce an invalid output. There is no need to split the for loop. Instead write
for (int i = 0; i < evenCount; i++) {
printf("%d, ", indexArr[i]);
}
putchar( '\n' );
You are trying to use '\0' as a sentinel. Thus you cannot have '\0' or '0' ('\0' is 0) as a valid value. I would recommend that you use INT_MIN as the sentinel. Then your range of acceptableinputs will be 2^32-1 to -(2^32-1) and that will be nice.
"pass it to a function that takes two arrays"
To pass arrays, the size information must be included in some way as array parameters in C decay into simple pointers, losing all array size information. The following method makes use of the VLA parameter format, i.e. define the size(s) of the array(s) you are passing prior to the array(s) themselves in the prototype...
Change the prototype from:
int evenIndices(int origArr[], int emptyArr[]);
To:
int evenIndices(int x, int y, int origArr[x], int emptyArr[y]);
Then pass it as:
int evenCount = evenIndices(numOfElts, numOfElts, arr, indexArr);
Or, because the size of both arrays sizes in this case is the same, you can define a single int x in the prototype,
int evenIndices(int x, int origArr[x], int emptyArr[x]);
then pass it as:
int evenCount = evenIndices(numOfElts, origArr, emptyArr);

Unexpected output of a growing dynamic array

I am attempting to create a dynamic array that will grow in size if needed, as I don't know how large the array will actually be. My code seems to work until the 8th element of the array where I start to see very large incorrect values that I did not enter. Not sure why this is happening.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char** argv)
{
int val;
int userInput;
int* arr;
int size = 1;
int arrIndex = 0;
arr = (int*) malloc(sizeof(int) * size);
/* prompt the user for input */
printf ("Enter in a list of numbers to be stored in a dynamic array.\n");
printf ("End the list with the terminal value of -999\n");
/* loop until the user enters -999 */
scanf ("%d", &val);
while (val != -999)
{
if (arrIndex >= size)
{
size++;
}
arr[arrIndex] = val;
arrIndex++;
/* get next value */
scanf("%d", &val);
}
int j = 0;
for(j = 0; j < size ; j++)
{
printf("%d \t", arr[j]);
}
}
The size of the array remains 1 and doesn't increase while incrementing size variable.
Your code worked until 8th element because adjacent memory after the array upto 7th element must be free.
In C array index out of bound is not checked and it is programmers responibility.
if you want to increase or decrease size of array you can use realloc inside while loop:
arr=(int*)realloc(arr,sizeof(int)*size);
Also Correct this if condition in your code initially arrayindex is 0 and size is 1 which results in false.
if (arrIndex >= size)
{
size++;
}

Binary search not returning the position

this code is used to create an array filled with 10 random integers. It sorts the array and then inputs the array into a binary search function. I do not get the position of where my search key is positioned.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int binary_search(int array[], int search, int strt, int ending)
{
int middle;
middle = (strt + ending)/2;//splitting the array in half to compare the search key
if (search > array[middle]){binary_search(array, search, middle + 1, ending);}
else if(search == array[middle])
{
printf("Your search key is indicated in %d position the array Ferrari\n", middle + 1);
return middle;
}
else{binary_search(array, search, strt, middle -1);}
return -1;
}
int main()
{
srand(time(NULL));//random number seed generator
int Ferrari[10];
int size = 10;
int selection;
int temporary = 0;//I'm using this variable to store
//the value returned from linear_search()
int start = 0;
int end;
int i;
//this is to generate a random number between 0 and 101
for(int i=0; i<10; i++) {Ferrari[i] = rand() % 100 + 1;}
//printing the initial array
printf("\nThe array Ferrari consists of -> ");
for(int i=0; i<10; i++){printf("%d, ", Ferrari[i]);}
//--------------------------SORTING--------------------------------------------
for(int f = 0; f < (size - 1); f++)
{
for(int kk = 0; kk < (size - 1 - f); kk++)
{
if(Ferrari[kk] > Ferrari[kk +1])
{
int Te_mP;
Te_mP = Ferrari[kk + 1];
Ferrari[kk+1] = Ferrari[kk];
Ferrari[kk] = Te_mP;
}
}
}
//----------------------------------------------------------------------------
//printing the array after it has been sorted
printf("\n");
printf("\nThe sorted array Ferrari consists of -> ");
for(int i=0; i<10; i++){printf("%d, ", Ferrari[i]);}
start = 0;
end = i -1;
//this will be used to implement the searching algorithm
printf("\n\n");
printf("Please enter a number to test if it is included in the array or not\n");
scanf("%d", &selection);
temporary = binary_search(Ferrari, selection, start, end);
return 0;
}
I keep getting the answer that the search key is positioned in ``0 of array Ferrari. How do I resolve this?
Please let me know what I'm doing wrong over here. Much appreciated.
Look at this line
end = i - 1;
Where is i initialized?
In your loop you have
for(int i=0........
Note by giving int i=0 it means you are creating a new variable i within the for block. So this doesn't alter your original i variable declared at the top. Try using end = size - 1 or it's a best practice to define a constant for this purpose.
#define ARR_SIZE 10
in loop
for(i=0; i<ARR_SIZE;i++)
Then initialize end = ARR_SIZE -1;
And one more thing in your binary_search function is that you don't handle the case when the key is not present in the array.
Something like
if(end==start && array[end] != search)
return -1;
This checks when the search space has only one element and that is not your search element, it means it doesn't exist so we return -1.
Hope this helps
The problem is occurring because you are using uninitialised variable i here:
end = i -1;
Note that the scope of variable i declared in loop init clause is different from the scope of variable i declared in function block.
for(int i=0; i<10; i++){
^^^^^^^
// The scope of i declared in loop init clause is limited to the loop.
To fix the problem, you can use the i declared at function block scope as the loop variable, like this
for(i=0; i<10; i++){
Now, after the loop finishes, the variable i will hold its last value until it's value explicitly modify. But using i to identify the size of array down the code may cause several problems as it is not tightly coupled with the size of array and i may be get modified by other part of code. So, it is not the right idea to use i to identify the size of array.
Since, you are having a variable size which hold the size of array Ferrari, you can do:
end = size - 1;
No need to have another variable to keep the track of size of array. The problem with this is that you have to keep updating the size whenever you change the array size. An alternative of this would be to use a macro to define the array size.
The most appropriate way to set the end of array would be:
end = (sizeof(Ferrari) / sizeof(Ferrari[0])) - 1;

What is wrong with my hash function?

I'm trying to create a hash table. Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define N 19
#define c1 3
#define c2 5
#define m 3000
int efort;
int h_table[N];
int h(int k, int i)
{
return (k + i*c1 + i*i*c2) % N;
}
void init()
{
for (int i = 0; i < N; i++)
h_table[i] = -1;
}
void insert(int k)
{
int position, i;
i = 0;
do
{
position = h(k, i);
printf("\n Position %d \n", position);
if (h_table[position] == -1)
{
h_table[position] = k;
printf("Inserted :elem %d at %d \n", h_table[position], position);
break;
}
else
{
i += 1;
}
} while (i != N);
}
void print(int n)
{
printf("\nTable content: \n");
for (int i = 0; i < n; i++)
{
printf("%d ", h_table[i]);
}
}
void test()
{
int a[100];
int b[100];
init();
memset(b, -1, 100);
srand(time(NULL));
for (int i = 0; i < N; i++)
{
a[i] = rand() % (3000 + 1 - 2000) + 2000;
}
for (int i = 0; i < N ; i++)
{
insert(a[i]);
}
print(N);
}
int main()
{
test();
return 0;
}
Hash ("h") function and "insert" function are took from "Introduction to algorithms" book (Cormen).I don't know what is happening with the h function or insert function. Sometimes it fills completely my array, but sometimes it doesn't. That means it doesn't work good. What am I doing wrong?
In short, you are producing repeating values for position often enough to prevent h_table[] from being populated after only N attempts...
The pseudo-random number generator is not guaranteed to produce a set of unique numbers, nor is your h(...) function guaranteed to produce a mutually exclusive set of position values. It is likely that you are generating the same position enough times that you run out of loops before all 19 positions have been generated. The question how many times must h(...) be called on average before you are likely to get the value of an unused position? should be answered. This may help to direct you to the problem.
As an experiment, I increased the looping indexes from N to 100 in all but the h(...) function (so as not to overrun h_table[] ). And as expected the first 5 positions filled immediately. The next one filled after 3 more tries. The next one 10 tries later, and so on, until by the end of 100 tries, there were still some unwritten positions.
On the next run, all table positions were filled.
2 possible solutions:
1) Modify hash to improve probability of unique values.
2) Increase iterations to populate h_table
A good_hash_function() % N may repeat itself in N re-hashes. A good hash looks nearly random in its output even though it is deterministic. So in N tries it might not loop through all the array elements.
After failing to find a free array element after a number of tries, say N/3 tries, recommend a different approach. Just look for the next free element.

function to perform bubble sort in C providing unstable results

I am participating in Harvard's opencourse ware and attempting the homework questions. I wrote (or tried to) write a program in C to sort an array using bubble sort implementation. After I finished it, I tested it with an array of size 5, then 6 then 3 etc. All worked. then, I tried to test it with an array of size 11, and then that's when it started bugging out. The program was written to stop getting numbers for the array after it hits the array size entered by the user. But, when I tested it with array size 11 it would continuously try to get more values from the user, past the size declared. It did that to me consistently for a couple days, then the third day I tried to initialize the array size variable to 0, then all of a sudden it would continue to have the same issues with an array size of 4 or more. I un-did the initialization and it continues to do the same thing for an array size of over 4. I cant figure out why the program would work for some array sizes and not others. I used main to get the array size and values from the keyboard, then I passed it to a function I wrote called sort. Note that this is not homework or anything I need to get credit, It is solely for learning. Any comments will be very much appreciated. Thanks.
/****************************************************************************
* helpers.c
*
* Computer Science 50
* Problem Set 3
*
* Helper functions for Problem Set 3.
***************************************************************************/
#include <cs50.h>
#include <stdio.h>
#include "helpers.h"
void
sort(int values[], int n);
int main(){
printf("Please enter the size of the array \n");
int num = GetInt();
int mystack[num];
for (int z=0; z < num; z++){
mystack[z] = GetInt();
}
sort(mystack, num);
}
/*
* Sorts array of n values.
*/
void
sort(int values[], int n)
{
// this is a bubble sort implementation
bool swapped = false; // initialize variable to check if swap was made
for (int i=0; i < (n-1);){ // loops through all array values
if (values[i + 1] > values [i]){ // checks the neighbor to see if it's bigger
i++; // if bigger do nothing except to move to the next value in the array
}
else{ // if neighbor is not bigger then out of order and needs sorting
int temp = values[i]; // store current array value in temp variable for swapping purposes
values[i] = values[i+1]; //swap with neighbor
values[i+1] = temp; // swap neighbor to current array value
swapped = true; // keep track that swap was made
i++;
}
// if we are at the end of array and swap was made then go back to beginning
// and start process again.
if((i == (n-1) && (swapped == true))){
i = 0;
swapped = false;
}
// if we are at the end and swap was not made then array must be in order so print it
if((i == (n-1) && (swapped == false))){
for (int y =0; y < n; y++){
printf("%d", values[y]);
}
// exit program
break;
}
} // end for
// return;
}
You can easily use 2 nested for loops :
int i, j, temp ;
for ( i = 0 ; i < n - 1 ; i++ )
{
for ( j = 0 ; j <= n - 2 - i ; j++ )
{
if ( arr[j] > arr[j + 1] )
{
temp = arr[j] ;
arr[j] = arr[j + 1] ;
arr[j + 1] = temp ;
}
}
}
also you should now it's a c++ code not a c, because c doesn't have something like :
int mystack[num];
and you should enter a number when you're creating an array and you can't use a variable (like "int num" in your code). This is in C, but in C++ you're doing right.
The first thing to do when debugging a problem like this is ensure that the computer is seeing the data you think it should be seeing. You do that by printing out the data as it is entered. You're having trouble with the inputs; print out what the computer is seeing:
static void dump_array(FILE *fp, const char *tag, const int *array, int size)
{
fprintf(fp, "Array %s (%d items)\n", tag, size);
for (int i = 0; i < size; i++)
fprintf(fp, " %d: %d\n", i, array[i]);
}
int main(void)
{
printf("Please enter the size of the array \n");
int num = GetInt();
printf("num = %d\n", num);
int mystack[num];
for (int z = 0; z < num; z++)
{
mystack[z] = GetInt();
printf("%d: %d\n", z, mystack[z]);
}
dump_array(stdout, "Before", mystack, num);
sort(mystack, num);
dump_array(stdout, "After", mystack, num);
}
This will give you direct indications of what is being entered as it is entered, which will probably help you recognize what is going wrong. Printing out inputs is a very basic debugging technique.
Also, stylistically, having a function that should be called sort_array_and_print() suggests that you do not have the correct division of labour; the sort code should sort, and a separate function (like the dump_array() function I showed) should be used for printing an array.
As it turns out the reason why it was doing this is because when comparing an array's neighbor to itself as in:
if (values[i + 1] > values [i])
The fact that I was just checking that it is greater than, without checking if it is '=' then it was causing it to behave undesirably. So if the array is for example [1, 1, 5, 2, 6, 8] then by 1 being next to a 1, my program did not account for this behavior and acted the way it did.

Resources