Brandon Kennedy's Fall 2011 Opus
Welcome!
This shall be from here-on-out the Opus of Brandon Kennedy!!! I am in my 3rd computer science semester at CCC, currently enrolled in:
I also tutor at the MLC in Elmira on tuesday and wednesday from 4-8, and thursday 4-6, come visit!!!
These last few weeks of class have been crazy. Over the summer my programming was lacking in quantity so it was that much harder to transition into this semester. But i was able to catch up and even learn about these few things already!
Some topics that i am having a lot of trouble understanding are:
There is not much to linked lists, i understand the concept of tmp → next = start or a line like such. But when to put which line, and the order of the commands is quite confusing to me!!!!!
I am pretty sure that the linked lists light buld just clicked! For my class project in data structures i am creating a linked list implementation using characters. It will have several different functions that will be in several different files, all used as a library.
I have to say that at first i was skeptical, but as i progressed the deffinitions started to help. Every deffinition I have done so far has helped me learn something. Whether it is a small syntax issue, or a major use issue where i didn't even know that certain function/use existed! So far i have done:
One thing that puzzles me now is still linked lists!!! I now have to remove a whole list, and deallocate the memory it was using, kinda hard for me. an example of what i am trying is below:
deletelist(Node *thing, Node *stop) //function must be passed the first and last node in the list { if(thing = stop) { free(thing); } else { Node *test; test = (Node *) malloc (sizeof(Node)); while(thing != stop) { test = thing -> next; thing -> next -> prev = NULL; thing -> next = test; free(thing); thing = next; } free(stop); free(test); free(thing): } }
And i used to think that a library was that place down the street where nerds banded together to feel safe… But they are so much more!!! We have been working with librarys in not just Data Structures, but discrete structures aswell, and i am so glad we have! There are a lot of lessons to learn from library building. Like for instance:
A pointer is a variant of a data type that deals with location. A pointer “points to” a storage address. So if you reference a storage address, call it address A, and that address contains another storage address, say address F, address A is then a pointer to address F.
in the program below, c is a pointer to a.
#include <stdio.h> int main() { int a=5; int b=7; int c; int d; c=a; d=b*c; printf("%d\n", d); return(0); }
Not all variables are automatically allocated. The following kinds of variables are statically allocated:
Statically allocated variables have their storage allocated and initialized before main starts running and are not deallocated until main has terminated.
String constants (except those used as initializers for variables of type array of char) are statically allocated. In most expressions a string constant generates a pointer to the first char in the string.
#include <stdio.h> int main(void) { char s[] = "dog"; char *e = "food"; printf("A %s eats %s\n", s, e); return 0; }
The problem with static allocations is that the programmer must know before hand how much data the program will need to handle. So he or she must make a guess at the largest possible amount of data that could be used. Dynamic allocation is the automatic allocation of memory in C/C++, Unlike declarations, which load data onto the programs data segment, dynamic allocation creates new usable space on the programs STACK.
{ #include<stdio.h> int main() int *array; array=(int *) malloc(size*sizeof(int)); return 0; }
Version control is simply the management of changes to files, documents, programs many other types of information stored as computer files. This is widely used by large programming teams where many people edit the same file. Bugs or features of the software are often only present in certain versions because of the fixing of some problems and the introduction of others as the program develops. Therefore, for the purposes of fixing bugs, it is very important to be able to retrieve and run different versions of the software to determine in which version(s) the problem occurs.
A few functional uses of version control are:
An array is a is a data type that can be indexed. It is described as a collection of elements, or information segments. An array is storage of any data type. arrays can contain integers, pointers and characters, and in that sence, can contain strings. For this example we will focus on integers.
Notice the below array is defined as data type “int” then a name with an array symbol after it “[]” containing the word size which is equal to an integer. This creates an array with 20 “sections” or “segments” for information to be stored. As i said above, arrays can be indexed, meaning they are in an order, and you can move about that array to store/retrieve data. you do this by use of the array symbol “[]”.
An array starts at the numeric index of 0, meaning it contains the sections 0-19. If you want to access the 4rth item of data, or fourth integer stored in the array, you would use list[3] because location 3 is the fourth space when you start at 0.
int size = 20; int list[size]; size[3] = 46; printf("%d", size[3]);
This example will save 46 in the array position 4 and then print out the contents of array position 4, which will be 46.
Pointer arithmetic is like moving about an array. An array can be defined in another way than by use of the array symbol []. It can be defined in another way, like this:
int *list; list = malloc(sizeof(char)*50);
int *array; *(list+1) = 34; *(list+5) = 4; for(i=5;i<0;i--) { *(list+i) = 3+i } printf("%d", *(list+1));
This will save 34 into the array, allong with many other pointer arithmetic operations, and then print out the contents of that array position. Moving about an array in this manner is called “Pointer Arithmetic”.
Numeric and character.
Variables are memory locations that are given names and can be assigned values. Variables are used to store different types of data in memory for future use.
Numeric types have several subtypes like integers or real values. characters are letters and ASCII symbols. Here is a list of data types and their range. (this list assumes signed integers)
These values are all relative to the operating system, as is the same for the size. A char is typically one byte but may not always be. Programmers should always use the sizeof() function to determine the size of the variable type they wish to use.
example:
int main() { int a = sizeof(int); int b = sizeof(short); int c = sizeof(char): printf("%d\n", a); printf("%d\n", b); printf("%d\n", c); return 0 }
Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.
If you want to demonstrate something on the command-line, you can do so as follows:
lab46:~$ cd src lab46:~/src$ gcc -o hello hello.c lab46:~/src$ ./hello Hello, World! lab46:~/src$
When you dynamically allocate memory in a program you have to deallocate it once you are done.
by use of C
free(num); free(ch) free(db);
by use of C++
delete number; delete ch; delete db; If you allocate memory and do not deallocate it, you can cause memory leaks.
CProgramming.com states: A function pointer is a variable that stores the address of a function that can later be called through that function pointer. This is useful because functions encapsulate behavior. For instance, every time you need a particular behavior such as drawing a line, instead of writing out a bunch of code, all you need to do is call the function.
Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.
If you want to demonstrate something on the command-line, you can do so as follows:
lab46:~$ cd src lab46:~/src$ gcc -o hello hello.c lab46:~/src$ ./hello Hello, World! lab46:~/src$
Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.
If you wish to aid your definition with a code sample, you can do so by using a wiki code block, an example follows:
/* * Sample code block */ #include <stdio.h> int main() { return(0); }
Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.
If you want to demonstrate something on the command-line, you can do so as follows:
lab46:~$ cd src lab46:~/src$ gcc -o hello hello.c lab46:~/src$ ./hello Hello, World! lab46:~/src$
Gets or extracts data from a file opened by an executing program. The information is stored in the buffer and used by the program, then the next read continues from where the last stopped. This continues to the Eod Of File flag or untill the file is closed.
In order for the system or a program to access or affect nother program during execution first the file must be opened by the program being executed.
After an executing program has finished with a file, and before run completion, any file which was opened by the program needs to be closed. This is done with the file close command.
File access can be dictated and restricted on an individual, group, and global scope. The abilities to read, write, and execute a file can each be set at each of these levels.
File Write puts data into a file. It can create a file if it doesn't already exist, and can append to or replace an existing file.
Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.
If you want to demonstrate something on the command-line, you can do so as follows:
lab46:~$ cd src lab46:~/src$ gcc -o hello hello.c lab46:~/src$ ./hello Hello, World! lab46:~/src$
Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.
If you wish to aid your definition with a code sample, you can do so by using a wiki code block, an example follows:
/* * Sample code block */ #include <stdio.h> int main() { return(0); }
Also called an IPC socket, a Unix domain socket is an endpoint for data communications that allows processes operating in the same system to exchange data. The APL for these sockets is similar to an internet socket, meaning the processes don't have to have the same ancestry.
These sockets are usually found on POSIX operating systems.
Coroutines are a pretty cool thing. As far as i've read they generalize subroutines like generators do, but are more powerful. They allow lots of entry points for suspending and resuming at different points.
The C programming guide says that Coroutines are best used when implementing components such as iterators, infinite lists, cooperative tasks and pipes.
Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.
If you wish to aid your definition with a code sample, you can do so by using a wiki code block, an example follows:
/* * Sample code block */ #include <stdio.h> int main() { return(0); }
Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.
If you want to demonstrate something on the command-line, you can do so as follows:
lab46:~$ cd src lab46:~/src$ gcc -o hello hello.c lab46:~/src$ ./hello Hello, World! lab46:~/src$
Choose the appropriate data structure for solving a given problem.
I will do this by comming up with a simple, but applicable problem in code, and applying a data structure to resolve this prolem.
This objective took me about 30 minutes to complete, I took not one, but two cases where a data structure needed to be implemented, and in both cases i was able to effectively, efficiently and quickly come up with a data structure/structures to solve each problem. The actual soving of each problem took seconds to think up, and seconds to minutes to code.
I believe that based on my ability to quickly and effectively solve these data structure problems, I completed this objective perfectly.
I would also say that this objective could be altered just a little bit to give room for a small example of what we did for the objective, maybe asking for code if applicable, or some other type of example. If not, then this objective was very effective in helping me understand the reasoning behind this course.
Discuss the representation and use of primitive data types and built-in data structures
I will research primitive data types and built-in-structures to determine their formal definition and a few examples, i will then bring that data before another individual to discuss the use of primitive data types and built-in-structures to help myself and the other individual better learn the uses and need for primitive data types and built-in-structures.
This objective took me roughly 4-5 hours to complete, I reserched many of these data types and structures, and presented the information before an individual who proceeded to discuss and explain a few of these in depth. I now plan to record the use of these structures as learned in class and review them in a drive to better understand the representation and use of primitive data types and built-in-structures.
Primitive data types:
Built-in-structures:
and many others.
I believe that yet again i achieved a very good understanding of the course objective and put a lot of effort into this objective. I believe it was done effectively and well and since there is much room for improvement with these topics, it is a good thing the class is only 25% done!
Describe common applications for each data structure described in class
As each data structure appears, i will ask questions and record programs and applications of each data structure that is given in class in an attempt to have each of the structure described to me in an understandable way.
So far so good, I have had linked lists explained to me in many ways by recording programs and using them to ask multiple questions to ensure that i understand the data structure that was being taught.
The method used to complete this objective seems to be an effective one. It falls in line with my teachers objectives for the course and for our learning and has so far provided much valid information reguarding the data structures being taught. I believe it will continue to be an effective method of learning that will help not only me, but others to convert to this style aswell.
better understand file I/O for efficient data processing
State the method you will use for measuring successful academic/intellectual achievement of this objective.
Follow your method and obtain a measurement. Document the results here.
Reflect upon your results of the measurement to ascertain your achievement of the particular course objective.
Can you enter an integer into the command line to be saved as argv[x] when argv[] is defined as data type char? What will happen when you try to print?
I do not think the desired integer will be printed out unless the argv[x] is cast to an integer because argv has been defined as data type char.
I will test this hypothesis by writing a small program to receive command line arguments. I will then print out a character to show that the program works properly, and then i will receive and print an integer saved under the same data type.
#include<stdio.h> int main(int argc,char **argv) { printf("The character argument entered is:%s\n", argv[1]); return 0; }
lab46:~/src/DataS/Project1$ ./experiment1 y The character argument entered is:y lab46:~/src/DataS/Project1$ ./experiment1 r The character argument entered is:r lab46:~/src/DataS/Project1$ ./experiment1 U The character argument entered is:U
As you can see above, the program receives a character and then prints that character out, with no problems.
#include<stdio.h> int main(int argc,char **argv) { printf("The character argument entered is:%s\n", argv[1]); return 0; }
lab46:~/src/DataS/Project1$ ./experiment1 35 The character argument entered is:35 lab46:~/src/DataS/Project1$ ./experiment1 3 The character argument entered is:3 lab46:~/src/DataS/Project1$ ./experiment1 5 The character argument entered is:5
As you can see above, the program receives an integer and then prints that integer out, with no problems.
#include<stdio.h> int main(int argc,char **argv) { int a=5; //new line int b; // new line printf("The character argument entered is: %s\n", argv[1]); b = (a + *argv[1]); // new line printf("The results of our arithmetic: %d\n", b); // new line return 0; }
lab46:~/src/DataS/Project1$ nano experiment1.c lab46:~/src/DataS/Project1$ gcc -o experiment1 experiment1.c experiment1.c: In function 'main': experiment1.c:8: error: invalid operands to binary * (have 'int' and 'char *') lab46:~/src/DataS/Project1$ nano experiment1.c lab46:~/src/DataS/Project1$ gcc -o experiment1 experiment1.c experiment1.c: In function 'main': experiment1.c:8: warning: assignment makes integer from pointer without a cast lab46:~/src/DataS/Project1$ nano experiment1.c lab46:~/src/DataS/Project1$ gcc -o experiment1 experiment1.c lab46:~/src/DataS/Project1$ ./experiment1 5 The character argument entered is: 5 The results of our arithmetic: 58
Based on the added arithmetic operation: b = 5 + 5, (The first 5 is the value of a, the second 5 is the command line argument), we see that 5 + 5 = 58???.
Based on the data collected:
Based on the experiment above, integer values can be saved into a character array, and printed directly from that array, but not manipulated without a cast. The reason for this is:
lab46:~/src/DataS/Project1$ gcc -o experiment1 experiment1.c experiment1.c: In function 'main': experiment1.c:8: error: invalid operands to binary * (have 'int' and 'char *')
This compiler error shows that an invalid operands to binary * was going on on line 8. Which when counted, is the line the code: b = (a + argv[1]) (at that point of compiling) was placed. This means that the integer was saved in the array with a binary representation that was not accessable by regular arithmetic means. But, the printing statement could print the integer because the binary given to the array was the same as what was printed out of the array, so the conversions in and out of the array were the same, and the integer could be expressed.
As i now understand, an integer can be saved into a character array via command line arguments, and printed with no errors, but not manipulated, which is wher ei was stuck. I had believe that the integer could not be manipulated or printed.
What is the question you'd like to pose for experimentation? State it here.
Collect information and resources (such as URLs of web resources), and comment on knowledge obtained that you think will provide useful background information to aid in performing the experiment.
Based on what you've read with respect to your original posed question, what do you think will be the result of your experiment (ie an educated guess based on the facts known). This is done before actually performing the experiment.
State your rationale.
How are you going to test your hypothesis? What is the structure of your experiment?
Perform your experiment, and collect/document the results here.
Based on the data collected:
What can you ascertain based on the experiment performed and data collected? Document your findings here; make a statement as to any discoveries you've made.
What is the question you'd like to pose for experimentation? State it here.
Collect information and resources (such as URLs of web resources), and comment on knowledge obtained that you think will provide useful background information to aid in performing the experiment.
Based on what you've read with respect to your original posed question, what do you think will be the result of your experiment (ie an educated guess based on the facts known). This is done before actually performing the experiment.
State your rationale.
How are you going to test your hypothesis? What is the structure of your experiment?
Perform your experiment, and collect/document the results here.
Based on the data collected:
What can you ascertain based on the experiment performed and data collected? Document your findings here; make a statement as to any discoveries you've made.
Ahh, the sweet smell of victory! On this sixth day of october i have already finished all 12 of my data structures keywords for this month!!! I have learned a LOT about sorting algorithms, and i am so ready to ask a lot of questions requarding sorting, especially selection sorting.
I am also working on 2 other programming projects. One is a doubly linked list implementation that is not going well, and the other is a String difference function that i now have to delete 3/4 of what i wrote because appearently, i took it out of context… I made the function to:
i guess it was a little much…
Just finished coding Projects 2 and 3, also known as queue and stack. Pretty simple concepts, deffinitely fundamental to more advanced lists. The main things that i walked away from this project with are a better understanding of the ar command, and the creation of libraries.
On a side note, i want the old journals back… Whereas opuses are a great was organize your current projects and journal entries, they seem to be taking away from the great deffinition / learning time that we spent in class in C.
Running in circles in dicrete, trying to finish this program, writing this library, understanding what the heck we are trying to accomplish! Then bam! Joe hits us with a program. We are going to take all of the functions we are trying to write and try to build a card game. We are going to use these broad functions to write a texas hold'em poker game. We are currently writing the game in a very high level pseudo code, so high we are outlining like such:
We are establing a rough list of major functions before breaking them down into smaller groups to get specific. After we have finished this major outline we will move into the functions individually and define elements like:
As this Opus is wrapping itself up, this will be my last edition to to it. I have finished:
Over the past week I have been studying concurrency based on forking. We are currently discussing forking in class through a half written program provided by matt. He is going to show us the functionality of the concept, and then let us loose on the code so that we can experiment and learn through trial and error. It is an awesome concept, really makes me wonder about Asynchronous I/0. I'd love to see a real-time application of the fork function in a already written and working program.
Enqueuing is most easily express through an example of a coffee shop. Since we all know that coffee shops always have a line, picute this! enqueuing is like someone walking up to the end of the line. yep, that's pretty much it!
example of enqueuing below.
enqueue(&Q, (rand() % 100) + 1); /* Fill with random numbers from 1 to 100 */
Queues are common in computer programs, where they are implemented as data structures coupled with access routines, as an abstract data structure or in object-oriented languages as classes. Common implementations are circular buffers and linked lists.
Since most arrays are limited in space, queuing and dequeuing become very useful when editing them.
Dequeuing can also be expressed via a coffee shop, so imagine you are standing in line. You walk to the counter and order a caramel cappacino, pay, and leave the line. As soon as you have left the front of the line, you have dequeued.
unsigned int k = 0; while (k < 100) { enqueue(&Q, (rand() % 100) + 1); /* Fill with random numbers from 1 to 100 */ ++k; } k = 1; while (!queue_empty_p(&Q)) { int data; dequeue(&Q, &data); printf("(%d) %d\n", k, data); ++k; }
Queues are common in computer programs, where they are implemented as data structures coupled with access routines, as an abstract data structure or in object-oriented languages as classes. Common implementations are circular buffers and linked lists.
Since most arrays are limited in space, queuing and dequeuing become very useful when editing them.
A queue is a collection of items or data that are kept in a specified order and the principal operations performed on the collection are the addition and subtraction from the front and end of a line. A queue can be expressed as a singly linked list. As i said in other examples, a queue is like a line, you can leave the front, or join the back.
struct queue_node { struct queue_node *next; int data; }; struct queue { struct queue_node *first; struct queue_node *last; };
This code may look familiar, that is because it is a linked list, a singly linked list to be exact.
Buffer overrunning or overflowing is caused when a program, when writing to the buffer, overruns or overflows the boundary's of the buffer and writes to adjacent memory. This is called a violation of memory safety.
Wikipedia states: “Buffer overflows can be triggered by inputs that are designed to execute code, or alter the way the program operates. This may result in erratic program behavior, including memory access errors, incorrect results, a crash, or a breach of system security. They are thus the basis of many software vulnerabilities and can be maliciously exploited.”
Buffer overflowing is very unlikely because of the implementation of segfaults. This is done by checking that the stack has not been altered when the function returns. If it has been altered, the program exits with a segmentation fault. Three systems that do this are Stackguard, libsafe, and ProPolice, all of which are gcc compiler patches.
Buffer underruning, or underflowing is cause when a buffer is sent data at a speed lower than the speed the data is being read from it. This means that whatever is reading from the buffer has to pause and wait for the stream to send data to the buffer so that the data can be read. In computing, this is most commonly refered to as lagging. “dang laggers!”.
This can be prevented/fixed by increasing the size of the buffer. If you wish to read data at a speed of 5, and the stream is sending it at a speed of 4, you are going to experience buffer underflow. So, you can increase you buffer size to 10, leaving you a 2 second window, or even to 300 to give you a full minute window. The unfortunate side to this is an increase in latency between the input and output, which is very undesirable in applications like video gaming.
LIFO - Last in, First out. FIFO - First in, First out.
LIFO can be expressed like a stack of plates. You can take a plate from the top, but no where else, hence the term “last in, first out”. By definition, a lifo is a linear structured list. YOu can take something from the top, but no where else. If you had such a thing as a linear array, where you loaded information in, but could not access any member, only the last one in, if you loaded the numbers {6,3,8,5,4} into the LIFO array in that order, the last one in would be 4, so the first one out, LIFO, would be 4.
FIFO is slightly different, and can be expressed through the example of a hose. If you have a piece of hose that is 6“ in diameter, and you put a couple balls in it that are just over 3” in diameter, what ball is the first one out the other end? The first ball put in. Hence the term “first in, first out”. If you loaded the numbers {6,3,8,5,4} into a FIFO array in that order, the first one in would be 6, so the first one out, FIFO, would be 6.
Sorting algorithms are an algorithm that puts members of a list in a specified order. ex:
Sorting is most useful when you plan to search through your data to find a specific value, or if you wish to output your data in any specific order, like sorted by last names, or age.
A few popular sorting methods:
There are many more sorting methods, but for this example, we will only list these methods. Below is a C implementation of a bubble sort.
void bubbleSort(int numbers[], int array_size) { int i, j, temp; for (i = (array_size - 1); i > 0; i--) { for (j = 1; j <= i; j++) { if (numbers[j-1] > numbers[j]) { temp = numbers[j-1]; numbers[j-1] = numbers[j]; numbers[j] = temp; } } } }
Bubble sorting begins at the top of the data, and if the first is greater than the second, it swaps them and so on and so forth. Below is an example of a bubble sort.
void bubbleSort(int numbers[], int array_size) { int i, j, temp; for (i = (array_size - 1); i > 0; i--) { for (j = 1; j <= i; j++) { if (numbers[j-1] > numbers[j]) { temp = numbers[j-1]; numbers[j-1] = numbers[j]; numbers[j] = temp; } } } }
This type of sorting is good for sorting arrays of numbers or letter into alphebetical or numerical order.
Insertion sort takes items one by one from the list and inserts them into their correct position. this type of sorting is very easy to implement and is very effective on small groups of data. Below is a quick look at some pseudo code for an insert loop in a 0 based array like in C.
for j ←1 to length(A)-1 key ← A[ j ] > A[ j ] is added in the sorted sequence A[0, .. j-1] i ← j - 1 while i >= 0 and A [ i ] > key A[ i +1 ] ← A[ i ] i ← i -1 A [i +1] ← key
below is a quick visual representation of what goes on during an insert sort:
Note: some items used from wikipedia as visual aids.
Shell sorting was created by a man named Donald Shell in 1959. It runs on a sorting method devised by Donald, and finishes with insertion sort by moving out of place elements more than one place at a time. While this method of sorting may not be the best for all cases of data, it is highly effective on small and medium groups of data.
“The algorithm begins by performing a gap insertion sort, with the gap being the first number in the increment sequence. It continues to perform a gap insertion sort for each number in the sequence, until it finishes with a gap of 1. When the increment reaches 1, the gap insertion sort is simply an ordinary insertion sort, guaranteeing that the final list is sorted. ” ~wikipedia
This simply means that the numbers in the set of data are arranged into n number of columns, lets say 5 columns, the columns are then sorted so that they are in order, lowest to highest. The sorting then aranges them into n - x columns, say 3 columns, these columns again are sorted from lowest to highest, providing more number to be in the right order. The sorting will eventually get down to 1 column where a regular insertion sort is perfomed which arranges the data into one long column where all the data is properly sorted.
13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 10 14 13 25 23 33 27 25 59 39 65 73 45 94 82 94
At this point the data is arranged again into a line and sorted using the insertion sort.
Selection sort algorithm finds the lowest value and swaps it with the first position for n amount of times, O(n^2) making it inefficient on larger lists.
The algorithm operates as so:
This breaks the list up into two parts, the items already sorted, and the sublist of items stuck at the end, waiting to be sorted.
Below is an example of this algorithm sorting 6 elements:
64 2 9 40 28 15 init. 2 64 9 40 28 15 [1] 2 9 64 40 28 15 [2] 2 9 15 40 28 64 [3] 2 9 15 28 40 64 [4] 2 9 15 28 40 64 [5]
as you can see, this method is very effective on a small list, only taking 5 steps to sort 6 elements of data.
Implementation of this in C is below:
int iPos; int iMin; for (iPos = 0; iPos < n; iPos++) { iMin = iPos; for (i = iPos+1; i < n; i++) { if (a[i] < a[iMin]) { iMin = i; } } if ( iMin != iPos ) { swap(a, iPos, iMin); } }
Heap sorting is a popular variant of this sorting algorithm as it has taken the basic structure and improved it using an implicit heap data structure.
Quick sort, a comparison algorithm, was designed by Tony Hoare and is faster in use than other O(nlogn) algorithms.
This alrogithm divides the list into 2 smaller sublist of higher and lower values. Quick sort can then sort these values by three steps:
cprogramming.com has given a simple pseudocode implementation of this topic:
function quicksort('array') //pass the function the array of all elements create empty lists 'less' and 'greater' //sort out the lesser from the greater if length('array') ≤ 1 //if 1 or less elements return 'array' // an array of zero or one elements is already sorted select and remove a pivot value 'pivot' from 'array' //find a value in the center, or some other means of grabbing a pivot value for each 'x' in 'array' //for every element in the array if 'x' ≤ 'pivot' then append 'x' to 'less' //self explanitory else append 'x' to 'greater' return concatenate(quicksort('less'), 'pivot', quicksort('greater')) //return the final sorted array
User space is the area of memory where all user applications are run. This involves software that works with file manipulations and performs input/output. Each user process has its own virtual memory location and cannot access the memory locations of other proccesses without permission.
referenceed cprogramming.com
The Jargon File
In computing, the kernel is the main part of most computer operating systems, it is a bridge between applications and the actual data processing done at the hardware level. The kernel's responsibilities include managing the system's resources and the communication between hardware and software components.
A computers operating system usually seperates virtual memory into kernel space and user space. Kernel space is reserved for running the kernel, kernel extensions, and most device drivers.
A file descriptor is an indicator for accessing a file. In C, and most other languages, a file descriptor is an integer, like C type int. Aside from this, every file proccess has 3 basic commands or operations. File in, File out, and Standard file error. A file descriptor is usualy an index for entry in a kernel-resident data structure that contains all the details for openning and accessing file. All applications pass commands via system calls where the files are then access by the kernel based on the commands sent.
Some operations that can be used with file descriptors are:
As refered to in the last keyword, a system call is how a program requests something from a computer systems kernel. This can include hardware or software related calls and can be things like scheduling, accessing the hard disk and many more.
System calls can be divided into 5 catagories:
side note: On POSIX operating systems usual calls are:
A unix pipe provides a one way flow of data. If someone was to enter the command : who | sort , the unix shell who evaluate the who command, and send that data into the sort command as its entry data.
who —–> | —–> sort
write read
The same goes for functions, as you can run a function that returns data, and pipe that data to another function
I/0 redirection is simply redirection input or output signals to a location other than it's standard direction. For instance, “concatenate > confile” would send the output of the concatenate function to the file confile, truncating the data to the end of the file. To append data simply use » instead of >.
To redirect standard input, use concatenate < confile, resulting in concatenate using confile as input.
symbol | |||
input | < | ||
output | » | ||
truncate | > |
Since a unix shell reads commands from the left to the right, pipes and I/0 redirection can be used in conjunction with each other.
Ex: concatenate | file1 > sort > filesorted
This will run the program concatenate, pipe the output to a file so that sort can use the contents of that file and run a sorting expression and place the input in the file “filesorted”.
similarly, a pipe can be used in place of I/0 redirection, and vice versa.
Ex: concat1 | concat2 ~this will pipe the output of concat1 to be used as the input for concat2 Ex: concat1 > file1 concat2 < file1 rm tmpfile ~this is equivalent to the piping command above.
An internet socket or network socket is an endpoint of a bidirectional inter-process communication flow across an Internet Protocol-based computer network, such as the Internet. ~wikipedia.
Internet sockets constitute as a mechanism for delivering incoming data packets to the appropriate application process or thread, and is all based on a combination of ip addresses, remote and local. Each socket is mapped by the operating system to an application. Within these application and the operating system, these sockets are refered to by an integer called a socket number.
Every socket has an address which is a combination of a port number and an ip address. Each socket also runs on a transport protocol, UDP, TCP, Raw IP, and many others.
A server creates on startup that remain in the listening state untill called by client programs.
For a listening TCP socket, the remote address presented by netstat may be denoted 0.0.0.0 and the remote port number 0.
A TCP server may serve several clients concurrently, by creating a child process for each client and establishing a TCP connection between the child process and the client.
Unique dedicated sockets are created for each connection. These are in established state, when a socket-to-socket virtual connection or virtual circuit (VC), also known as a TCP session, is established with the remote socket, providing a duplex byte stream. ~wikipedia
Therefore, a server socket is a socket created by a server at startup that runs in the listening state until called by a client program. These sockets establish a TCP connection between the server and client. IF it is a TCP server, multiple clients can be run simultaneously.
A signal is a type of inter-process communication used in UNIX operating systems. It is a type of message sent to a process to notify it that an event happend. When the process gets the signal it stops it's normal flow and allows its signal handler to execute.
Ex:
Signal | Description | Signal number on Linux | |||
SIGABRT | Process aborted | 6 | |||
SIGALRM | Signal raised by <tt>alarm</tt> | 14 | |||
SIGBUS | Bus error: “access to undefined portion of memory object” | 7 | |||
SIGCHLD | Child process terminated, stopped (or continued*) | 17 | |||
SIGCONT | Continue if stopped | 18 | |||
SIGFPE | Floating point exception: “erroneous arithmetic operation” | 8 | |||
SIGHUP | Hangup | 1 | |||
SIGILL | Illegal instruction | 4 | |||
SIGINT (POSIX) | Interrupt | 2 | |||
SIGKILL | Kill (terminate immediately) | 9 | |||
SIGPIPE | Write to pipe with no one reading | 13 |
These are only a few of the 64 unix signals.
<signal.h> can also be referenced for more information on this topic.
blocking and non-blocking are forms of input/output processing.
Operating systems implement many functions to use Asynchronous I/0 at many different levels. This type of processing only requires basic functionality to check if steps have checked in or completed, and alerts the other steps accordingly.
Discuss the representation and use of primitive data types and built-in data structures
I will research primitive data types and built-in-structures to determine their formal definition and a few examples, i will then bring that data before another individual to discuss the use of primitive data types and built-in-structures to help myself and the other individual better learn the uses and need for primitive data types and built-in-structures.
This objective took me roughly 4-5 hours to complete, I reserched many of these data types and structures, and presented the information before an individual who proceeded to discuss and explain a few of these in depth. I now plan to record the use of these structures as learned in class and review them in a drive to better understand the representation and use of primitive data types and built-in-structures.
Primitive data types:
Built-in-structures:
and many others.
I believe that yet again i achieved a very good understanding of the course objective and put a lot of effort into this objective. I believe it was done effectively and well and since there is much room for improvement with these topics, it is a good thing the class is only 25% done!
To develop a better understanding of concurrency.
I will now start to ask questions about concurrency, and concurrency in the programs we are writing to see if there is any concurrency going on in our current programs. I will then document that concurrency and try to find or create more concurrency in other programs to better understand it.
concurrency is sahweeeeet! We are going to be touching on the fork() function possibly this Friday in an attempt to really understand concurrency at its finest. It is running more than one thing at a time in a function. So if a function is going to process 400 items, but you need it done in the time it would take to process 100, you can fork the function 3 times and have each fork of the program process 100 items, all at the same time!
What will happen if you give the squaring function [pow()] an invalid value? Like an array?
The man page for this function, and a test program to see hand in hand the results of at valid and invalid entry.
Based on the manual recordings for the pow() function, a non integer value entered into the pow() will return a domain error.
I will test this by running through a program and passing a non integer value for the y coordinate of the pow(x,y) function.
z = pow(x,zero); where x is a positive integer and zero is a character array, does not evaluate. Instead, it returns the error:
showing that an evaluation where x > 0 and y is a non integer, cannot be executed.
Based on the data collected:
Based on my evaluations, i ascertain that the pow function does exactly what it is supposed to, and returns a reasonable statement “domain error”. It returns this because its input cannot be non integer, meaning it cannot accept an array.
Can randomness create order??
Using the monroe method for estimating pi, we can get a rough estimate for pi by generating x amount of points in a quadrant. Also, monkeys are quite fast typers.
I do believe that you can get pi, respectively, by using randomness.
How are you going to test your hypothesis? By using the monte carlo method for calculating pi. I will create a function that runs through some math based on a user define number of iterations.
/* Program to compute Pi using Monte Carlo methods */ #include <stdlib.h> #include <stdio.h> #include <math.h> #include <string.h> #define SEED 35791246 main(int argc, char* argv) { unsigned long int niter=0; double x,y; int i,count=0; /* # of points in the 1st quadrant of unit circle */ double z; double pi; printf("Enter the number of iterations used to estimate pi: "); scanf("%u",&niter); /* initialize random numbers */ srand(SEED); count=0; for ( i=0; i<niter; i++) { x = (double)rand()/RAND_MAX; y = (double)rand()/RAND_MAX; z = x*x+y*y; if (z<=1) count++; } pi=(double)count/niter*4; printf("# of trials= %u , estimate of pi is %g \n",niter,pi); return 0; }
lab46:~/src/DataS$ ./pi Enter the number of iterations used to estimate pi: 1 # of trials= 1 , estimate of pi is 4 lab46:~/src/DataS$ ./pi Enter the number of iterations used to estimate pi: 2 # of trials= 2 , estimate of pi is 2 lab46:~/src/DataS$ ./pi Enter the number of iterations used to estimate pi: 4 # of trials= 4 , estimate of pi is 2 lab46:~/src/DataS$ ./pi Enter the number of iterations used to estimate pi: 16 # of trials= 16 , estimate of pi is 2.5 lab46:~/src/DataS$ ./pi Enter the number of iterations used to estimate pi: 256 # of trials= 256 , estimate of pi is 2.98438 lab46:~/src/DataS$ ./pi Enter the number of iterations used to estimate pi: 65536 # of trials= 65536 , estimate of pi is 3.14227 lab46:~/src/DataS$ ./pi Enter the number of iterations used to estimate pi: 4294967296 # of trials= 0 , estimate of pi is -nan lab46:~/src/DataS$ ./pi Enter the number of iterations used to estimate pi: 131072 # of trials= 131072 , estimate of pi is 3.1423 lab46:~/src/DataS$ ./pi Enter the number of iterations used to estimate pi: 262144 # of trials= 262144 , estimate of pi is 3.14171 lab46:~/src/DataS$ ./pi Enter the number of iterations used to estimate pi: 524288 # of trials= 524288 , estimate of pi is 3.13922
Based on this data collected, as we increase the number of random numbers, we get a closer and closer approximation of pi.
The monte carlo method for computing pi is a great way to show that randomness can produce order.
Dave Schoeffler asks: How does the system handle unexpected input. Such as a character when an integer is expected.
I believe that when you enter a character when an integer is expected the program will output an error and terminate. This will happen because the system does not know what with the character value.
I used the same code as Dave.
lab46:~/src/data$ ./inttest Enter integer: 1 Int is 1 lab46:~/src/data$ ./inttest Enter integer: q Int is 0 lab46:~/src/data$ ./inttest Enter integer: s Int is 0 lab46:~/src/data$
Answer the following:
Answer the following:
Spent the better part of Data Structures reading through the fork manual, called by “man 2 fork”. We then wrote ~/src/SysProg/fork/forkify.c , a simple program to demonstate the uses and returns of the fork function along with sleep, wait, and get pid. We also covered the pid_t data type. The program demonstrated a couple of good ways to check to see what child has what PID, and to make sure the children don't do anything the parent is supposed to, and vice versa.
To use the fork function, you need to include the unistd.h header file, called by “#include<unistd.h>”. accepts a void parameter returns the PID of the forked process
wait() will wait for PID's to die, and will clean up what they did.
Today was a good day. We spent a decent amount of time on sorting algorithms, and then each implemented our own algorithms. I used a bubble sort that sorted an integer value array.The bubble sort is found in ~/src/DataS/bubble.c and the bubble sort part is below:
while(swap == 0) { swap=1; for(i=1;i<count;i++) { if(*(list+(i-1)) > *(list+i)) { c = *(list+(i-1)); *(list+(i-1))=*(list+i); *(list+i) = c; swap = 0; } } count--; }
While this is a simple algorithm, it has a lot wrapped up in it. It compares the elements of an array with each other and if they are equal, it swaps them by use of a dummy variable. One the for loop ends, the highest unsorted value is at the end of the array, therefore we can reduce how far into the array we need to compare.
Also, revenge is sweet ;)
I am pretty sure I am going to devote this whole journal entry to Thanksgiving because this year, it was pretty special. This is the first holiday that my extended family has “hung around” before or after the meal. My mom accidentally turned the oven off while messing with the turkey timer, so food was delayed about an hour. Because of that, my family had to arrive early and i dont know if they enjoyed staying, but they stayed after aswell and we had a lot of quality family time for once. And the food, ohhhh…. Stuffing is the best part of thanksgiving, fo sho son. Not to mention that but the deserts we will have for decades! We had apples pies, chocolate pies, white chocolate cheesecake and pumpkin bars, soooo good!
This is a sample format for a dated entry. Please substitute the actual date for “Month Day, Year”, and duplicate the level 4 heading to make additional entries.
As an aid, feel free to use the following questions to help you generate content for your entries:
Remember that 4 is just the minimum number of entries. Feel free to have more.
A hash table is a data structure that maps values known as keys, like an age, to the profiles of everyone that age. These tables use a hash function that turns the key into the index of the main array.
These tables are usually comprized of an array of linked lists, allowing you to create structures like directories fairly simple.
In a well-made hash table, the average iterations for each lookup is independent of the number of elements stored in the table. Many hash table designs also allow arbitrary insertions and deletions of key-value pairs, at a constant average cost per operation. photo courtesy of wikipedia
Graph structures consist of a set of ordered pairs, formaly called arcs, or edges of entities called nodes. These nodes can be part of the graph structure, or be external entities represented by integer indices.
A graph data structure may also associate to each edge some edge value, such as a symbolic label or a numeric attribute (cost, capacity, length, etc.).
The basic operations provided by a graph data structure G usually include:
Structures that associate values to the edges usually also provide:
Different data structures for the representation of graphs are used in practice:
Some information derrived and simplified from wikipedia
A binary tree is a node based data structure that has two main branches, one to the left with lesser keys, and one to the right with greater keys. The placement of each node is based on it's key, and not the other values of the node. The tree is formed based on a root node that is assigned a pivot key. All other keys entered then go either to the left or right of that root node based on the rank of that key. and so on and so forth through the tree until they reach the bottom of their branch where they become a leave of the tree.
This is an effective method of data searching because after the first check, at the root node, half of the tree is no longer a possibility because the check will send the tmp variable to either the lesser or greater value branch of the root node.
Below is a sample of code that is used in a node based tree.
Node *grep; grep = malloc(sizeof(Node *)); mytree -> tmp = mytree -> root; while(mytree -> tmp -> value != val) { if(val < mytree -> tmp -> value) { if(mytree -> tmp -> smaller != NULL) mytree -> tmp = mytree -> tmp -> smaller; else mytree -> tmp -> smaller = grep; } else { if(mytree -> tmp -> bigger != NULL) mytree -> tmp = mytree -> tmp -> bigger; else mytree -> tmp -> bigger = grep; }
Insertion is where a value, or key is added at an arbitrary point in a list. Observe a single-dimension array for example. This array contains the values 3, 7, 13, 21, 45, 93 and we wish to insert the value 33. If the list is ordered, the value will be inserted between the values 21 and 45. If not, the value can be inserted at any point in the array.
Tree *add(Tree *mytree, char val) { if(mytree -> root != NULL) { Node *grep; grep = malloc(sizeof(Node *)); mytree -> tmp = mytree -> root; while(mytree -> tmp -> value != val) { if(val < mytree -> tmp -> value) { if(mytree -> tmp -> smaller != NULL) mytree -> tmp = mytree -> tmp -> smaller; else mytree -> tmp -> smaller = grep; } else { if(mytree -> tmp -> bigger != NULL) mytree -> tmp = mytree -> tmp -> bigger; else mytree -> tmp -> bigger = grep; } } } return mytree; }
Removal is pretty straight forward, just as insertion was. Removal refers to the removing, pop, or displacement of an arbitrary value/key or node. If we go back to the example of an array, this time containing the values 3,7,13,21,33,45,93 with 33 added from the insertion operation. And we remove an arbitrary value, say 33, we will then turn the array back to the starting array of 3,7,13,21,45,93, showing that insert and remove are opposites.
#include"tree.h" Tree *del(Tree *mytree, char val) { if(mytree -> root != NULL) { mytree -> tmp = mytree -> root; while(mytree -> tmp -> value != val) { if(val < mytree -> tmp -> value) { if(mytree -> tmp -> smaller -> value = val) { mytree -> solo = mytree -> tmp -> smaller; mytree -> tmp2 = mytree -> solo -> bigger; while(mytree -> tmp2 -> smaller != NULL) mytree -> tmp2 = mytree -> tmp2 -> smaller; mytree -> tmp2 -> smaller = mytree -> solo -> smaller; mytree -> tmp -> smaller = solo -> bigger; mytree -> solo -> smaller = NULL; mytree -> solo -> bigger = NULL; free(mytree -> solo); } else mytree -> tmp = mytree -> tmp -> smaller; } else { if(mytree -> tmp -> bigger -> value = val) { mytree -> solo = mytree -> tmp -> bigger; mytree -> tmp2 = mytree -> solo -> bigger; while(mytree -> tmp2 -> smaller != NULL) mytree -> tmp2 = mytree -> tmp2 -> smaller; mytree -> tmp2 -> smaller = mytree -> solo -> smaller; mytree -> tmp -> smaller = solo -> bigger; mytree -> solo -> smaller = NULL; mytree -> solo -> bigger = NULL; free(mytree -> solo); } else mytree -> tmp = mytree -> tmp -> bigger; } } } return mytree; }
Searching means to move about a data structure to see if a given value or key is in that data arrangement. This can be best explained through an example of a linked list search.
#include"linkedlist.h" Node *find(List *mylist, char f) //Mylist is the list we are looking through, f is the value to find. { Node *test2; // tmp node for moving about the list. test2 = mylist -> start; while((test2 != NULL) && (test2 -> value != f)) //while list is populated and test2 does not find the value { if(test2 -> next != NULL) //while list is populated { test2 = test2 -> next; //move to next spot } } if(test2 -> value != f) { test2 -> value = #; } return test2; //returns the address of the node that contains the value, or # if not found. }
Tree traversal is visiting each node in a tree structure to examine or update those nodes. Three traversal structures are classified by the way each node is visited.
Merge sort is a “divide to conquer” sorting algorithm that operates on a O(n logn) comparison basis.
A merge sort works like so:
A binary search is a O(1) best case, O(logn) worst case sorting algorithm that works off from an already sorted array. This method takes a given key and compared it to the middle key of the array. If the given key is greater, the index of the array is moved one to the right. If the given key is less, the index is moved to the left one. This operation is repeated until the desired key is found, or the array index's next is null. In this case a special “end of file” indicator is returned.
These computational problems are given a complexity level based on the amount of resources need to perform. The computer defines these levels based on a set of models of computation that project how much time and storage needed for the problem to complete.
This Notation is used to classify different algorithms based on the time they take to complete. Each algorithm has three recorded times, a worse case, best case, and average case. The time it takes for each case is given in a mathmatical expression like (nlogn) or n^2 where n is the number of iterations of the algorithm.
Big-O is roughly affirmed with the upper bound asymptote or as the worst possible case.
Describes the case where the upper and lower bounds of a function are on the same order of magnitude.
Describes the lower bound, or best case.
Memory is managed statically, automatically, and dynamically. In this example we will look at static versus dynamic allocation.
Static memory is not adequate for all situations. You might want to make a variable that could contain one word, or 1000 sentances, but you don't want to allocate enough memory for 1000 sentances if you are just storing one word. That is where Dynamic memory allocation comes in and Malloc() is an example of this. Dynamic memory is allocated from the heap, so as long as there is memory left to allocate, a program can use as much as needed, or as little as needed. A linked list is a great example of Dynamic memory allocation. If the user wants to use more memory storage the program can allocate memory like so:
Node* tmp3; tmp3 = (Node *) malloc (sizeof(Node)); tmp3 -> value = d;
This will create a node structure based on some Struct, and allocate memory of a pre-defined size, the size of the Node, and place a specified value in that node. This can be called recursively or in a loop as needed, thus creating dynamic memory allocation. Since this memory was allocated via Malloc(), it can be removed with the free() function, thus freeing up the space used my malloc().
Static memory is allocated and fixed for the lifetime of the program. This memory is allocated on the stack and comes and goes as the functions call for it, but still exists whether called or not. This can be useful for programs that know exactly how much memory will be used during the lifetime of the program, and will never need to allocate more that a given amount of memory.
int input; printf("please enter input"); scanf("%d", input);
This will allocated static memory and same input into it, which will then exist for the lifetime of the program whether it is used or not, and cannot be freed by functions like free().
A named pipe is a more indepth pipe from unix computer systems, and is an inter-process communicator. A regular pipe is usually unnamed because it only exists and acts anonymously while the program is runnning. A named pipe exists after the life on the program and must be deleted. It is called System-Persistent.
mkfifo my_pipe gzip -9 -c < my_pipe > out.gz cat file > my_pipe rm my_pipe
File locking restricts access to one user or process at a time to avoid changes being over written (interceding updates).
Most systems support file locking to prevent updates happening in this fashion. Therefore Mark must wait for John to finish before he can check a copy of the file out. Use of file locking should be monitored as a poor use of it can cause a gridlock in the system.
ID's are numbers assigned to users and groups on a Linux system(and possibly others) so that the kernel has a way to address them. This is used mainly for permissions. One can set individual permission levels or group levels and place individuals into that group.
A users UID and GID can both be attained through the id command.
lab46:~$ id uid=5689(bkenne11) gid=5000(lab46) groups=5000(lab46),1734(sys),1738(data),5689(bkenne11) lab46:~$
Once you log into a Linux system you become a number to the kernel. This number is your user ID. This ID helps to set permissions for what user number # can do. Exapmles of this in affect are user ID 0. The Zero user is Root and enjoys unlimited/unrestricted access to the system.
A group can be created with special permissions that allows it's member to have the permissions of the group. You then can create a group with permissions to manage the mail client of a system so that those users and those users only have special rights to manage or maintain the mail client.
A deivce file, or special file, is like an interface for software to interact with device drivers via standard input and output. These usually conect periferals like printers, mice, keyboards and serial ports but can also be used to access more specific things like disk partitions.
There are two general kinds of device files in Unix-like operating systems, known as character special files and block special files. The difference between them lies in how data written to and read from them is processed by the operating system and hardware.
CON | Receives typed data until | Z (Ctrl-Z) is pressed. | Prints data to the console. | |||
---|---|---|---|---|---|---|
RN | N/A | Prints text to the printer. | ||||
AUX | Reads data from an auxiliary device, usually a serial port. | Sends data to an auxiliary device, usually a serial port. | ||||
NUL | Returns null or no data. | Discards received data. | ||||
CLOCK$ | Returns system real-time clock. | N/A | ||||
LPT1 (also 2–9) | Reads data from the selected parallel port | Sends data to the selected parallel port | ||||
COM1 (also 2–9) | Reads data from the selected serial port | Sends data to the selected serial port |
A typical file system may contain thousands upon thousands of files which can be organized by Directories(often called folders). These directories can hold files and or other directories making a tree system of files. The files contained within a folder are called subfiles or subfolders. For example:
You have a file system that is phone book. You can have a directory call phbook that contains directories for all leters of the alphabet, which contain directories for all people with the last name -blank-, which are files of the information of each person.
On unix based systems:
comand | action | ||
cd | change current directory | ||
ls | list current directory | ||
mkdir | make directory called ? | ||
rm -d | remove directory ? | ||
mv | move directory |
A buffer is a place where data you have just recieved is stored once downloaded from somewhere like the internet. This given you an opportunity to work on that data in real time incase your download speed is too slow to work on the data as it is recieved. This is useful when rendering videos off from the internet on sites like youtube or hulu, but can also be used in file reading. On unix-like system the command read-partial can be used to read a file to a buffer up to a certain point where it can then be read to another file or etc.
Shared memory is memory that can be simultaneously accessed by multiple programs on a running system to provide communication between those programs.
Shared memory can also be refered to as a large block of RAM that can be accessed by multiple CPU's on a multi-cpu system.
Also called an IPC socket, a Unix domain socket is an endpoint for data communications that allows processes operating in the same system to exchange data. The APL for these sockets is similar to an internet socket, meaning the processes don't have to have the same ancestry.
These sockets are usually found on POSIX operating systems.
Coroutines are a pretty cool thing. As far as i've read they generalize subroutines like generators do, but are more powerful. They allow lots of entry points for suspending and resuming at different points.
The C programming guide says that Coroutines are best used when implementing components such as iterators, infinite lists, cooperative tasks and pipes.
A good time to use a file link is when you have several different programs that need to use the same data, but are in different directories. The programs can of course call the files with their complete file name, but that can get slopy and can be hard to change if the file is moved. This is when file links come in handy.
A file link is a directory entry that refers to a file. There are a few ways to do this, but the most common is a symbolic link. A symbolic link is a special file that contains a refrence to another file or directory by it's pathname. Any program that uses a symbolic link treats it as if it is operating on the target file.
The process of keeping consistency with data from a source to a target storage device and vice versa is called data synchronization. In english, this process harmonizes data contained in data storage spaces such as files or file servers. A good example of file synchronization is a USB flash drive or a hard drive of a home computer. This process prevents copying already identical files, saving a lot of time.
To sum it up, It creates one big data storage of one copy of all the files, instead of copying every source and having multiples of each file.
My last keyword for my fall 2011 opus, almost sad, but deffinitely not! I have chosen threads because it is something that has always avoided my grasp. I have wanted to learn about and understand a thread for a long time, so here we go!
A thread is a thread of execution, or a unit of processing that can be scheduled by the operating system to evaluate at the scheduled time. Since a thread is the smallest unit of processing, a thread is actually contained within a process. Not just that, but there can be multiple threads inside of a process which can share resources like memory, but only inside that process. Multithreading can be expressed like multiple contractors building the same house, at the same house, and working off from the same building plan, but maybe not the same pages.
A few notes about threads:
Describe common applications for each data structure described in class
As each data structure appears, i will ask questions and record programs and applications of each data structure that is given in class in an attempt to have each of the structure described to me in an understandable way.
So far so good, I have had linked lists explained to me in many ways by recording programs and using them to ask multiple questions to ensure that i understand the data structure that was being taught.
The method used to complete this objective seems to be an effective one. It falls in line with my teachers objectives for the course and for our learning and has so far provided much valid information reguarding the data structures being taught. I believe it will continue to be an effective method of learning that will help not only me, but others to convert to this style aswell.
explore efficient solutions to data- and processing- intensive problems.
Exploring Asymptotic algorithms for data processing.
Going very well, i have seen a lot of algorithms for data processing and I can see how it is very important to be consistently developing solutions to data and processing intensive problems.
Can I implement a tree program through a library and not use function prototypes? What will happen if I don't?
I think that I will be able to compile and run my program properly without using prototypes, but i am guessing i will get some warning considering so.
I am going to use a previously written tree library and remove it's prototypes, then compile.
Bingo! When recompiling this tree structure without function prototypes it went through! I ran the program and everything worked properly, give or take getting 2 unrelated compiler warnings. It looks like the compiler doesn't need prototypes.
#include"tree.h" int main() { int input; Tree *mytree; mytree = malloc(sizeof(Tree *)); while(input != -1) { printf("Enter a positive integer value: "); scanf("%d", &input); if (input != -1) mytree = add(mytree, input); } printf("Enter - 1 - to add a node\n"); printf("Enter - 2 - to delete a node\n"); printf("Enter - 3 - to print the nodes in post order\n"); scanf("%d", &input); if(input == 1) { printf("Enter a positive integer value: "); scanf("%d", &input); mytree = add(mytree, input); } else if(input == 2) { printf("These are the values in the tree,\n"); printf("please enter a value to delete: "); postpr(mytree -> root); scanf("%d", &input); del(mytree, input); } postpr(mytree -> root); printf("\n"); return 0; }
* * add.c, a tree manipulation function. * Made by Brandon Kennedy for Data Structures * Semester: Fall: 2011 * * prototype: Tree *add(Tree *, char); * Returns a tree struct containing the address of the root, tmp, tmp2, and solo nodes.. */ #include"tree.h" Tree *add(Tree *mytree, int val) { Node *grep; grep = malloc(sizeof(Node *)); grep -> value = val; if(mytree -> root != NULL) { mytree -> tmp = mytree -> root; while(mytree -> tmp -> value != val) { if(val < mytree -> tmp -> value) { if(mytree -> tmp -> smaller != NULL) { mytree -> tmp = mytree -> tmp -> smaller; printf("smaller\n"); } else mytree -> tmp -> smaller = grep; } else { if(mytree -> tmp -> bigger != NULL) { mytree -> tmp = mytree -> tmp -> bigger; printf("bigger\n"); } else mytree -> tmp -> bigger = grep; } } } else { mytree -> root = grep; } return mytree; }
#include"tree.h" Tree *del(Tree *mytree, char val) { if(mytree -> root != NULL) { mytree -> tmp = mytree -> root; while(mytree -> tmp -> value != val) { if(val < mytree -> tmp -> value) { if(mytree -> tmp -> smaller -> value = val) { mytree -> solo = mytree -> tmp -> smaller; mytree -> tmp2 = mytree -> solo -> bigger; while(mytree -> tmp2 -> smaller != NULL) { mytree -> tmp2 = mytree -> tmp2 -> smaller; } mytree -> tmp2 -> smaller = mytree -> solo -> smaller; mytree -> tmp -> smaller = mytree -> solo -> bigger; mytree -> solo -> smaller = NULL; mytree -> solo -> bigger = NULL; free(mytree -> solo); } else mytree -> tmp = mytree -> tmp -> smaller; } else { if(mytree -> tmp -> bigger -> value = val) { mytree -> solo = mytree -> tmp -> bigger; mytree -> tmp2 = mytree -> solo -> bigger; while(mytree -> tmp2 -> smaller != NULL) { mytree -> tmp2 = mytree -> tmp2 -> smaller; } mytree -> tmp2 -> smaller = mytree -> solo -> smaller; mytree -> tmp -> smaller = mytree -> solo -> bigger; mytree -> solo -> smaller = NULL; mytree -> solo -> bigger = NULL; free(mytree -> solo); } else mytree -> tmp = mytree -> tmp -> bigger; } } } return mytree; }
#include"tree.h" void postpr(Node *lantro) { if(lantro != NULL) { postpr(lantro -> smaller); printf("%d, ", lantro -> value); postpr(lantro -> bigger); } }
#ifndef _TREE_H_ #define _TREE_H_ #include<stdlib.h> #include<stdio.h> struct node{ char value; struct node *bigger; struct node *smaller; }; typedef struct node Node; struct tree{ struct node *root; struct node *tmp; struct node *tmp2; struct node *solo; }; typedef struct tree Tree; #endif
Based on the data collected:
It appears(by reading and reviewing data) that if you don't include function prototypes, the compiler cannot see potential errors like:
In conclusion, include prototypes! It only takes a line per prototype, and saves you from a lot of potential trouble.
How much more memory does a linked list use than an array?
The C programming guide Cprogramming.com/threads%read\input
I don't feel that a linked list should take up very much more memory than an array.
They have the same basic structure, a next and a previous. they may be incrememnted differently, but they hold the same basic structure.
To test this hypothesis i am going to write a quick program that will create an array with an integer value, and a struct with an integer value. I will then use the sizeof command to retrieve the size of both data structures and multiply then by 100 to show a decent difference in their memory uses.
#include<stdio.h> struct node { int value; }; typedef struct node Node; int main() { int array[10]; int i; for (i=0;i<10;i++) array[i] = i; printf("node size is %d in bytes\n", (sizeof(Node)*100)); printf("array is %d bytes\n", (sizeof(array[3])*100)); return 0; }
Done with the above code:
lab46:~$ ./exper node size is 400 in bytes array is 400 bytes lab46:~$
Done with the code manipulated so that the array is of type char.
lab46:~$ ./exper node size is 400 in bytes array is 100 bytes lab46:~$
Based on the data collected:
As far as I can conclude from this experiment, the data structure used matter none in reference to the memory space allocated when creating/using that structure. The only thing that affects the memory used is the data type of the variable being allocated. In this experiment, I gace two command line examples. The first was a linked list node and an array slot both of type int. They, when sized, use the same amount of memory to store the integers they are given. In the second CLI example the node structure in of type int, and the array is of type char and this is where we can see some change. The node of type int takes up four bytes while the array slot of type char takes up 1 byte, showing that these data structure are only the size (memory wise) of the data types allocated inside of them.
Thought this experiment was over? Well think again!
The above experiment is correct in it's context, but only because the node structure created is for a linked list of one node. What happens while i make it a singly linked list? or a doubly linked list?
Lab46 is a 64 bit system that has char value of 1 byte and int value of 4 bytes, this is important. That means that when you created a variable with the data type char, the system allocates it a block size of 1 byte, same for an integer, but of block size 4. The next block size after that is 8 then 16, also important. When the node structure for the above linked list was created:
#include<stdio.h> struct node { int value; }; typedef struct node Node;
Inside of the structure there is only an integer value, nothing else, causing this node to only use 4 bytes of data. This is fine for a list of one node, but what about an 10 nodes? or 100? Since linked lists use pointers to nodes to keep track of the address of other nodes, these pointers must be taken into account also. On lab46, the system allocates 8 bytes for a pointer to a node.
#include<stdio.h> struct node { int value; struct node *next; }; typedef struct node Node;
This singly linked list will take up memory for two things:
total bytes: 9 Since the block sizes around this are 8 and 16, the system will allocate 16 bytes of data and pad the unneeded space. But what does that mean for a doubly linked list?
#include<stdio.h> struct node { int value; struct node *next; struct node *prev }; typedef struct node Node;
This doubly linked list will take up memory for:
total bytes: 17 Since this is above 16, we have to go to the next block size, which is 32.
So, to REALLY conclude, while a data type is worth it's respective bytes no matter the data structure it is contained in, the data structure can need other data types allocated to operate. Therefore:
I think that covers everything…
Karl Kraus.
Question: After learning about enum I was curious as to what value it starts at, is it 0 or 1? Or possibly some other random value?
Evaluate their resources and commentary. Answer the following questions:
State their experiment's hypothesis. Answer the following questions: there was no hypothesis stated
Follow the steps given to recreate the original experiment. Answer the following questions:
#include <stdio.h> int main() { enum days{sunday, monday, tuesday, wednesday, thursday, friday, saturday}; printf("%d\n", sunday); printf("%d\n", monday); return 0; }
lab46:~/src$ ./karlretest 0 1 lab46:~/src$
Answer the following:
Answer the following: