Trouble Understanding Fork Logic - process

Can someone help me understand what is happening in this segment of code? I am having trouble understanding why the output is how it is. Output is:
0 1 2 3 4
3
2
1
0
int main() {
int i;
for (i = 0; i < 5 && !fork(); i++) {
fflush(stdout);
printf("%d ", i);
}
wait(NULL);
printf("\n");
return 0;
}

Two things here:
First, fork() return 0 in child process while it returns a non zero pid to the parent process.
Second, short circuit of &&.
So in the beginning of the first process (p0), it runs to i < 5 && !fork(). Now i = 0 and another process created (p1). Now for p0, test !fork() fails, it ends the for loop and waiting for child to end. For p1, the test succeeds, and print out 0, then increment i to 1, then it will create process p2 and itself goes out the for loop as p0 did.
Because of short circuiting, when i equals 5, no more fork will be called.

Related

Cyclomatic Complexity edges

So I'm trying to figure out if that blue line is in the right place, I know that I should have 9 edges but not sure if it's correct.
The code
public int getResult(int p1, int p2) {
int result = 0; // 1
if (p1 == 0) { // 2
result += 1; //3
} else {
result += 2; //4
}
if (p2 == 0) { //5
result += 3; //6
} else {
result += 4; //7
}
return result; //8 exit node
}
so 8 nodes and it should have 9 edges, right? Did I do the right thing?
Yes, the blue line is placed correctly because after the 3rd line, your program is going to jump to the 5th line.
The easiest way to compute cyclomatic complexity without drawing any flow diagram is as follows:
Count all the loops in the program for, while, do-while, if. Assign a value of 1 to each loop. Else should not be counted here.
Assign a value of 1 to each switch case. Default case should not be counted here.
Cyclomatic complexity = Total number of loops + 1
In your program, there are 2 if loops, so the cyclomatic complexity would be 3(2+1)
You can cross-check it with the standard formulae available as well which are as below:
C = E-N+2 (9-8+2=3)
OR
C = Number of closed regions + 1 (2+1=3)
According to wikipedia:
M = E − N + 2P,
where
E = the number of edges of the graph.
N = the number of nodes of the graph.
P = the number of connected components.
so:
9 - 8 + 2*1 = 3

How to get a grandparents/ancestors process ID?

I would like to know - if possible - how to get the pid of a process' grandparent (or further).
To be more specific, I want for a process to print its depth in a process tree.
For example, when starting with the following:
int main() {
int creator_id = (int) getpid();
pid_t pid1 = fork();
pid_t pid2 = fork();
pid_t pid3 = fork();
//print depth in process tree of each process
return 0;
}
According to my theory, the tree will look like this:
0
/|\
/ | \
/ | \
0 0 0
/ \ |
0 0 0
/
0
So my first idea was to somehow see how often I have to go up until I find the creator's pid.
As a little sidenote:
I also wondered if it was possible to make the printing from bottom up, meaning that all processes in the deepest level would print first.
how to get the pid of a process' grandparent (or further).
This depends on which operating system you are using, since you use fork() to create new process in your example, I suppose you are using some Unix-like system.
If you are using Linux and know the pid of a process, you could get its parent process' pid from /proc/[pid]/stat, the fourth field in that file. Through this parent-child chain, you could find a process' all ancestors.
Following #Lee Duhem's hint, I made the following function that returns the nth ancestor of the current process (the 2nd ancestor is the grandparent).
/* Get the process ID of the calling process's nth ancestor. */
pid_t getapid(int n) {
pid_t pid = getpid();
while(n>0 && pid){ // process with pid 0 has no parent
// strlen("/proc/") == 6
// max [pid] for 64 bits is 4194304 then strlen("[pid]") < 7
// strlen("/stat") == 5
// then strlen("/proc/[pid]/stat") < 6 + 7 + 5
char proc_stat_path[6+7+5+1];
sprintf(proc_stat_path, "/proc/%d/stat", pid);
// open "/proc/<pid>/stat"
FILE *fh = fopen(proc_stat_path, "r");
if (fh == NULL) {
fprintf(stderr, "Failed opening %s: ", proc_stat_path);
perror("");
exit(1);
}
// seek to the last ')'
int c;
long pos = 0;
while ((c = fgetc(fh)) != EOF) {
if (c == ')')
pos = ftell(fh);
}
fseek(fh, pos, SEEK_SET);
// get parent
fscanf(fh, " %*c %d", &pid);
// close "/proc/<pid>/stat"
fclose(fh);
// decrement n
n--;
}
if(n>0)
return -1;
else
return pid;
}

Code for factorials in objective C

Using only for or while statements, I'm trying to come up with a program to generate and print a table of the first 10 factorials. Here's my code:
for (count = 1; count<=10; ++count)
{
n = count;
while (n > 0){
count *= (count-1);
n -= 1;
}
NSLog(#" %2g %3g", count, factorial);
}
I don't understand why this is not working. It never gets out of the loop and goes on forever. What's the correction? Thank you!
The reason:
count *= (count-1);
Since count starts at 1, it will always be reset to 0, so the count <= 10 condition of the outer loop will always be true, hence the infinite looping.
And you're overcomplicating it anyway.
for (int i = 1; i <= 10; i++) {
int r = 1, n = i;
while (n)
r *= n--;
printf("%d! = %d\n", i, r);
}
In Math, n! is the same thing as Γ(n+1) (see: http://en.wikipedia.org/wiki/Gamma_function)
So just use:
-(float)factorial:(float)number1 {
return tgammaf(++number1);
}
This will even work for floats and negative numbers,
other solutions posted are long and extraneous and only work with
positive integers.
During the first loop iteration count is 1 and so also n is 1, then you enter the while and you set count to zero (count-1), and decrease n which becomes zero and you exit the while. So during the second loop iteration count will be zero. You keep decreasing count and it never gets increased, so you never exit the loop until a numeric overflow occurs.
You're doing it harder that what it is (and also inefficient) . Is enough that you keep multiplying n for count to get the factorial:
int n=1;
for (count = 1; count<=10; ++count)
{
n*= count;
NSLog(#"%d",n);
}

While loop executing too many times

this program reads text files, and in this case, reads this one:
Sam
5 0 0 0
Dave
5 5 0 0
Bill
5 -5 0 0
Louise
3 3 5 0
Early in my program, I execute the following while loop:
int count = 0;
while (input.hasNextLine())
{
count++;
if (count % 2 == 1) //for every other line, reads the name
{
String line = input.nextLine();
names.add(line); //puts name into array
}
if (count % 2 == 0) //for every other line, reads the ratings
{
ArrayList<Integer> rtemp = new ArrayList<Integer>();
while (input.hasNextInt())
{
int tempInt = input.nextInt();
rtemp.add(tempInt);
}
allratings.add(rtemp);
}
}
For some reason, by the time this while loop is done, int count is at 14. I only want it to be at 8, and think that it should be, considering that there are only 8 lines of text, and it is supposed to execute for each line. Obviously, this causes big problems later in the program. Any idea what is going on?
It seems from your second loop, the cursor never moves to the next line...I added below lines just after your allratings.add(rtemp); and it worked.
if(input.hasNext())
input.next();

What's wrong with my pascal's triangle?

I've been looking for some simple coding challenges recently, and discovered about Pascal's triangle (here), and I've tried to generate one myself in C/Objective-C. For those that don't know what it is, that link explains it pretty well.
I'm starting to get oddness after the fourth row, and I just can't figure out why.
My output for 5 iterations currently looks like this:
1
1 1
1 2 1
1 3 3 1
4 6 3 1
It should look like this:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
Here is my code so far. The first loop is just a reset loop (setting all the values to 0). The actual logic happens mostly in the second loop. The third loop is where the values are concatenated and formatted in a string.
I've commented this code much more than I would for myself just to aid readability.
int iterations, i, b, mid, chars, temp;
NSLog(#"Please enter the number of itereations");
scanf("%i",&iterations); // take users input and store it in iterations
// calculate where the first 1 should go.
if (iterations % 2 == 0) mid = (iterations)/2;
else mid = (iterations+1)/2;
chars = iterations*2;
int solutions[iterations][chars];
// reset loop
for (i = 0; i<iterations; i++) {
for (b = 0; b<chars; b++) {
solutions[i][b] = 0;
}
}
solutions[0][mid] = 1; // place the initial 1 in first row
for (int row = 1; row<iterations; row++) {
for (int chi = 0; chi<chars; chi++) {
temp = 0;
if (chi > 0) {
temp += solutions[row-1][chi-1]; // add the one diagonally left
}
if (chi < iterations) {
temp += solutions[row-1][chi+1]; // add the one diagonally right
}
solutions[row][chi] = temp; // set the value
}
}
// printing below...
NSMutableString *result = [[NSMutableString alloc] initWithString:#"\n"];
NSMutableString *rowtmp;
for (i = 0; i<iterations; i++) {
rowtmp = [NSMutableString stringWithString:#""];
for (b = 0; b<chars; b++) {
if (solutions[i][b] != 0) [rowtmp appendFormat:#"%i",solutions[i][b]];
else [rowtmp appendString:#" "]; // replace any 0s with spaces.
}
[result appendFormat:#"%#\n",rowtmp];
}
NSLog(#"%#",result);
[result release];
I have a feeling the problem may be to do with the offset, but I have no idea how to fix it. If anyone can spot where my code is going wrong, that would be great.
It appears (from a brief look) that the original midpoint calculation is incorrect. I think it should simply be:
mid = iterations - 1;
In the example of 5 iterations, the midpoint needs to be at array position 4. Each iteration "moves" one more position to the left. The 2nd iteration (2nd row) would then place a 1 at positions 3 and 5. The 3rd iteration at 2 and 6. The 4th at 1 and 7. And the 5th and last iteration would fill in the 1s at 0 and 8.
Also, the second if statement for the temp addition should be as follows otherwise it reads past the end of the array bounds:
if (chi < iterations - 1) {