我怎样从C语言开始读取文件?

问题描述 投票:-1回答:1

我需要读取一个包含2个线程的文件,其中一个将从头到尾读取文件,另一个将从头到中读取文件。我的文件中有10个浮点数。前5个浮点数将由一个线程求和,最后5个浮点数将由另一个线程求和。 func1没问题,但我无法处理func2部分。

float sum=0,sum1=0,sum2=0,flo;  
int i=0;
FILE *fp;

 void *func1(void *param) {
      for(i=1;i<=5;i++) {
      fscanf(fp,"%f",&flo);
      sum1=flo+sum1;
}
      pthread_exit(0);
}
int main() {

   pthread_t tid;   
   pthread_attr_t attr;   
   pthread_attr_init(&attr);

   fp = fopen("input.txt","r");
   pthread_create(&tid, &attr, func1,fp);
   pthread_create(&tid, &attr, func2,fp);
   pthread_join(tid, NULL);
}
c multithreading pthreads
1个回答
0
投票

到目前为止,最简单的技术是使用单个线程来进行读取。但是,鉴于这是使用POSIX线程的练习,那么:

  • 你应该总是检查fscanf()的返回值 - 线程或没有线程。
  • 即使在无线程序中也应该避开全局变量。
  • 线程和isum1flo都是全球性的,你正在为可怕的竞争条件做好准备。您应该使用互斥锁来防止对这些变量的并发访问。或者,更好的是,使它们都是线程函数的本地。
  • 您还需要使函数返回适当的值。
  • 您应该使用传递给线程函数的参数。
  • 您应该将线程ID值保存在单独的变量中,以便您可以等待两个线程完成;你的代码只等待一个线程完成(第二个)。
  • 你应该打印结果。
  • 您不必担心文件流上的同步 - POSIX要求无论如何都要发生(请参阅同一页上记录的flockfile()及其近亲)。
  • 您应该提供func1()func2()来创建MCVE(Minimal, Complete, Verifiable Example。我假设相同的函数将对两个线程都做,这在上下文中不是一个冒险的假设。

将它们放在一起会导致:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

struct tcb
{
    FILE *fp;
    double sum;
    int thread_num;
};

static void *func1(void *param)
{
    struct tcb *tcb = param;
    double sum1 = 0.0, flo;
    for (int i = 1; i <= 5; i++)
    {
        if (fscanf(tcb->fp, "%lf", &flo) != 1)
        {
            fprintf(stderr, "Thread %d failed to read value %d\n", tcb->thread_num, i);
            pthread_exit(0);
        }
        sum1 += flo;
    }
    tcb->sum = sum1;
    pthread_exit(0);
}

int main(void)
{
    FILE *fp;
    pthread_t tid1;
    pthread_t tid2;
    struct tcb tcb[2];
    pthread_attr_t attr;

    pthread_attr_init(&attr);
    const char *filename = "input.txt";

    if ((fp = fopen(filename, "r")) == NULL)
    {
        fprintf(stderr, "Failed to open file %s for reading\n", filename);
        exit(1);
    }
    tcb[0].fp = fp;
    tcb[0].thread_num = 0;
    tcb[0].sum = 0.0;
    tcb[1].fp = fp;
    tcb[1].thread_num = 1;
    tcb[1].sum = 0.0;
    pthread_create(&tid1, &attr, func1, &tcb[0]);
    pthread_create(&tid2, &attr, func1, &tcb[1]);
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    printf("Total from thread 0 = %f\n", tcb[0].sum);
    printf("Total from thread 1 = %f\n", tcb[1].sum);
    printf("Grand total         = %f\n", tcb[0].sum + tcb[1].sum);
    return 0;
}

还有其他方法可以处理线程函数的输入和输出,但创建一个简单的结构似乎非常简单和适当。

给定数据文件(input.txt):

 23.192048
  4.128715
  3.465737
 74.307105
  4.329846
  6.098813
  9.497566
  6.988740
 11.530497
 53.262049
  9.469198
 41.305744

一次运行的输出是:

Total from thread 0 = 87.377665
Total from thread 1 = 109.423451
Grand total         = 196.801116

其他运行给出了不同的值(另一个运行颠倒了两个结果)。这两个总和对应于数据文件的行6-10和1-5(其具有12行)。这表明一个线程设法调度并读取其数据配额,然后让另一个线程读取下一个数据配额。添加更多线程(使用循环和线程ID值数组)和更多数据可能会显示I / O操作的不同交错排序。

© www.soinside.com 2019 - 2024. All rights reserved.