user312642
user312642

Reputation: 37

write on pipe in C

I am trying to create a program that is basically has 2 processes. the first takes a string from the user and passes it to the other. the 2nd read the string from the pipe. capitalize it then send it back to the first process. the 1st then print the 2 stings.

My code does pass the String and the other process reads it and capitalize it but I think there is an error in either writing the 2nd time or reading the 2nd time. here is the code:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#define SIZE 15

int main() {
    int fd[2];
    pipe(fd);
    if(fork() == 0) {
        char message[SIZE];
        int length;
    
        close(fd[1]);
        length = read(fd[0], message, SIZE);
        for(int i=0;i<length;i++) {
            message[i]=toupper(message[i]);
        }
        printf("%s\n",message);
        close(fd[0]);
    
        open(fd[1]);
        write(fd[1], message, strlen(message) + 1);
        close(fd[1]);
    } else {
        char phrase[SIZE];
        char message[SIZE];
        printf("please type a sentence : ");
        scanf("%s", phrase);
        close(fd[0]);
        write(fd[1], phrase, strlen(phrase) + 1);
        close(fd[1]);
    
        sleep(2);
    
        open(fd[0]);
        read(fd[0], message, SIZE);
        close(fd[0]);
        printf("the original message: %s\nthe capitalized version: %s\n",phrase,message);
    }
    return 0;
}

Upvotes: 1

Views: 31619

Answers (2)

Robert Petersen
Robert Petersen

Reputation: 35

Thank you very much for posting, I want to share my variation of this that I built upon for an assignment - I found this while trying to debug a const to char problem with the sample code we were given.

Some changes to mine are accepts the entire data value, transforms the data when piping and is much larger buffer space

Again - thank you for posting, the code I was given was more difficult for me to understand, I've included references to variations for those that may be interested and to how I made changes.

// Message Passing and Case Reversal: Done
// Pipe Creation: Done
// Output Messages: Done 
// Art : Done
// Testing :  Done
// Error Handling : Done
// Makefile :

#include <stdio.h>
#include <unistd.h>
#include <ctype.h>   // for toupper
#include <string.h>
#include <signal.h>
#include <iostream>
#define SIZE 10000      // intrinsic to functionality [pipe capacity 16 []]

using namespace std;


// This code is referenced here, and built upon after references
// https://stackoverflow.com/questions/47503798/write-on-pipe-in-c/47503999#47503999

// references
// https://cboard.cprogramming.com/c-programming/145884-two-pipes-send-string-between-parent-child-process.html
// https://www.geeksforgeeks.org/demostrating-bidirectional-communication-using-ordinary-pipe/
// https://unix.stackexchange.com/questions/649553/pipe-output-from-process-substitution-to-variable
// https://stackoverflow.com/questions/47503798/write-on-pipe-in-c/47503999#47503999
// https://www2.cs.uregina.ca/~hamilton/courses/330/notes/unix/pipes/pipes.html
// https://www.programiz.com/cpp-programming/library-function/cctype/isupper#:~:text=int%20isupper(int%20ch)%3B,to%2090)%20are%20uppercase%20characters.
// https://www.geeksforgeeks.org/taking-string-input-space-c-3-different-methods/
// https://stackoverflow.com/questions/8158516/invalid-conversion-from-const-char-to-char-error
// https://www.programiz.com/cpp-programming/examples/ASCII-value-character

// error handling for this takes form of else statements and recognition
// that the code will not function if an error occurs i.e if fork does not occur
// the pipe will effectively open for whatever is written an then close
// however as the fork if broken, the pipe will have no functionality
// 

int main()

// pip[0] - the read end of the pipe - is a file descriptor used to read from the pipe
// pip[1] - the write end of the pipe - is a file descriptor used to write to the pipe

{
    int to_child_fd[2];
    int to_parent_fd[2];
    pipe(to_child_fd);
    pipe(to_parent_fd);

    // the reason for forking here is both processes have been made known to
    // each other with the pipe command so that they can see each other 
    // the code structure is non-linear per the piping.

    if (fork() == 0) {
    char message[SIZE];  // if you use string it will not pass through the write
    
    int length;

    close(to_child_fd[1]);  /* child closes write side of child  pipe */
    close(to_parent_fd[0]); /* child closes read  side of parent pipe */
    
    //careful of sizing here, stack smashing possible
    
    // * 4 to make space for the art transformations
    length = read(to_child_fd[0], message, SIZE) *4;
    
    // isupper checks for uppercase: returns non-zero if uppercase 
    // for loop counter reverts, cannot change loop counter in loop
    for (int i = 0; i < length; i++) 
        {
        if(isupper(message[i]) == 0 )   // if is uppercase
        {
            message[i] = toupper(message[i]);
        }
        else if(islower(message[i]) == 0)  // if is lowercase
        {
        message[i] = tolower(message[i]);
        }
        else
        {
            message[i] = message[i];
        }
    }
    char Art[SIZE];
    int k = 0;
    for ( int j = 0; j<length; j++)
    {
        // this statement, for some reason isupper and islower
        // spaces and everything will transform artistically without this
    if(message[j] < 65 )
    {
        Art[k] = message[j];
        k += 1;
    }
        // cout << j;
    else if(isupper(message[j]) == 0)
    {
    Art[k] = '[';
    Art[k+1] = '-';
    Art[k+2] = message[j];
    Art[k+3] = '-';
    Art[k+4] = ']';
    k += 5;
    }
    // for some reason, islower and isupper will register the space
    // and add art transformations when should not!
    else if(islower(message[j]) == 0)
    {
        Art[k] = '(';
        Art[k+1] = message[j];
        Art[k+2] = ')';
        k += 3;   // one address higher than the last
    }
    else
    {
        Art[k] = ' ';
    }
    }
    
    // recopying the array to prove function rather than changing variable
    // names - this loop is an redundancy
    for(int k = 0; k<length; k++)
    {
        message[k] = Art[k];
    }
    
    printf("child: %s\n", message);
    write(to_parent_fd[1], message, strlen(message) + 1);
    close(to_parent_fd[1]);
    } else {
    
    char phrase[SIZE];
    char message[SIZE];
    
    
    printf("please type a sentence : ");
    scanf("%[^\n]%*c", phrase);   // what intakes input
    close(to_parent_fd[1]); /* parent closes write side of parent pipe */
    close(to_child_fd[0]);  /* parent closes read  side of child  pipe */
    write(to_child_fd[1], phrase, strlen(phrase) + 1);
    close(to_child_fd[1]);

    read(to_parent_fd[0], message, SIZE);
    printf("the parent message: %s\nthe child message: %s\n", phrase, message);
    }
    return 0;
}

Upvotes: 0

TonyB
TonyB

Reputation: 947

Here's a demo of a two-pipe solution... keeping the "scanf()" you imployed which only captures the first word... not all input:

#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>

#define SIZE 15

int main()
{
    int to_child_fd[2];
    int to_parent_fd[2];
    pipe(to_child_fd);
    pipe(to_parent_fd);

    if (fork() == 0) {
    char message[SIZE];
    int length;

    close(to_child_fd[1]);  /* child closes write side of child  pipe */
    close(to_parent_fd[0]); /* child closes read  side of parent pipe */
    length = read(to_child_fd[0], message, SIZE);
    for (int i = 0; i < length; i++) {
        message[i] = toupper(message[i]);
    }
    printf("child: %s\n", message);
    write(to_parent_fd[1], message, strlen(message) + 1);
    close(to_parent_fd[1]);
    } else {

    char phrase[SIZE];
    char message[SIZE];
    printf("please type a sentence : ");
    scanf("%s", phrase);
    close(to_parent_fd[1]); /* parent closes write side of parent pipe */
    close(to_child_fd[0]);  /* parent closes read  side of child  pipe */
    write(to_child_fd[1], phrase, strlen(phrase) + 1);
    close(to_child_fd[1]);

    read(to_parent_fd[0], message, SIZE);
    printf("the original message: %s\nthe capitalized version: %s\n", phrase, message);
    }
    return 0;
}

Upvotes: 4

Related Questions