2017-11-25 12 views
0

私のプログラムでは、出力を一時バッファに格納しパイプを通過させる必要があるいくつかの物理計算を行っています。Cで一時バッファを作成するにはどうしたらいいですか?

バッファは異なるデータ型を共有する必要があります。まず、私が勉強している対象の名前を格納する必要があります。第二に私の計算の結果(すべてfloat数字)。

Aston Martin Vantage V12|07.7|090 
Ferrari LaFerrari  |09.6|111 
Lamborghini Aventador |09.6|097 
Porsche 911 Turbo S  |09.6|092 
Tesla Model S P100D  |10.0|069 
Hennessey Venom GT  |10.3|120 
Bugatti Chiron   |11.2|114 
Koenigsegg Agera  |10.3|121 

main.cの initialdata.dat:

コードは次のようになります

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <sys/time.h> 
#include <string.h> 
#include <time.h> 
#include <math.h> 

#define READ 0 
#define WRITE 1 
#define M 2 // Number of subjects. 

int main(){ 
    int pipeToChild[2]; 
    if (pipe(pipeToChild) < 0) { 
     fprintf(stderr,"Error in pipe!"); 
     return -1; 
    } 

    pid_t pid[M]; 
    srand (time(NULL)); 

    // Declares the file pointer with the information. 
    FILE * pFile; 
    char buffer[34]; // Buffer where subject info is sent to childs. 
    char tempBuffer[50]; // The buffer that causes problems. 
    pFile = fopen ("initialdata.dat","r"); 

    for(int i = 0; i < M; i++){ 
     pid[i] = fork(); 
     if (pid[i] < 0){ 
      printf("Fork error!\n"); 
      return -1; 
     } 
     else if(pid[i]==0){ 
      // Creates the pipes (one per child) to pass the temporary buffer to the results process (still not created). 
      int pipeToResults[2]; 
      if (pipe(pipeToResults) < 0) { 
       fprintf(stderr,"Error in pipe!"); 
       return -1; 
      } 

      // Receives the car information from the file through a pipe. 
      char receivedValue[34]; 
      receivedValue[33] = '\0'; 
      close(pipeToChild[WRITE]); 
      read(pipeToChild[READ], receivedValue, sizeof(receivedValue)); 

     // Processes the information and tokenizes it. 
      char name[25]; 
      char CHARacceleration[6]; 
      char CHARmaxSpeed[4]; 
      strcpy(name, strtok(receivedValue, "|")); 
      strcpy(CHARacceleration, strtok(NULL, "|")); 
      strcpy(CHARmaxSpeed, strtok(NULL, "|"));  
      float acceleration = atof(CHARacceleration); 
      float maxSpeed = atoi(CHARmaxSpeed); 

      // Adds 0.0X to acceleration. 
      float randomNum = rand() % 5; 
      acceleration = acceleration + randomNum/100; 

      float distance = 0; 
      float TA = 0; // Time using Uniformly Accelerated Linear Motion. 
      float TB = 0; // Time using Linear Motion. 
      float TE = 0.5; // Time increment. 
      float currentVelocity = 0; // In m/s. 

      // Applies different physical calculations depending on the case. 
      while (distance <= 1000){ 
       TA += TE; 
       if (currentVelocity < maxSpeed){ // Acceleration > 0 
        distance = (acceleration*pow((TA),2))/2; 
        currentVelocity = acceleration*TA; 
        distance = 2*distance; 
       } 
       else{ // Acceleration = 0 
        TB += TE; 
        currentVelocity = maxSpeed; 
        distance += maxSpeed*TB; 
       } 
      } 

      // Debug purposes, just for ensuring everything gets processed the right way. 
      printf("Name: %s\n", name); 
      printf("Distance: %.2f m\n", distance); 
      printf("Time: %.2f s\n", TA+TB); 
      printf("Max speed reached: %.2f km/h\n", currentVelocity*3.6); 
      printf("Acceleration: %.2f m/s^2\n", acceleration); 
      printf("\n"); 

     // Comment this if you want to switch between the situations I talked about. 
     sprintf(tempBuffer, "%s %.2f %.2f %.2f %.2f", name, distance, TA+TB, currentVelocity, acceleration); 
      printf("Buffer: %s\n\n", tempBuffer); 
      exit(0); 
     } 
     else if(pid[i]>0){ 
      // Generates a random subject from the list. Buggy section, fixed it the best way I could. 
      int randCar = rand() % 15 + 1; 
      if (randCar % 2 == 0) 
       randCar--; 
      for (int i = 1; i <= randCar; i++){ 
       if (pFile != NULL) 
        fgets (buffer, sizeof(buffer), pFile); 
       else 
        perror ("ERROR reading file!"); 
      } 
      char toSend[34]; //This will be passed through the `pipeToChild` pipe. 
      strcpy(toSend, buffer); 

      // Loads pipe. 
      close(pipeToChild[READ]); 
      write(pipeToChild[WRITE], toSend, strlen(toSend)); 
      close(pipeToChild[WRITE]); 
     } 
    } 
    for (int i=0;i<M;i++){ 
     waitpid(pid[i], NULL, 0); 
    } 
    fclose(pFile); 
    return 0; 
} 

出力は、しかし、私が使用している場合によって異なりますsprintfかどうか。例えば、M = 2の場合、出力は次のようになります。

ケース1:いいえsprintf

I'm the child process 1 with PID 12304 
Name: Bugatti Chiron   
Distance: 1012.61 m 
Time: 9.50 s 
Max speed reached: 383.72 km/h 
Aceleration: 11.22 m/s^2 

I'm the child process 2 with PID 12305 
Name: Bugatti Chiron   
Distance: 1012.61 m 
Time: 9.50 s 
Max speed reached: 383.72 km/h 
Aceleration: 11.22 m/s^2 

ケース2:sprintf

I'm the child process 2 with PID 12307 
I'm the child process 1 with PID 12306 
Name: Bugatti Chiron   
Distance: 1012.61 m 
Time: 9.50 s 
Max speed reached: 383.72 km/h 
Aceleration: 11.22 m/s^2 
Buffer: Bugatti Chiron 1012.61 9.50 383.82 11.22 

に問題は何「スプリント」?なぜこの線はプログラム全体をねじ込んでいるのですか?

EDIT:このプログラムは、M台の車が1000mの直線で競争する単純なドラッグレーシングシミュレータです。 masterプロセスはM個のランダムな車を作成しますが(この機能は正しく実装されていません)、の単一パイプを介して.datファイルに保存されたデータをM個の子プロセスに渡します。

すべての車は、子プロセスであり、計算が行われる場所にあります。値を取得すると、すべての子は、自身のパイプ~ というプロセスを介して、一時ファイルに格納されたデータを出力ファイルに格納します。最初にバッファを作成する必要があるため、この関数は実装されていないことに注意してください。私の質問は、のみですバッファの問題についてです。

enter image description here

+0

[最小、**完全**、および検証可能な例](http:// stackoverflow。com/help/mcve)それは具体的なことを言うのが非常に難しくなります。我々ができるのは*推測*です(おそらくひどく推測されます)。そして、[良い質問をする方法について](http://stackoverflow.com/help/how-to-ask)を読んでください。 –

+0

しかし、それはスケジューラの処理を制御できないためです。追加の 'sprintf'呼び出しによって、スケジューラが予期せずプロセスを切り替える可能性がありますか?これは、出力バッファリングと一緒に、マルチプロセスプログラムで出力の問題を引き起こす可能性があります。 –

+0

コメント '// printf'を持つ' ... 'は非常に問題になりそうです。 'printf'を呼び出して出力バッファをフラッシュせずにforkを呼び出すと、出力が重複します。ループの最後に 'flush'を追加してみてください。 –

答えて

1

あなたfork、新しいプロセスを作成します。どんなタイプの同期もなければ、作成される2つの子プロセスは同時に実行されます。したがって、各子の出力は、OSが各プロセスをスケジュールする方法に応じて、相互にインターリーブされる場合があります。 sprintfの存在はそれを変更しません。

パイプを介してメッセージを渡す必要があるため、各プロセスがいつ同期するかを制御するためにプロセスを同期させる必要があります。

0

char tempBuffer[50];は、送信したデータの正確なサイズである34の代わりに50に初期化されました。

+0

しかし、各フロートが7文字で表現されていて、各番号の間に1つのスペースがあり、タイトルの場合は「31」文字+「25」文字、バッファオーバーランの場合は「6」文字です。あなたは*未定義行動*のためにレッドカーペットをロールアウトしました。バッファサイズをスキップしないでください。 '256'はここに十分な余裕を持たせるべきです。 –

関連する問題