2012-10-13 222 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