initial commit
This commit is contained in:
157
pipe_cc.c
Normal file
157
pipe_cc.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
Author: Alexander Wong
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#define READ_END 0
|
||||
#define WRITE_END 1
|
||||
#define BUFFER_SIZE sizeof(long long int)
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// Create pipe file descriptors with two ends.
|
||||
int fdIn[2]; // Pipe for sending numbers.
|
||||
|
||||
pid_t pid; // Create new PID for holding the forks PID value
|
||||
|
||||
if (pipe(fdIn) < 0) {
|
||||
// Initialize and check if pipes were properly created.
|
||||
fprintf(stderr, "There was an issue creating the pipes.\n");
|
||||
return 1; // Return 1, there was an issue.
|
||||
}
|
||||
|
||||
if (argc != 2) {
|
||||
// Check if there are an unexpected number of arguments.
|
||||
// Value is set to 2 because the first argument is always the program binary being executed.
|
||||
fprintf(stderr, "Invalid number of arguments, expected one. Got %u.\n", argc - 1);
|
||||
return 1; // Return 1, there was an issue.
|
||||
}
|
||||
|
||||
for (int i = 0; i < strlen(argv[1]); i++) {
|
||||
// Iterates over each value to check and see if it is a digit in the input string.
|
||||
// This will handle negatives automatically since the - character is not considered
|
||||
// as a negative in the isdigit() function.
|
||||
if (!isdigit((argv[1][i]))) {
|
||||
fprintf(stderr, "Input must be a valid positive integer.\n");
|
||||
return 1; // Return 1, there was an issue.
|
||||
}
|
||||
}
|
||||
|
||||
long long int input = atoll(argv[1]); // Convert the first argument to an int.
|
||||
|
||||
if (input <= 0) {
|
||||
// Checks to make sure the value is non-zero and not negative.
|
||||
// A negative number shouldn't make it here however.
|
||||
fprintf(stderr, "Integer cannot be 0 or negative.\n");
|
||||
return 1; // Return 1, there was an issue.
|
||||
}
|
||||
|
||||
pid = fork(); // Fork the process
|
||||
|
||||
|
||||
if (pid > 0) {
|
||||
/* If the PID is greater than 0, this is the parent process.
|
||||
|
||||
The parent process is responsible for informing the child process
|
||||
what number to generate the collatz conjecture sequence for. This
|
||||
input is expected to be an integer value that is non-negative or zero.
|
||||
|
||||
Once the child has finished producing the collatz conjecture sequence,
|
||||
the parent process will then read the pipe that the child users to write
|
||||
to the parent and output the collatz conjecture sequence. It will also
|
||||
record the maximum value found in the sequence and the number of steps
|
||||
taken while generating the collatz conjecture sequence. These are output
|
||||
as (s, m) where s being the number of steps and m being the max.
|
||||
|
||||
*/
|
||||
close(fdIn[WRITE_END]); // Close the write end of the pipe since we're not writing.
|
||||
|
||||
int status;
|
||||
wait(&status); // Wait for the child process to exit.
|
||||
int returnCode = WEXITSTATUS(status); // Retrieve the status code.
|
||||
|
||||
if (returnCode == 1) {
|
||||
// Report there was an error if the error code is 1.
|
||||
fprintf(stderr,
|
||||
"There was an error while generating the collatz conjecture sequence.\n"
|
||||
"Your input of %lld was likely too large, we exceeded the max length,\n"
|
||||
"or something else happened.\n", input);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int remainingBytes; // Used to determine if we still have bytes to read in the pipe.
|
||||
long long int collatzNumber; // Represents the current number in the collatz conjecture sequence beign read.
|
||||
int counter = 0; // Initialize a count of 0, used to determine the number of steps.
|
||||
long long int peak = 0; // The max value found in the collatz conjecture sequence.
|
||||
|
||||
bool inputWasOne = false;
|
||||
if (input == 1)
|
||||
// If the input was 1, set true.
|
||||
inputWasOne = true;
|
||||
|
||||
while ((remainingBytes = read(fdIn[READ_END], &collatzNumber, BUFFER_SIZE)) > 0) {
|
||||
// This loop checks to make sure there are bytes to read and if so will increment
|
||||
// the counter and record the peak of the collatz conjecture sequence. It will then
|
||||
// output the number to produce the sequence in stdout.
|
||||
if (collatzNumber > peak) peak = collatzNumber; // Set the new max value
|
||||
|
||||
if (collatzNumber == 1 && !inputWasOne)
|
||||
// If the value is one, drop the comma as it's the last in the sequence.
|
||||
fprintf(stdout, "%lld ", collatzNumber);
|
||||
else
|
||||
fprintf(stdout, "%lld, ", collatzNumber);
|
||||
|
||||
if (inputWasOne) inputWasOne = false; // Clear statement to enable writing 1.
|
||||
|
||||
counter++; // Increment the counter
|
||||
}
|
||||
counter--; // Decrement counter by 1 since the input does not count.
|
||||
fprintf(stdout, "(%d, %lld)\n", counter, peak); // Output the, s, number of steps and, m, max. (s, n)
|
||||
close(fdIn[READ_END]); // Close the pipe.
|
||||
}
|
||||
// Child
|
||||
else if (pid == 0) {
|
||||
/* If the PID is equal to 0, this is the child process.
|
||||
|
||||
The child process is responsible for producing the collatz conjecture
|
||||
sequence for the number provided by the parent. This sequence is then
|
||||
written back to the parent over the pipe.
|
||||
|
||||
*/
|
||||
long long int collatzNumber = input; // Used to hold the number used in the collatz conjecture sequence.
|
||||
|
||||
close(fdIn[READ_END]); // Close the read end of the pipe, no more inputs expected.
|
||||
write(fdIn[WRITE_END], &collatzNumber, BUFFER_SIZE); // Write input to pipe.
|
||||
|
||||
do {
|
||||
// This loop performs the collatz conjecture algorithm to produce
|
||||
// the collatz conjecture sequence. A do loop is required because
|
||||
// the collatz conjecture is still performed om 1 and standard while
|
||||
// loop will not treat it as such and assume it is done.
|
||||
|
||||
if (collatzNumber % 2 == 0) {
|
||||
// If the number is even divide by two.
|
||||
collatzNumber = collatzNumber / 2;
|
||||
} else {
|
||||
// If the number is odd, multiply it by 3 and add 1.
|
||||
collatzNumber = 3 * collatzNumber + 1;
|
||||
}
|
||||
write(fdIn[WRITE_END], &collatzNumber, BUFFER_SIZE); // Write the number to the pipe.
|
||||
} while (collatzNumber > 1);
|
||||
|
||||
if (collatzNumber <= 0) exit(EXIT_FAILURE); // If the number is negative or 0, an error or overflow occurred.
|
||||
|
||||
close(fdIn[WRITE_END]); // Close the write end of the pipe.
|
||||
return 0; // Return 0, no issues.
|
||||
}
|
||||
return 0; // Return 0, no issues.
|
||||
}
|
||||
Reference in New Issue
Block a user