You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言多线程解析文本文件单词无法读取内容问题求助

问题原因及修复方案
  • 核心问题1:文件路径错误

你调用opendir(argv[1])打开的是指定目录,但readdir返回的d_name仅为文件名本身,不包含目录前缀。你直接把文件名传给fopen时,程序只会在当前运行的工作目录下查找文件,不会去你指定的目标目录查找。
你输出中能打开文件,说明当前工作目录刚好存在同名的空文件,因此fgets读不到任何内容,单词打印逻辑自然不会执行。

  • 核心问题2:线程逻辑存在未定义行为

你定义的线程数组pthread_t threads[threadCount]长度为你输入的线程数,但后续pthread_join时循环次数是目录内总文件数i:

  1. 如果目录内文件数大于线程数,会发生数组越界访问,且后续文件没有创建线程却执行join操作,触发未定义行为
  2. 超出线程数的文件不会被处理,直接遗漏
  • 核心问题3:错误处理不完整

fopen打开文件失败后仅打印错误,没有终止线程逻辑,后续会传入空指针调用fgets引发段错误。


修复代码示例

首先修改路径拼接逻辑,其次修复线程生命周期管理逻辑,最后补全错误处理:

#include <stdlib.h>
#include <dirent.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include "queue.h"

void* splitInput(void *arg) {
  char* filename = (char*)arg;
  printf("Thread %s Created\n", filename);

  FILE *file = fopen(filename, "r");
  if(file == NULL) {
    perror("Error opening file");
    free(filename); // 释放传入的路径内存
    pthread_exit(NULL);
  }

  printf("Opened File %s\n", filename);

  int i = 0;
  char *cp;
  char *bp;
  char line[255];
  char *array[5000];

  while(fgets(line, sizeof(line), file) != NULL) {
    bp = line;
    while(1) {
      cp = strtok(bp, ",.!? \n");
      bp = NULL;
      if(cp == NULL) {
        break;
      }
      array[i++] = cp;
      printf("Check print - word %i:%s:\n", i-1, cp);
    }
  }

  fclose(file);
  free(filename); // 释放传入的路径内存
  return 0;
}

int main(int argc, char *argv[]) {
  if(argc < 4) { // 新增参数合法性判断
    printf("Usage: %s <dir_path> <queue_size> <thread_count>\n", argv[0]);
    return 1;
  }

  DIR* d = opendir(argv[1]);
  if(d == NULL) {
    perror("Error opening directory");
    return 1;
  }

  int queueSize = atoi(argv[2]);
  int threadCount = atoi(argv[3]);
  printf("Queue Size: %d\n", queueSize);
  printf("Thread Count: %d\n", threadCount);

  pthread_t threads[threadCount];
  int i = 0;
  struct dirent* e;

  while((e = readdir(d)) != NULL) {
    if(strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0) {
      continue;
    }
    if(i >= threadCount) { // 超过线程数的文件先跳过,可根据需求调整为线程池逻辑处理全部文件
      printf("Skip file %s, exceed thread count\n", e->d_name);
      continue;
    }
    printf("entered file %s\n", e->d_name);
    // 拼接完整路径
    int path_len = strlen(argv[1]) + strlen(e->d_name) + 2;
    char *full_path = malloc(path_len);
    snprintf(full_path, path_len, "%s/%s", argv[1], e->d_name);
    
    pthread_create(&threads[i], NULL, splitInput, full_path);
    i++;
  }
  closedir(d);

  // 仅join实际创建的线程
  for(int j = 0; j < i; j++) {
    pthread_join(threads[j], NULL);
  }

  return 0;
}

内容的提问来源于stack exchange,提问作者Shiloh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 19:15:03