【问题标题】:reading characters line by line from a text file in c with multiprocessing使用多处理从c中的文本文件逐行读取字符
【发布时间】:2012-10-09 19:55:42
【问题描述】:

您好,我在阅读时遇到null 字符问题,并尝试在多进程程序中使用fseek() 函数打印文件的字符。这是我的简单代码,

#include <stdio.h>     /* basic I/O routines.   */
#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 <time.h>

void print_screen(int i);
int counter=0;

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

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

    int counter = atoi(argv[1]);
    int i,k;
    int temp;
    pid_t child_pid;
    int child_status;
    char array[counter];

    srand ( time(NULL) );

    for(i=0; i<counter; i++){
        temp = rand()%4;

        if( temp==0 ) {

            fprintf(fptr,"A\n");
            array[i]='A';
            }
        else if( temp==1 ) {

            fprintf(fptr,"C\n");
            array[i]='C';
            }
        else if( temp==2 ) {

            fprintf(fptr,"G\n");
            array[i]='G';
            }
        else if( temp==3 ) {

            fprintf(fptr,"T\n");
            array[i]='T';
            }
    }
    fclose(fptr);

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

                    child_pid = fork();

                       switch(child_pid) {

                        case -1:
                            printf("Error occured with fork()\n");
                            exit(1);

                        case 0: 
                            print_screen(i); /* Child Process */
                            exit(0);
                             }
            }

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

void print_screen(int i){

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

        fseek(fptr,i,SEEK_SET);
        fscanf(fptr,"%s",str);
        printf("Process Number %d, Character = %s\n",i,str);
        sleep(1);

    fclose(fptr);
    return;
    }

假设我在命令行中输入./sample 10,那么程序将在 sample.txt 中打印 10 个字符,然后将创建 10 个子进程,每个子进程都尝试选择一个字符并打印到屏幕上。此外,如你可以看到我发送i 作为参数来设置偏移量。但正如我提到的,它打印为空。这是该计划的前景。

Process Number 7, Character = (null)
Process Number 6, Character = (null)
Process Number 5, Character = (null)
Process Number 3, Character = (null)
Process Number 8, Character = (null)
Process Number 4, Character = (null)
Process Number 9, Character = (null)
Process Number 10, Character = (null)
Process Number 2, Character = (null)
Process Number 1, Character = (null)

txt文件是这样的。

G
A
A
T
G
C
C
A
A
T

如果您能提供帮助,我将不胜感激。

编辑:我意识到我像$ gcc sample.c -o sample -lpthread 一样编译它打印出空值。另一方面,我在没有-lpthread 的情况下编译它,它打印字符但不正确,例如这是文本文件。

T
G
G
T
G

终端给出这样的输出。

Process Number 1, Character = G
Process Number 2, Character = G
Process Number 3, Character = G
Process Number 4, Character = G
Process Number 5, Character = T

【问题讨论】:

    标签: c file-io multiprocessing fseek


    【解决方案1】:

    看看这个http://www.cs.nmsu.edu/~jcook/Tools/pthreads/pthreads.html

    您可能知道 fork() 会生成调用进程的副本,并且该副本(几乎)与原始副本相同 - 它们仅在 child = 1 中的 fork() 中有所不同

    尝试(并告诉我它是否有效,我无法测试它:)

                for(i=1; i<=counter; i++){
    
                    child_pid = fork();
    
                       switch(child_pid) {
    
                        case -1:
                            printf("Error occured with fork()\n");
                            exit(1);
                        case 0: 
                            print_screen(i); /* Child Process */
                            exit(0);
                        default: 
                            printf("...\n");
                             }
            }
    

    编辑:为我工作

    编辑:好吧,我做了一些测试,应该使用if 而不是case(还添加了文件内容的直接输出 - 如果文件大小增长,应该删除它);现在这就是我的代码:

    #include <stdio.h>     /* basic I/O routines.   */
    #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 <time.h>
    
    void print_screen(int i);
    int counter=0;
    
    int main(int argc, char* argv[]) {
    
    FILE* fptr;
    fptr = fopen("sample.txt","w");
    
    int counter = atoi(argv[1]);
    int i,k;
    int temp;
    pid_t child_pid;
    int child_status;
    char array[counter];
    
    srand ( time(NULL) );
    
    for(i=0; i<counter; i++){
        temp = rand()%4;
    
        if( temp==0 ) {
    
            fprintf(fptr,"A\n");
            printf("A\n");
            array[i]='A';
            }
        else if( temp==1 ) {
    
            fprintf(fptr,"C\n");
            printf("C\n");
            array[i]='C';
            }
        else if( temp==2 ) {
            fprintf(fptr,"G\n");
            printf("G\n");
            array[i]='G';
            }
        else if( temp==3 ) {
            fprintf(fptr,"T\n");
            printf("T\n");
            array[i]='T';
            }
    }
    fclose(fptr);
                for(i=1; i<=counter; i++){
    
                    child_pid = fork();
    
                        if (child_pid == -1){
                            printf("Error occured with fork()\n"); exit(-1);
                        }
                        else if (child_pid == 0){
                             print_screen(i); exit(0);
                        }
                        else{ printf("something \n"); }
            }
    
    wait(&child_status);
    execl("/usr/bin/killall","killall","tail",(char *) 0);
    return 0;
    }
    
    void print_screen(int i){
    
    char* str;
    FILE* fptr;
    fptr=fopen("sample.txt","r");
    
        fseek(fptr,i,SEEK_SET);
        fscanf(fptr,"%s",str);
        printf("Process Number %d, Character = %s\n",i,str);
        sleep(1);
    
    fclose(fptr);
    return;
    }
    

    它不能正常工作(我很确定当 pthreads 同时从文件中读取时会发生某种冲突),但至少你会有一些东西可以继续使用。

    我得到了这个输出:

    一个

    T

    一个

    T

    某事

    某事

    某事

    某事

    进程号 4,字符 = A

    进程号 3,字符 = A

    进程号 2,字符 = T

    进程号 1,字符 = T

    tail:未找到进程

    【讨论】:

    • 它对我不起作用,实际上它卡在死循环中,导致条件实际上永远不会是“1”。我猜有一个错误的情况导致child_pid 在子进程中返回0 而父进程应该default : _?当我将其更改为默认值并将孩子的条件设置为 0 时,它可以工作但不能正常工作。它打印错误的字符。
    • 是的,这就是我的意思!它打印错误的字符系列。
    • 正如我所说,这是因为分叉的进程都是独立的,并且没有任何东西可以控制它们打印出所读取字符的时间点。例如:p1 读取 A,p2 读取 B,p3 读取 C,p2 打印 B,p1 打印 A,p3 打印 C -> 文件为“A B C”但输出为“B A C”
    • 如果它是这样工作的,那就没有任何问题了。但问题是字符数不相等。例如,当我运行您的代码时,我得到了这个输入:A G T C CProcess Number 5, Character = C Process Number 3, Character = T Process Number 2, Character = G Process Number 1, Character = G Process Number 4, Character = T 所以没有处理打印出来的“A”字符
    【解决方案2】:

    您没有为 print_screen 中的 str 分配任何内存。 fscanf 要求这样做。

    尝试以下技巧:

    void print_screen(int i){
    
    char str[256];  /* plenty large enough for this example */
    

    【讨论】:

      猜你喜欢
      • 2011-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-15
      • 1970-01-01
      • 2020-09-11
      相关资源
      最近更新 更多