C 将 "strings"的 2D 数组收集到数组中,然后将每个 2D 传递到 C98 函数中

标签 c arrays multidimensional-array

我遇到了一些 C 语法问题,我希望有人知道答案,或者知道一篇文章解释了我可以从中学习的接近解决方案。我知道如何用包括多个汇编程序在内的十几种其他语言来执行此操作,但我无法弄清楚 C 语法(不是 C++,或者 C99+ 必须是 C98,因为有 5 个操作系统支持)来执行此操作。

我有一个库 API,它接受“字符串”N x 2(N 行,2 列)的二维数组,其中包含行数的整数。该数组几乎总是在调用应用程序的代码中定义为常量,因为这些信息几乎总是在该应用程序的编译时已知。我的代码可以接受数组并正确处理它,所以 API 实际上工作得很好。目的是避免对在调用应用程序的新版本发布之前永远不会改变的内容进行内存分配/释放(即,我通过允许应用程序开发人员使用编译时间常量来帮助他们使用 API)。

我遇到的问题是创建一个综合测试器,我想通过相同的 API 运行多个场景,但内容略有不同。在 Java、JavaScript、COBOL、Ruby、Python、汇编器等中...它就像数组的数组一样“简单”...在 C 中,则不然。

我定义的工作 API 是:

CTS parse(const char* contents, size_t len, const char* app
            , const char* pVs[][2], const int pvLen);

这是我正在测试的令人讨厌的代码部分;第一部分工作正常并正确测试代码,但如果我想添加更多变体,愚蠢的 case 语句将变得丑陋(呃)和低能(这与我目前的 C 技能相当接近:D):

int i = 0, f = 0, lf = 0, len = 0;
int lengths[] = {1, 3, 1, 1, 1};
char* filt1[][2] = { {"CS","5"},{"AS","5.4"},{"OS","16.*"} };
char* filt2[][2] = { {"CS","6.2"} };
char* filt3[][2] = { {"CS","5.4"} };
char* filt4[][2] = { {"CS","*"} };
char* filt5[][2] = { {"",""} };

for(i = 1; i < 6; i++) {         // Filter cases (filt 1=5)
     lf = lengths[i];
     for(f = 0; f < 6; f++) {   // Input files to be checked
           printf("Test #%i:\n", f);
           file = loadFile(f);
           len = (file == NULL ? 0 : strlen(file));
           switch(i) {                     // WTF Code!! stupid way to do this!
           case 1:
                l = parse(file, len, NULL, filt1, lf);
                break;
           case 2:
                l = parse(file, len, NULL, filt2, lf);
                break;
           case 3:
                l = parse(file, len, NULL, filt3, lf);
                break;
           case 4:
                l = parse(file, len, NULL, filt4, lf);
                break;
           case 5:
                l = parse(file, len, NULL, filt5, lf);
                break;
           }
           // Finish testing "l" result
           ...
     }
}

我很想知道如何将上面的内容重写为这样的内容(我并不真正关心 NULL 选项,我可以将其排除在组测试之外):

?????? filters[6] = {NULL, filt1, filt2, filt3, filt4, filt5};

for(i = 1; i < 6; i++) {
     lf = lengths[i];
     for(f = 0; f < 6; f++) {
           char* filter[][2] = filters[i];       // What goes here?

           printf("Test #%i:\n", f);
           file = loadFile(f);
           len = (file == NULL ? 0 : strlen(file));

           l = parse(file, len, NULL, filter, lf);

           // Finish testing "l" result
     }
}

忽略 NULL 选项,如何构建(技术上)稀疏内容的 3 维数组(即并非所有“深度”行都具有相同的维度)并将其传递到 API 函数?我在 StackOverflow 上进行了近 2 天的研究,没有任何示例适用于 char* 或我想要的接收 API 签名。

我检查过Error passing 2D char* array into a function但它只引用固定的数组大小和二维。

不是 How to pass 2D array (matrix) in a function in C? 的重复项因为这个问题涉及整数而不是“字符串”/char*。使用该问题中的建议会导致代码无法编译,因为无法将“表列表”/3d 数组中的结果转换为可以传递到 API 中的可用类型。

最佳答案

这是一个好问题。我希望有人能给出好的答案。 对我来说,使用结构数组的解决方案似乎更清晰且更简单。 如果

typedef struct sar{
    char* (*f)[2];
}SAR

然后你的循环简化为:

SAR ar[6];     
ar[0].f = NULL;
ar[1].f = filt1;   
ar[2].f = filt2; 
ar[3].f = filt3;  
ar[4].f = filt4; 
ar[5].f = filt5; 

for(i = 1; i < 6; i++) {
    lf = lengths[i];
    for(f = 0; f < 6; f++) {
       printf("Test #%i:\n", f);
       file = loadFile(f);
       len = (file == NULL ? 0 : strlen(file));
      l = parse(file, len, NULL, ar[i].f, lf);
       // Finish testing "l" result
    }
}

我没有您程序的所有数据,但进行了一些简化 我验证了输出。

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

typedef struct sar{
    char* (*f)[2];
}SAR;

int parse(const char* contents, size_t len, const char* app
            ,char* pVs[][2], const int pvLen)
{

    for(int i=0; i < pvLen; i++)
        printf("%s %s   ", pVs[i][0], pVs[i][1]);       
    printf("\n");       
    return 1;                
}

char * loadFile(int f)
{
    return NULL;
}

int main(void) 
{            
    char * file;
    int l;

    int i = 0, f = 0, lf = 0, len = 0;

    int lengths[] = {1, 3, 1, 1, 1};

    char* filt1[][2] = { {"CS","5"},{"AS","5.4"},{"OS","16.*"} };
    char* filt2[][2] = { {"CS","6.2"} };
    char* filt3[][2] = { {"CS","5.4"} };
    char* filt4[][2] = { {"CS","*"} };
    char* filt5[][2] = { {"",""} };

    for(i = 1; i < 6; i++) {         // Filter cases (filt 1=5)
         lf = lengths[i];

        for(f = 0; f < 6; f++) {   // Input files to be checked

           printf("Test #%i:\n", f);
           file = loadFile(f);
           len = (file == NULL ? 0 : strlen(file));
           switch(i) {                     // WTF Code!! stupid way to do this!
           case 1:
                l = parse(file, len, NULL, filt1, lf);
                break;
           case 2:
                l = parse(file, len, NULL, filt2, lf);
                break;
           case 3:
                l = parse(file, len, NULL, filt3, lf);
                break;
           case 4:
                l = parse(file, len, NULL, filt4, lf);
                break;
           case 5:
                l = parse(file, len, NULL, filt5, lf);
                break;
           }
           // Finish testing "l" result
           //...
        }
    }

    printf("............\n");

    SAR ar[6];

    ar[0].f = NULL;
    ar[1].f = filt1;   
    ar[2].f = filt2; 
    ar[3].f = filt3;  
    ar[4].f = filt4; 
    ar[5].f = filt5; 

    for(i = 1; i < 6; i++) {
        lf = lengths[i];
        for(f = 0; f < 6; f++) {
           printf("Test #%i:\n", f);
           file = loadFile(f);
           len = (file == NULL ? 0 : strlen(file));
          l = parse(file, len, NULL, ar[i].f, lf);
           // Finish testing "l" result
        }
    }

    return 0
}

输出:

Test #0:
CS 5   AS 5.4   OS 16.*   
Test #1:
CS 5   AS 5.4   OS 16.*   
Test #2:
CS 5   AS 5.4   OS 16.*   
Test #3:
CS 5   AS 5.4   OS 16.*   
Test #4:
CS 5   AS 5.4   OS 16.*   
Test #5:
CS 5   AS 5.4   OS 16.*   
Test #0:
CS 6.2   
Test #1:
CS 6.2   
Test #2:
CS 6.2   
Test #3:
CS 6.2   
Test #4:
CS 6.2   
Test #5:
CS 6.2   
Test #0:
CS 5.4   
Test #1:
CS 5.4   
Test #2:
CS 5.4   
Test #3:
CS 5.4   
Test #4:
CS 5.4   
Test #5:
CS 5.4   
Test #0:
CS *   
Test #1:
CS *   
Test #2:
CS *   
Test #3:
CS *   
Test #4:
CS *   
Test #5:
CS *   
Test #0:

Test #1:

Test #2:

Test #3:

Test #4:

Test #5:

............
Test #0:
CS 5   AS 5.4   OS 16.*   
Test #1:
CS 5   AS 5.4   OS 16.*   
Test #2:
CS 5   AS 5.4   OS 16.*   
Test #3:
CS 5   AS 5.4   OS 16.*   
Test #4:
CS 5   AS 5.4   OS 16.*   
Test #5:
CS 5   AS 5.4   OS 16.*   
Test #0:
CS 6.2   
Test #1:
CS 6.2   
Test #2:
CS 6.2   
Test #3:
CS 6.2   
Test #4:
CS 6.2   
Test #5:
CS 6.2   
Test #0:
CS 5.4   
Test #1:
CS 5.4   
Test #2:
CS 5.4   
Test #3:
CS 5.4   
Test #4:
CS 5.4   
Test #5:
CS 5.4   
Test #0:
CS *   
Test #1:
CS *   
Test #2:
CS *   
Test #3:
CS *   
Test #4:
CS *   
Test #5:
CS *   
Test #0:

Test #1:

Test #2:

Test #3:

Test #4:

Test #5:

希望对您有所帮助。

关于C 将 "strings"的 2D 数组收集到数组中,然后将每个 2D 传递到 C98 函数中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49057090/

相关文章:

objective-c - 用于密集型科学应用的 NSDecimalNumber?

php - 如何对wp_query的结果进行排序

arrays - 使用带有附加参数的自定义规则验证 Laravel 中的数组

c - 下面的输出如何可能?

c - C 中的二维字符串声明数组

c - 程序不断返回段错误

c - 不按唯一键搜索哈希表

c++ - 摆脱丑陋的 C 结构

php - 根据 PHP 中的匹配列值合并数组

c++ - 为什么第一行出现了除零以外的其他值?