2017-02-19 24 views
-2

Невозможно обработать функцию трубы, где даны трубы, в которых один процесс отправляет строковое сообщение второму процессу, а второй процесс меняет регистр каждого символа в сообщении и отправляет его обратно первый процесс.Невозможно обработать функцию трубы

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <string.h> 
#include <ctype.h> 
#include <assert.h> 
    #include <stdbool.h> 

    // Parent: reads from P1_READ, writes on P1_WRITE 
    // Child: reads from P2_READ, writes on P2_WRITE 

#define P1_READ  0 
#define P2_WRITE 1 
#define P2_READ  2 
#define P1_WRITE 3 

// the total number of pipe *pairs* we need 
#define NUM_PIPES 2 
/* 
toggleString accepts an a pointer to char array, allocates size for the  
string to be toggled, 
    copys the argument into a string, loops through the string and for every 
uppercase character 
we set it to its lower case counterpart and vice versa, returning the 
    toggled string 
    */ 
    char *toggleString(char *argv){ 

int i;  /* Declare counter */ 

char *str = malloc(sizeof(argv[1])); /* Declare array sizeof input */ 

strcpy(str, argv); /* Copy String to char array */ 

for(i=0;str[i]!='\0';i++) { //Loop through length of string 

    if(str[i]>='A'&&str[i]<='Z'){ //if the array at i is uppercase 

    str[i]+=32;   //Make it lower case 

    } else if (str[i]>='a'&&str[i]<='z') {// if the array at i is lowercase 

    str[i]-=32;    //Make it uppercase 

    } 

} 

    return str; 

    } 

    /* 
    int inputValidation accept and integer (number of arugments) and a  
pointer to the cmd line input array 
    We check to see if the command line input contains the minimal number of  
arugments and check to see  
    whether or not the user input contains at least one reversible haracter,  
if all goes well we return 0 
*/ 
    int inputValidation(int argc, char *argv[]){ 

    int i;   //Declare counter variable 

    bool c = false; //Declare boolean flag using imported <stdbool.h> 

    char str[strlen(argv[1])]; //Declare str 

    strcpy(str, argv[1]); //copy argument into str 

    if (argc != 2) { // check to see if we have enough arguments to 
    continue  
         // Prompt user of correct usage 

    fprintf(stderr, "\nUsage: %s <string> or <'string 1, string 2', ...,     

    string n'> for multiple strings\n", argv[0]); 

    exit(EXIT_FAILURE); //Exit on improper input 

    } else { 
       //loop through our string 
    for(i=0;i<strlen(str);i++) { 
       //if any any char is a reversible character 
    if(isalpha((int) str[i])){ 

     c = true; //set the flag to true 

    } 

    } 

    if(c == false){ //If flag is false input does not contain any 

    reversible charachters 

      printf("\nSorry, The string you entered did NOT contain any  

     Alphabetical Characters\nRun me again, with at least 1 Alphabetical  

     character\n\n"); 

     exit(EXIT_FAILURE); //Exit on improper input 

    } 

    return (0); 

    }  

    } 

/* Main принимает входные данные из командной строки, вызывает проверку входных данных, чтобы убедиться в
соответствующего входе, затем создает трубу нам понадобятся и вилы дочернего процесс родительский
и ребенок выполнить они соответствующий код */

int main(int argc, char *argv[]) { 

    assert(argc>1); 

    int fd[2*NUM_PIPES]; //Declare int[] of file descriptors 

    int len, i;    //Declare length and integer for count 

    pid_t pid;    //Declare process id 

    char parent[strlen(argv[1])]; //Declare Parent array 

char child[strlen(argv[1])]; //Declare Child array 

if(inputValidation(argc, argv) == 0) /* Check for proper input */ 

    strcpy(parent, argv[1]); 

// create all the descriptor pairs we need 
    for (i=0; i<NUM_PIPES; ++i) 
    { 
    if (pipe(fd+(i*2)) < 0) 
    { 
     perror("Failed to allocate pipes"); 
     exit(EXIT_FAILURE); 
    } 
    } 

// fork() returns 0 for child process, child-pid for parent process. 
    if ((pid = fork()) < 0) 
    { 
    perror("Failed to fork process"); 
    return EXIT_FAILURE; 
    } 
//////////////////////////////Childs Code  
BEGINS////////////////////////////////// 


// if the pid is zero, this is the child process 
    if (pid == 0) 
    { 
    // Child. Start by closing descriptors we 
    // don't need in this process 
    close(fd[P1_READ]); 
    close(fd[P1_WRITE]); 

    // used for output 
    pid = getpid(); 

    // wait for parent to send us a value 
    len = read(fd[P2_READ], &child, len); 
    if (len < 0) 
    { 
     perror("Child: Failed to read data from pipe"); 
     exit(EXIT_FAILURE); 
    } 
    else if (len == 0) 
    { 
     // not an error, but certainly unexpected 
     fprintf(stderr, "Child: Read EOF from pipe"); 
    } 
    else 
    { 

      // report pid to console 
     printf("Child(%d): Recieved Message\n\nChild(%d): Toggling Case and 
    Sending to Parent\n",pid, pid); 

     // send the message to toggleString and write it to pipe// 
     if (write(fd[P2_WRITE], toggleString(child), strlen(child)) < 0) 
     { 
      perror("Child: Failed to write response value"); 
      exit(EXIT_FAILURE); 

     } 

    } 

    // finished. close remaining descriptors. 
    close(fd[P2_READ]); 
    close(fd[P2_WRITE]); 

    return EXIT_SUCCESS; 
    } 
    //child code ends/// 
//////////////////////////////Parent Code  
BEGINS////////////////////////////////// 

    // Parent. close unneeded descriptors 
    close(fd[P2_READ]); 
    close(fd[P2_WRITE]); 

    // used for output 
    pid = getpid(); 

    // send a value to the child 

    printf("\nParent(%d): Sending %s to Child\n\n", pid, argv[1]); 
    if (write(fd[P1_WRITE], argv[1], strlen(argv[1])) != strlen(argv[1])) 
    { 
    perror("Parent: Failed to send value to child "); 
    exit(EXIT_FAILURE); 
    } 

    // now wait for a response 
    len = read(fd[P1_READ], &parent, strlen(parent)); 
    if (len < 0) 
    { 
    perror("Parent: failed to read value from pipe"); 
    exit(EXIT_FAILURE); 
    } 
    else if (len == 0) 
    { 
    // not an error, but certainly unexpected 
    fprintf(stderr, "Parent(%d): Read EOF from pipe", pid); 
    } 
    else 
    { 
    // report what we received 
    printf("\nParent(%d): Received %s from Child\n\n", pid, parent); 
    } 

    // close down remaining descriptors 
    close(fd[P1_READ]); 
    close(fd[P1_WRITE]); 

    // wait for child termination 
    wait(NULL); 

    return EXIT_SUCCESS; 

    } 
    //////////////////////////////Parent Code  
ENDS////////////////////////////////// 
+1

пожалуйста выбрал один язык С или C++ –

+0

Это не действительный C++ код. – melpomene

+2

Если вы отформатируете свой код более аккуратно, тем легче читать другим. Я даже не буду смотреть на код, который не имеет должным образом отступы. – Galik

ответ

1

Это работает:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <string.h> 
#include <ctype.h> 
#include <assert.h> 
#include <stdbool.h> 

#define P1_READ  0 
#define P2_WRITE 1 
#define P2_READ  2 
#define P1_WRITE 3 

#define NUM_PIPES 2 

static 
char *toggleString(char *argv) 
{ 
    int i; 

    char *str = malloc(strlen(argv) + 1); /* Key Fix */ 

    strcpy(str, argv); 

    for (i = 0; str[i] != '\0'; i++) 
    { 
     if (str[i] >= 'A' && str[i] <= 'Z') 
     { 
      str[i] += 32; 
     } 
     else if (str[i] >= 'a' && str[i] <= 'z') 
     { 
      str[i] -= 32; 
     } 
    } 

    return str; 
} 

static 
int inputValidation(int argc, char *argv[]) 
{ 
    bool c = false; 

    char str[strlen(argv[1])]; 

    strcpy(str, argv[1]); 

    if (argc != 2) 
    { 
     fprintf(stderr, "\nUsage: %s <string> or <'string 1, string 2', ..., string n'> for multiple strings\n", argv[0]); 
     exit(EXIT_FAILURE); 
    } 
    else 
    { 
     for (size_t i = 0; i < strlen(str); i++) 
     { 
      if (isalpha((int)str[i])) 
      { 
       c = true; 
      } 
     } 

     if (c == false) 
     { 
      printf("\nSorry, The string you entered did NOT contain any" 
        " Alphabetical Characters\nRun me again, with at least 1 Alphabetical" 
        " character\n\n"); 
      exit(EXIT_FAILURE); 
     } 

     return(0); 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    assert(argc > 1); 

    int fd[2 * NUM_PIPES]; 
    int len, i; 
    pid_t pid; 
    char parent[strlen(argv[1])]; 
    char child[strlen(argv[1])]; 

    if (inputValidation(argc, argv) == 0) 
     strcpy(parent, argv[1]); 

    for (i = 0; i < NUM_PIPES; ++i) 
    { 
     if (pipe(fd + (i * 2)) < 0) 
     { 
      perror("Failed to allocate pipes"); 
      exit(EXIT_FAILURE); 
     } 
    } 

    if ((pid = fork()) < 0) 
    { 
     perror("Failed to fork process"); 
     exit(EXIT_FAILURE); 
    } 

    if (pid == 0) 
    { 
     close(fd[P1_READ]); 
     close(fd[P1_WRITE]); 

     pid = getpid(); 

     len = read(fd[P2_READ], child, sizeof(child)); 
     if (len < 0) 
     { 
      perror("Child: Failed to read data from pipe"); 
      exit(EXIT_FAILURE); 
     } 
     else if (len == 0) 
     { 
      fprintf(stderr, "Child: Read EOF from pipe\n"); 
     } 
     else 
     { 
      child[len] = '\0'; 
      printf("Child(%d): Received Message [%s]\nChild(%d): Toggling Case and Sending to Parent\n", pid, child, pid); 
      char *toggled = toggleString(child); 
      printf("Child(%d): Sending [%s]\n", pid, toggled); 

      if (write(fd[P2_WRITE], toggled, len) < 0) 
      { 
       perror("Child: Failed to write response value"); 
       exit(EXIT_FAILURE); 
      } 
      free(toggled); 
     } 

     close(fd[P2_READ]); 
     close(fd[P2_WRITE]); 

     return EXIT_SUCCESS; 
    } 

    close(fd[P2_READ]); 
    close(fd[P2_WRITE]); 

    pid = getpid(); 

    printf("\nParent(%d): Sending [%s] to Child\n\n", pid, argv[1]); 
    len = strlen(argv[1]); 
    if (write(fd[P1_WRITE], argv[1], len) != len) 
    { 
     perror("Parent: Failed to send value to child"); 
     exit(EXIT_FAILURE); 
    } 

    len = read(fd[P1_READ], parent, sizeof(parent)); 
    if (len < 0) 
    { 
     perror("Parent: failed to read value from pipe"); 
     exit(EXIT_FAILURE); 
    } 
    else if (len == 0) 
    { 
     fprintf(stderr, "Parent(%d): Read EOF from pipe\n", pid); 
    } 
    else 
    { 
     parent[len] = '\0'; 
     printf("\nParent(%d): Received [%s] from Child\n\n", pid, parent); 
    } 

    close(fd[P1_READ]); 
    close(fd[P1_WRITE]); 

    wait(NULL); 

    return EXIT_SUCCESS; 
} 

Было больно извлекать ваш код из ваших комментариев, а также делиться на несколько строк строк и т. Д. Функция toggleString() была сломана - выделение 1 байт, а затем копирование строки над ней. Другой код не был осторожен в отношении нулевых строк и их обработки. Это в основном проблемы, диагностированные в комментариях.

Пример запуска:

$ pp53 'AbSoLuTeLy GlOrIoUs' 

Parent(5209): Sending [AbSoLuTeLy GlOrIoUs] to Child 

Child(5210): Received Message [AbSoLuTeLy GlOrIoUs] 
Child(5210): Toggling Case and Sending to Parent 
Child(5210): Sending [aBsOlUtElY gLoRiOuS] 

Parent(5209): Received [aBsOlUtElY gLoRiOuS] from Child 

$