【问题标题】:Iterate on files of a folder, with specific condition在特定条件下迭代文件夹的文件
【发布时间】:2015-03-01 00:24:40
【问题描述】:

this solutiondirent.h 一起使用,我正在尝试迭代当前文件夹的特定文件(那些具有.wav 扩展名开头的文件3 位数字),代码如下:

(重要提示:由于我使用的是 MSVC++ 2010,我似乎无法使用 #include <regex>,而且我也无法使用 this,因为不支持 C++11) p>

DIR *dir;
struct dirent *ent;
if ((dir = opendir (".")) != NULL) {
  while ((ent = readdir (dir)) != NULL) {
    printf ("%s\n", ent->d_name);
    //if substr(ent->d_name, 0, 3) ... // what to do here to 
                                      //  check if those 3 first char are digits?
    // int i = susbtr(ent->d_name, 0, 3).strtoi();        //  error here! how to parse 
                                                         // the 3 first char (digits) as int? 

    // if susbtr(ent->d_name, strlen(ent->d_name)-3) != "wav" // ...

  }
  closedir (dir);
} else {
  perror ("");
  return EXIT_FAILURE;
}

如何使用未完全支持 C+11 的 MSVC++2010 执行这些测试?

【问题讨论】:

  • 什么是import <regex>?这是 c++,因为它在我看来像 c。
  • 对不起@iharob,我更正了,我的意思是:#include <regex>(我写 import 可能是因为 python...)
  • 如果你擅长python,那为什么不用python呢?而且,c 解决方案与 c++ 解决方案有很大不同,您不需要正则表达式,这就像用火箭筒杀死苍蝇一样。
  • @iharob 我必须在 c/c++ 而不是 python 上这样做,因为我使用的 SDK 仅在 c/c++ 中可用,而且我想要一个非常小的输出可执行文件...... C 或 C++ 解决方案会对我来说没问题,只要它适用于“旧”MSVC++2010
  • @iharob,如果您无法帮助使用 c++,为什么您认为这不像 c++。 C++ 被设计为兼容并允许将 C 代码编译为 c++ 代码。您的 cmets 在这里显然是题外话。

标签: c++ c string visual-studio-2010 visual-c++


【解决方案1】:

您实际上不会检查 wav 扩展名,只是文件名将以这 3 个字母结尾...

C 库中没有 substr 这样的函数来从字符串中提取切片。

您应该检查文件名长度是否至少为 7:strlen(ent->d_name) >= 7,然后使用 <ctype.h> 中的 isdigit 函数检查前 3 个字符是数字而不是第四个字符,最后比较最后 4 个字符使用strcmp 或更好的strcasecmp 将文件名改为".wav"。后者在微软世界中可能被称为_stricmp。如果这些都不可用,请使用tolower 将最后三个字符与'w''a''v' 进行比较。

这里是放宽要求(任意位数)的实现:

#include <ctype.h>
#include <stdlib.h>

...

DIR *dir;
struct dirent *ent;
if ((dir = opendir(".")) != NULL) {
    while ((ent = readdir(dir)) != NULL) {
        char *name = ent->d_name;
        size_t length = strlen(name);
        if (length >= 5 &&
            isdigit(name[0]) &&
            name[length-4] == '.' &&
            tolower(name[length-3]) == 'w' &&
            tolower(name[length-2]) == 'a' &&
            tolower(name[length-1]) == 'v') {
               int num = atoi(name);
               printf("%s -> %d\n", name, num);
               /* do your thing */
        }
    }
    closedir(dir);
} else {
    perror ("");
    return EXIT_FAILURE;
}

【讨论】:

  • 不错的解决方案!需要的最后一件事:如何将数字(3 位数字)提取为 int
  • strtol(name, NULL, 10) 或简单的atoi(name) 就可以了。我会编辑答案。
  • 只是为了完全了解它是如何工作的:如何使用您的方法@chqrlie 进行测试:1) any number (1 digit or 2 digits or 3 or 4 or ...) + 2) anystring empty or not 3) .wav.... [示例:现在应该接受123blah.wav123235762blah.wav1blah.wav。这只是为了了解它如何与您的方法一起使用。]
  • 你修改上面的代码来检查5的最小长度并且只用isdigit测试第一个字符。回复已编辑。
  • 如果您不关心大小写,您可以使用memcmp(name + length - 4, ".wav", 4) 进一步简化,但请注意文件系统在 Windows 中通常不区分大小写。
【解决方案2】:

好的,这是一个解决方案

#include <stdio.h>
#include <string.h>

int
main(void)
{
    const char *strings[] = {"123.wav", "1234 not-good.wav", "456.wav", "789.wav", "12 fail.wav"};
    int         i;
    int         number;

    for (i = 0 ; i < sizeof(strings) / sizeof(*strings) ; ++i)
    {
        size_t      length;
        int         count;
        const char *pointer;

        if ((sscanf(strings[i], "%d%n", &number, &count) != 1) || (count != 3))
            continue;
        length = strlen(strings[i]);
        if (length < 4)
            continue;
        pointer = strings[i] + length - 4;
        if (strncasecmp(pointer, ".wav", 4) != 0)
            continue;
        printf("%s matches and number is %d\n", strings[i], number);
    }
    return 0;
}

如您所见,scanf() 检查字符串开头是否有整数,也跳过任何可能的空白字符,然后捕获扫描的字符数,如果等于3,则继续检查扩展。

如果您使用的是 Windows,请将 strncasecmp() 替换为 _strnicmp()

【讨论】:

  • 哇,太棒了!最后一件事:我愿意接受 123 bonjour.wav(因为 .wav 以 3 位数字开头)但不接受 12blah.wav(仅限 2 位数字)或 1234hey.wav(4 位数字)......你知道怎么做吗?
  • sscanf 不适合这个。我在冒险一个猜想:哪里有scanf,哪里就有bug
  • @chqrlie 你肯定会滥用它。
  • @chqrlie 看得出来你对sscanf()有一些特殊的感觉。我觉得对这种事情不理智是不好的,就像那些认为永远不应该使用goto的人一样。您的代码显然是正确的,但这并不意味着您不能使用 sscanf() 编写正确的代码,我看到人们抱怨很多标准函数,但从来没有 scanf(),如果使用正确,它确实有效,使用正确地看起来很难,但并非不可能。
  • @iharob:结束这场辩论,我非常同意你的观点,除了 c++ 部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-28
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-19
相关资源
最近更新 更多