From aee479000c2e739c31b89296281f2983ade10627 Mon Sep 17 00:00:00 2001 From: Yan-Hua Date: Mon, 23 Jun 2025 22:27:49 -0400 Subject: [PATCH] initial commit --- pipe_cc.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 pipe_cc.c diff --git a/pipe_cc.c b/pipe_cc.c new file mode 100644 index 0000000..df3b015 --- /dev/null +++ b/pipe_cc.c @@ -0,0 +1,157 @@ +/* + Author: Alexander Wong +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#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. +} \ No newline at end of file