【问题标题】:Reading only .txt files from an input directory, then getc all contents into one array in C从输入目录中仅读取 .txt 文件,然后将所有内容获取到 C 中的一个数组中
【发布时间】:2020-10-22 07:51:39
【问题描述】:

所以我试图创建一个接收输入目录的函数,只检查它的“.txt”文件,然后将所有内容存储到一个字符数组中(这里是动态分配的)。当我对每个文件中的每个字符使用 getc() 时,一次一个,我不仅一次存储每个字符,而且我希望它们一次打印一个字符,以查看是否所有文件正在正确读取。请注意,这里 else 循环中的所有内容在我制作的另一个程序中仅读取单个输入文件时 100% 正确工作。

这是alphabetcount.c,就是函数...

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include<unistd.h> 
#include <stdbool.h>
#include <dirent.h>
#include "count.h"

void alphabetlettercount( char *path, char *filetowrite, long alphabetfreq[] )
{
    DIR *dir;
    FILE *entry_file;
    struct dirent *in_file;

    int c, i;
    int filled_elements = 0;

    char *temp_arrayPointer;
    char *perm_arrayPointer;

    perm_arrayPointer = ( char* ) calloc ( 1, sizeof( char ) );

    dir = opendir( path );

    if( dir == NULL )
    {
        printf( "Unable to read directory!" );
        exit( 1 );
    }

    while( ( in_file = readdir( dir ) ) != NULL )
    {

        if ( !strcmp ( in_file->d_name, "." ) || !strcmp ( in_file->d_name, ".." ) || strstr( ( in_file->d_name ), ".txt" ) )
        {

        }


       else
       {

            printf( "%s\n", in_file->d_name );

            entry_file = fopen( in_file->d_name, "r" );

            if ( entry_file != NULL )
            {

                while ( ( c = getc( entry_file ) ) != EOF )
                {
                        *( perm_arrayPointer + filled_elements ) = c;

                        printf( "%c", ( *( perm_arrayPointer + filled_elements ) ) );

                        filled_elements++;        

                        temp_arrayPointer = ( char* ) realloc ( perm_arrayPointer, ( ( filled_elements + 1 ) * sizeof( char ) ) );

                        if ( temp_arrayPointer != NULL )
                        {
                            perm_arrayPointer = temp_arrayPointer;
                        }
            }

        }

        fclose( entry_file );    
    }

    closedir( dir );    
}

这是 testingalphabetcount.c,或者只是 main()...

(注意:alphabetlettercount() 原型存在于两个 .c 文件的 count.h #include 文件中)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include<unistd.h> 
#include <stdbool.h>
#include <dirent.h>
#include "count.h"

int main()
{

      char *path = "../data";           // the data *.txt files are under this folder
      
      alphabetlettercount(path);  // process the data files

}

这个的输出是......

.
.
..
..

...如果“ printf("%s\n", in_file->d_name ); ”被放置在“If”循环内,但如果它被放置在“else”循环内,我的输出是...

test2.txt 
Segmentation Fault

关于我做错了什么有什么建议吗?我认为这与 fopen() 使用不正确有关吗?感谢和抱歉读了这么久!

【问题讨论】:

  • 头文件 unistd.hdirent.h 不是 ISO C 的一部分。这意味着您正在使用特定于平台的扩展。这没有什么问题,但是当你这样做时,还请通过设置适当的标签在你的问题中指定平台。据我所知,在这种情况下,标志“posix”可能是合适的。
  • 您绝对应该 fclose(entry_file) 在打开它的else 子句之外。 (即,将 fclose 移到 else 中)。您可以通过限制变量的范围来捕获此类错误。 (即,将其声明移到使用它的块中)
  • 检查你的代码,fclose( entry_file ); 应该在 if 中
  • 谢谢大家!不幸的是,它仍然无法工作:(程序运行但在将 fclose(entry_file); 放置在 else 循环内部 [并且就在 if (entry_file != NULL ) 之外没有打​​印任何内容
  • printf( "Unable to read directory!" ); 替换为perror(path); 错误消息应该提供信息并写入stderr。

标签: c fopen readdir opendir getc


【解决方案1】:

我已更改您的函数 alphabetlettercount 以匹配提供的 main 函数

我已经通过使用continue 简化了您的else,这样可以避免深度过大并便于阅读。

我已在专用范围内移动变量。 我已尝试保持您的风格,但恕我直言,有些台词很长。

您不应该强制转换 calloc(或 malloc)返回。

您的代码的主要问题是fclose 的位置以及您仅获取.txt 文件的测试(我刚刚添加了缺少的!,请注意将读取foo.txt.bar)

做这么多 realloc 不是一个好习惯,尝试分配一个 1k 的缓冲区,每次需要时加倍这个大小会更好

static void alphabetlettercount(const char *path)
{
    DIR *dir;
    struct dirent *in_file;

    int filled_elements = 0;

    char *perm_arrayPointer;

    perm_arrayPointer = calloc ( 1, sizeof( char ) );

    dir = opendir( path );

    if( dir == NULL )
    {
        printf( "Unable to read directory!" );
        exit( 1 );
    }

    while( ( in_file = readdir( dir ) ) != NULL )
    {
        FILE *entry_file;
        int c;
        char filepath[256];
        if ( !strcmp ( in_file->d_name, "." ) || !strcmp ( in_file->d_name, ".." ) || !strstr( ( in_file->d_name ), ".txt" ) )
        {
            continue;
        }

        printf( "%s\n", in_file->d_name );
        snprintf(filepath, sizeof(filepath), "%s/%s", path, in_file->d_name );
        entry_file = fopen( filepath, "r" );
        if ( entry_file == NULL ) {
            printf ("Error opening file: %s\n",strerror(errno));
            continue;
        }

        while ( ( c = getc( entry_file ) ) != EOF )
        {
            char *temp_arrayPointer;
            *( perm_arrayPointer + filled_elements ) = c;

            printf( "%c", ( *( perm_arrayPointer + filled_elements ) ) );

            filled_elements++;

            temp_arrayPointer = realloc ( perm_arrayPointer, ( ( filled_elements + 1 ) * sizeof( char ) ) );

            if ( temp_arrayPointer != NULL )
            {
                perm_arrayPointer = temp_arrayPointer;
            }
        }
        putchar('\n');
        fclose( entry_file );
    }

    closedir( dir );
    free(perm_arrayPointer);
}

【讨论】:

  • 嗨 Orel 非常感谢您的宝贵时间!所以你的函数在这里打印出我放在输入目录中的 3 个 .txt 文件的名称,但是文件的内容仍然没有打印出来)
  • 是的,它对我有用,标准输出流默认是行缓冲的,添加一个新的行字符来刷新缓冲区可以提供帮助。我已经编辑了代码并添加了putchar
  • 还有一点值得注意的是,当我尝试更改它以在每个文件上使用 fopen() 之后打印出文件名时,文件名甚至根本不打印,所以有些奇怪当我尝试使用 fopen() 时正在发生,似乎
  • 你的平台是什么?尝试使用stderr打印fprintf(stderr, "...
  • 我做了这个修改,但仍然没有打印:(我在虚拟机中使用 ubuntu linux 终端...你认为这些 c 头文件有问题吗?
猜你喜欢
  • 2023-04-07
  • 1970-01-01
  • 2013-11-27
  • 1970-01-01
  • 2015-07-03
  • 1970-01-01
  • 2021-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多