2012-10-13 218 views
0

你好有一個多進程編程的任務,我面臨着一個問題,當我嘗試逐行讀取字符(每行包含3個字符和1個整數)。問題是當我使用fscanf時,它不能正常工作,並且它只是每2步成功讀取一次字符。在這裏你可以看到我的代碼;fscanf does not work properly

#include <stdio.h>  /* basic I/O routines. */ 
#include <stdlib.h> 
#include <unistd.h> /* define fork(), etc. */ 
#include <sys/types.h> /* define pid_t, etc. */ 
#include <sys/wait.h> /* define wait(), etc. */ 
#include <signal.h> /* define signal(), etc. */ 
#include <pthread.h> 
#include <ctype.h> 

void child_process(int); 
void parent_process(); 
void function(); 
int counter=0; 
int bond_number=0; 

char* f_strand; 

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

    counter = atoi(argv[1]); 

    function(); 

    fflush(stdout); 

    execl("/usr/bin/killall","killall","tail",(char *) 0); 
    return 0; 
} 

void function(){ 

    int i,k; 
    pid_t child_pid[counter]; 
    char array[counter]; 
    char array_opst[counter]; 
    srand (time(NULL)); 
    int temp; 

    FILE* fptr; 
    fptr = fopen("sample.txt","w"); 

    if(! (f_strand=(char*)malloc(counter*sizeof(char)))){ 
     printf("Error\n"); 
     exit(1); 
    } 

    for(i=0; i<counter; i++){ 

     temp = rand()%4; 

     if(temp==0){ 
      *(f_strand+i) = 'A'; 
      fprintf(fptr,"A\n"); 
     } 
     else if(temp==1){ 
      *(f_strand+i) = 'C'; 
      fprintf(fptr,"C\n"); 
     } 
     else if(temp==2){ 
      *(f_strand+i) = 'T'; 
      fprintf(fptr,"T\n"); 
     } 
     else if(temp==3){ 
      *(f_strand+i) = 'G'; 
      fprintf(fptr,"G\n"); 
     } 
    } 

    fclose(fptr); 

        for (i = 0; i < counter; i++) { 
         if ((child_pid[i] = fork()) < 0) { 

         perror("fork"); 
         abort(); 
         } 
         else if (child_pid[i] == 0) { 

         child_process(i); 
         exit(0); 
         } 
        } 
    int status; 
    pid_t pid; 
    int num=counter; 
     while (num > 0) { 
      pid = wait(&status); 
      //printf("Child with PID %ld exited with status 0x%x.\n", (long)pid, status); 
      --num; // Remove pid from the pids array. 
     } 


    parent_process(); 
    printf("\n"); 

} 

void child_process(int index){ 

    int i; 
    char str,str1,str2; 

    FILE* fptr; 
    fptr = fopen("sample.txt","r"); 

    fseek (fptr, 2*index, SEEK_SET); 
    fscanf(fptr,"%c", &str); 

    FILE* fptr2; 
    fptr2 = fopen("sample_2.txt","a"); 

     if(str == 'A'){ 
      str1='T'; 
      str2=';'; 
      fprintf(fptr2,"%c%c%c%d\n",str,str2,str1,index); 
      } 
     else if(str == 'T'){ 
      str1='A'; 
      str2=';'; 
      fprintf(fptr2,"%c%c%c%d\n",str,str2,str1,index); 
      } 
     else if(str == 'G'){ 
      str1='C'; 
      str2=':'; 
      fprintf(fptr2,"%c%c%c%d\n",str,str2,str1,index); 
      } 
     else if(str == 'C'){ 
      str1='G'; 
      str2=':'; 
      fprintf(fptr2,"%c%c%c%d\n",str,str2,str1,index); 
      } 

    fflush(stdout); 
    fclose(fptr); 
    fclose(fptr2); 
    sleep(1); 

} 

void parent_process(void){ 

    FILE* fptr; 
    fptr = fopen("sample_2.txt","r"); 

    char str,str1,str2; 
    int index,i,k; 
    char array_opst[counter]; // second strand 
    char array_type[counter]; // bond type 

    i=0; 

    while(!feof(fptr)){ 

     if(4==fscanf(fptr,"%c%c%c%d",&str,&str1,&str2,&index)){ 

      if(feof(fptr)) 
       break; 

      printf("STR = %c\n, K = %d",str,k); 

      array_type[index]=str1; 
      array_opst[index]=str2; 
      printf("WHILE\n"); 

      if(array_type[index] == ':') 
       bond_number=bond_number+2; 
      else if(array_type[index] == ';') 
       bond_number=bond_number+3; 
    } 

     i++; 
} 
    fclose(fptr); 

} 

這是sample2.txt

C:G5 
G:C6 
A;T4 
C:G3 
G:C7 
C:G8 
G:C2 
A;T9 
T;A1 
C:G0 

在它試圖讀取3個字符且從sample2.txt文件由行一個整數線parent_process()輸出。但它會在每兩行中執行此過程。我的意思是它讀取前三分之一的第五行並繼續。如果您能幫助並感謝,我將不勝感激。

+0

你可以用'sample2.txt'文件創建一個[SSCCE](http://sscce.org)來演示這種行爲嗎? – oldrinb

+1

東西告訴我'fscanf()'可能正常工作。 –

+1

您是否嘗試過使用較低級別的輸入例程,例如'fgets'甚至'read'? 'fscanf'幾乎總是比它的價值更麻煩。 – zwol

回答

3

這是一個有趣的多方面問題。首先要注意的是,您正在使用c轉換。 C99標準規定如下(§7.19.6.2¶ 8)。

輸入的空白​​字符(由isspace函數指定)被跳過,除非 說明書包括[c,或n說明符。

現在,讓我們來看看重要的一行。

if(4==fscanf(fptr,"%c%c%c%d",&str,&str1,&str2,&index)){ 

什麼發生的是,空白(條目之間的填料,線路終端器等)正在被消耗fscanf。發生這種情況時,讀取未對齊,因此在遇到d轉換時無法讀取整數。因此,fscanf不計算爲4,分支不被採用,因此不會打印錯誤讀取的數據。

取而代之的是,它需要錯誤地讀取每隔一行以重新對齊正確的輸入,因此您只能看到這些打印的選擇行。爲了證明這一點,試着用0 < fscanf(...)代替條件,不正確的讀取將產生輸出來證明讀取每隔一行的中間嘗試。

+0

這是一個解釋性回覆,感謝它。它工作時,我嘗試閱讀'\ n'作爲一個字符與'if(5 == fscanf(fptr,「%c%c%c%d%c」,&str,&str1,&str2,&index,&nl))' – quartaela

2

我假設問題是換行符。嘗試將其包含在格式字符串中或讀取連續fscanf()調用之間的額外字符。

+1

+1 [除非轉換規範包含'[','c','C'或'n'轉換說明符],否則應該跳過輸入空白字符(由'isspace()'指定) http://pubs.opengroup.org/onlinepubs/007904975/functions/scanf.html) – oldrinb