I have a structure in C which contains an array on which I perform stack operations.
If the stack is full, I need to prevent pushing an element past the end of the array, and return an error condition.
Is it better style to include the size of the stack as an element of the structure, and pass that number of elements to the stack_push() function, or should I have a sentinel element at the end of the stack array?
How are you going to implement your stack_push() function?
If it requires scanning to the end of the array looking for an empty slot to insert the pushed element into, then you need a sentinel value anyway (e.g., NULL, if the array contains pointer elements). But note that the algorithm is going to be O(N).
On the other hand, keeping track of the number of active elements within the array allows your algorithm to be O(1) for pushes (and also for pops). It also saves you the trouble of allocating one extra element in the array, which may be significant if it's an array of structs.
Generally speaking, most stack data structures are implemented using an array and a counter.
What sentinel value would you use? Of course, you have to be sure that the caller of this function will definitely never use this value. It could be very confusing to debug if your function is stopping prematurely at a sentinel value that seems like a reasonable input.
For things like strings, it is easy to use a NULL to terminate because a string should never have a zero byte. However, if you start using sentinels in some places and not in others, it can start to get very confusing for developers that are trying to use your code.
I would say to use a size argument unless there is a VERY clear and obvious choice of sentinel, and probably not even then.
Related
So I want to create some functions that take arrays as input, but I don't know how many dimensions the array will have.
Is there a way in c to determine how many dimensions an array has? (ideally as a function)
So this is actually a fairly difficult problem in C. Usually this is solved using one of three ways:
Have a special terminating value, like '\0' for strings
Pass the dimensions of the array as a parameter to whatever function you're using
Keep the pointer of the array and its dimension in a struct together
If I remember correctly, there's a way to figure out the size of an allocated array using *nix systems, but I definitely would not recommend doing this. Just keep track of your allocated memory.
Iv'e been given a mission to implement a dynamic queue in c language without any loops and any recursion.
the queue should contain the next function: installation, destruct, add, remove and peek.
I thought to make a link structure, that way each link will have a pointer the next link and so on..but the problem is that I don't know how to do the destruct function without any loops, the only solution I can think of is making a loop that will send each one of the links to the remove function(but again, I need to it without any loops). Is their any possibility to do the destruct function without any loops?
p.s the destruct function should free all of the memory that we used for the queue.
If a recursing function doesn't count as a loop for your constrains, you could use recursion to traverse the list and destroy the items.
Another approach is to store items in an array, and maintain a pointer into the array for the head and tail of the queue. Destroying the queue just means freeing the array or resetting the head/tail pointers, and no loops would be required.
There's no real need to make a queue based on a linked list, it would have all the downside of random allocated elements and lack of spatial locality, would be relatively harder to debug, and won't use the main benefit of a linked list (insertion at O(1)) since it's a queue with only one insertion point anyway (or 2 for a double-ended one).
Instead you could use an array, and maintain a head and tail index variables, use cyclic incrementation when they wrap around at the end, and reallocate when required. If the queue holds basic data types this would also allow you to deallocate the entire queue in one go, just free the array (although for elements you had to manually allocate, I can't see any way to avoid iterated removal, unless you move to c++).
I am assuming that the item to be inserted in memory is of constant size. If needed, it could be a pointer to a block of memory. In that case, you can use a circular buffer with a head and tail pointer. When either pointer "gets to the end of the block" it should wrap - i.e. you increment / decrement modulo queue size.
Initialization:
Create a memory space of finite size (max size of the buffer)
Add:
Update memory location at the current tail (if add to end)
or head (if add to beginning), and update the tail/head pointer.
Remove:
Read the data at the head/tail, and update the pointer
Peek:
Read the data at the head/tail, and don't move the pointer
Destruct:
Free the memory block
No loops, no recursion. It uses the fact that a FIFO buffer only allows changes at the beginning / end of the queue- it is not possible to remove elements "in the middle".
If the head and tail pointers meet, the queue is "full". In that case, the "insert" function should return an error, unless you add a "insert destructively" flag that says "overwrite the oldest element". That seems beyond the scope of your homework, but it is important in real life applications. Sometimes you care about the oldest data - at other times you care about the latest data. But usually, if your queue is filling up, there is a problem with the over all system design (you didn't scale the process that empties the queue to deal with the rate at which it is filling, basically).
Note - if each element in the queue is a pointer to dynamically allocated memory you WILL need to iterate over all elements to free that memory, or you will create a memory leak. But if the queue is of constant size, this is not needed. Given the constraints given, and the lack of specification that queue element size should be variable, I would recommend you write your solution for a fixed size queue element.
I asked a previous question about declaring an array in a for loop, e.g.
for(i=0;i<=1000;i++){
float arrayone[(length[i])];
do a bunch of other stuff
}
Basically, I'm trying to do an array whose length can be varied based on what step the program is on. I don't want to keep the array data saved permanently (like arrayone[][]), since it's big and there's lots of steps.
So I was told it's legal to declare the array only within this scope like this. But will it try to store 1000 copies of the array by the end, which I don't want? I'm a beginner, so I don't understand the nuances of what the blocks really do.
The alternative for me is just to make an array outside of the loop which has the maximum length ever needed, and to overwrite that at every step.
Edit: The use for the array is: I have a global array. The arrays in the loop are filled with function results using that global array, to save computing. The arrays get manipulated,...,...,and finally are used to change the global array. Then they're not needed anymore.
But will it try to store 1000 copies of the array by the end, which I don't want?
No, at the beginning of each iteration a new array will be allocated, and, since the array goes out of scope at the end of the iteration, at that time it will be deallocated, so only one array exists at one time.
That is the point of automatic variables (which that array is). At the end of the scope in which they are declared (usually but not always delimited by braces) they are automatically deallocated.
After each iteration of your loop is done all the variables that were declared inside your loop will be destroyed, including your array. So only one copy of your array will be kept.
That being said, however, you should know that initializing the array outside your loop is probably better, because you won't have to allocate memory on the stack every iteration.
If you were dynamically allocating your array (which you're not in your example) like this:
for(i=0;i<=1000;i++){
float * arrayone = (float*)malloc(i * sizeof(float));
}
then you have a problem. Here the local variable is the pointer, which when it gets destroyed you can no longer access the memory you allocated. This is the case where you would end up with 1000 different arrays in memory at once. You could free your memory before the pointer is destroyed, but I maintain that having the array declared outside the loop is still better.
How to know whether an array is initialized in C ? Functions like strlen() are not helping me as I dont want to know whether the array is empty or not.
There's no way to test that at runtime -- an uninitialized array looks just like one that has been initialized with garbage.
Depending on what you're doing, you need either to make sure the array is actually initialized or explicitly pass around a flag that tells you whether the values in the array are meaningful yet.
Also note that "whether the array is empty" is not a very meaningful concept in C. The array is just there, and it always contains whatever number of bits are necessary to represent the elements it's declared to have. Those bits may not have meaningful values, but the're always there.
You can't by using programmatic language features.
But you can by design and discipline. At declaration time set your array as a pointer to NULL.
Then make a function to assign both memory and value to your pointer and a corresponding freeing function to destroy it when is not needed anymore, setting it to NULL again. And then making every function that processes check for NULL as an error condition.
To do bounds recognition, set the last element to NULL.
Example:
char* myArray=NULL;
/* other code */
myArray = createMyArray(n_elements);
memset(myArray,0,sizeof(int)*n_elements); /* Set the allocated memory to zero */
/* other code */
myArray[0]=functionReturningAString();
myArray[n_elements-1]=functionReturningAnotherString();
/* other code */
/*Processing*/
char* incr=myArray;
while( incr != NULL){
processArray(incr);
incr++;/* Increments by size of char pointer to the next pointer*/
}
free_Array(&myArray);/* this function calls free() and sets myArray to NULL*/
This is usable, when you need a lot of efficiency. Otherwise you should either create your own arraylist or use an existing library which provides it.
You need too much discipline to keep track of every possible error condition, so it can be tiresome.
Usually is just better to just use a library which provides arraylist, linkedlist, HashSets, etc. For C I use a lot of Glib functions for this.
what is the difference between array and list?
In C, an array is a fixed-size region of contiguous storage containing multiple objects, one after the other. This array is an "object" in the meaning which C gives to the word - basically just some memory that represents something. An object could just be an int.
You can distinguish slightly between array objects, and array types. Often people use array objects which are allocated with malloc, and used via a pointer to the first element. But C does also have specific types for arrays of different sizes, and also for variable-length-arrays, whose size is set when they are created. VLAs have a slightly misleading name: the size is only "variable" in the sense that it isn't fixed at compile time. It can't change during the lifetime of the object.
So, when I say an array is fixed-size I mean that the size cannot change once the array is created, and this includes VLAs. There is realloc, which logically returns a pointer to a new array that replaces the old one, but can sometimes return the same address passed in, having changed the size of the array in place. realloc operates on memory allocations, not on arrays in general.
That's what an array is. The C programming language doesn't define anything called a list. Can't really compare something which is well defined, with something that isn't defined ;-) Usually "list" would mean a linked list, but in some contexts or in other languages it means other things.
For that matter, in other languages "array" could mean other things, although I can't immediately think of a language where it means anything very different from a C array.
If your question really has nothing to do with C, and is a language-agnostic data-structures question, "what is the difference between an array and a linked list?", then it's a duplicate of this:
Array versus linked-list
There is no such thing as a standard list in C. There is such a thing in C++, where it is implemented as a double-linked list.
The main differences are that arrays have random access - you can access any member of the array in O(1) time (i.e. if a was an array, a[4]) and have a pre-set size at compile time. Linked lists have sequential access - to access an element, you have to loop through the list until you get to the element you want (i.e. if b was a linked list, to get to the 5th element of b you would have to iterate through elements 0, 1, 2, 3 and 4), and the size can be grown and shrunk dynamically.
Although there is nothing like a list in C per se but you sure could be talking about a linked lists implementation.
Array: Random access, predefine size.
Linked List: Sequential access, size at runtime.
Other languages like, say Python, may have have both lists and arrays inbuilt and their meaning may differ.
Useful comments from below:
You could add array lists. Lists which internally is an array which is doubled when needed and halved when only 1/4 full. This gives O(1) for add, remove, get(index) amortized. – lasseespeholt
Python's list is not a linked list. And the distinction between Python list and array is list can store anything while array can only store primitive types (int, float, etc). – KennyTM
For array, it has a fixed size like we write, new int [100]
but list does not have a fixed size...it can go on and on
Insertion and Deletion is easier in list than in array
Reason: we can simply use to change the pointers to insert and delete for linked list but for array insert and deletion needs shiftRight and shiftLeft
Linked List uses a dummy head node to avoid special cases of inserting into an empty list, or removing the last node from a list of unit size; and, it uses double links to allow iterating in both directions. The cost of course is the extra space needed to hold the dummy node (minimal cost), and the extra previous link in addition the usual next link for each node (much more significant cost).
In array, we can add with the help of its random access
In Linked list, reference to the tail node is simply header.prev, which gives us ability to append to the list in constant time (without having to iterate to find the tail reference, or having to maintain a separate tail reference).
But in array, we need to re-size the array before inserting.
Array has the flexibility to attain random access unlike Linked List.
Linked list has problems like,
It consumes extra memory storage for the pointer we are using!
Time complexity of O(n) instead of O(1) like in array
Reverse traversing is difficult for singly linked list and if we use doubly linked list, another pointer means more of extra memory storage
Heap Restriction as well! Memory is allocated only if there is space available in the heap. If insufficient memory then memory won't be created.
Array has problems like,
a chance of memory wastage or shortage.
Hope this helps ! :)
An often under appreciated characteristic of Linked data structures is that you can use them in situations where memory is highly fragmented due to there being no contiguous memory guarantee between elements. For example you could have 100MB of free space but only say a maximum run of free memory of length 10MB. In this case you can only create an an array of size 10MB but perhaps a potentially larger linked list since you would be able to make use of every run of free memory which was large enough to contain a single node.
array has only similar data types(i.e.,) they are homogeneous in nature. we can only have an array of strings , integers etc. also the size of array is predefined.
but in the case of list we can have any type of elements. let it be a string integer or combination of both.Also null or duplicate elements are allowed in list. example of list include arraylist , linkedlist.here in list the size can grow or shrink at any time.