在 C 中的管道上写入

问题描述 投票:0回答:2

我正在尝试创建一个基本上有 2 个进程的程序。第一个从用户那里获取一个字符串并将其传递给另一个。第二个从管道中读取字符串。将其大写然后将其发送回第一个进程。第一个然后打印 2 个刺。

我的代码确实传递了字符串,其他进程读取它并将其大写,但我认为第二次写入或第二次读取时存在错误。这是代码:

#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;
}
c pipe
2个回答
4
投票

这是一个双管道解决方案的演示...保留您使用的“scanf()”,它仅捕获第一个单词...而不是所有输入:

#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;
}

0
投票
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;
}
© www.soinside.com 2019 - 2024. All rights reserved.