矩阵转置从 Java 移植到 C,类型不兼容问题

2024-02-11

我必须在 C 中移植一些 Java 方法,有 Java 背景,但我在 C 编程方面完全是菜鸟

In java

float[][] traspose(float Xy[][]) {
    float result[][]=new float[5000][3000];
    for(int i = 0; i < m; i++) {
        for(int j = 0; j < n; j++) {
            result[i][j] = Xy[j][i];
        }
    }
    return result;
}

我的 C 移植尝试

float traspose(int m, int n, float Xy[m][n]) {
    int i,j;
    float result[5000][3000];
    for(i = 0; i < m; i++) {
        for(j = 0; j < n; j++) {
            result[i][j] = Xy[j][i];
        }
    }
    return result;
}

这不起作用并会出现不兼容类型错误。

我的 2 个问题

1)我应该如何修复我的代码? 谷歌搜索我看到了一些关于在 C 中返回矩阵的问题,但不是很清楚,在大多数情况下,建议使用一种不暗示使用 return 的方法。

2)我发现通常这种用 C 语言编写的操作没有返回类型方法,例如对常量进行操作的 void 方法或直接在 main 中编写代码。 为什么?

EDIT

按照建议,我尝试对此进行编码

float **transpose(int m, int n, float Xy[]) {
    int i,j;
    float **result = allocate_mem_m(m,n);
    for(i = 0; i < m; i++) {
        for(j = 0; j < n; j++) {
            result[i][j] = Xy[j*n+i];
        }
    }
    return result;
}


int main(int argc, char **argv) {
    printf("Hello World!");
    float matrix[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
    printf("Matrix created\n");
    int size=3;
    print(size, size, matrix);
    float **transposedmat = transpose(size, size, &matrix[0][0]);
    printMat(size, size, transposedmat);
    return 0;
}

但不幸的是,当我调用换位方法时,程序崩溃了。

聚苯乙烯 我想用标准 C 编译代码(不是 C99)


严格来说,关于使用指向浮点数的指针的答案在技术上是不正确的,因为浮点数的二维数组与指向浮点数的指针的指针不同。

这将是等效的 C 代码:

#include <stdlib.h>

float (*transpose(int m, int n, float Xy[m][n]))[5000][3000] {
    float (*result)[5000][3000] = malloc(sizeof(*result));
    for(int i = 0; i < m; i++) {
        for(int j = 0; j < n; j++) {
            (*result)[i][j] = Xy[j][i];
        }
    }
    return result;
}

这适用于指针:函数内的第一行为 5000 x 3000 的二维数组分配空间,按照 Java 代码中的方式进行复制,然后返回指向新数组的指针。请注意,一旦使用完内存,您就必须释放它(通过调用free()).

该函数返回一个指向数组的指针,这意味着您必须像这样使用它:

float (*array)[5000][3000] = transpose(m, n, Xy);

然后就可以访问元素了i,j从新数组中使用(*array)[i][j].

要释放,你可以这样做:

free(array);

最后,记住在 C99 支持下编译它 - 你需要它是因为可变长度数组Xy在参数列表中。如果您使用 gcc,可以通过以下方式实现-std=c99

其他答案中提出的解决方案可能足以满足您的目的,但请记住,使用float **因为二维数组有一些警告和“陷阱”。例如,与float **解决方案,您必须手动释放中的每个位置array[i]释放之前array本身;sizeof不会告诉您“模拟”二维数组的真实大小,并且浮点数不会连续存储在内存中。

2)我见过通常用C编写这种操作 没有返回类型方法,例如void 操作的方法 常量或者代码直接写在main中。为什么?

直接编写代码的部分main()并不是很常见。也许您刚刚看到了一些教程示例。在更大的程序中,一般来说,这当然不在内部main().

如果您不想分配内存,那么在不带返回类型的情况下编写它可能会很有用:您可以将其留给调用者。这很重要,因为您不会将释放分配的内存的负担交给调用者。相反,您会收到一个由调用者提供给您的指向已分配内存缓冲区的指针,并将结果写入其中。在内存管理方面,这通常是一种优越的方法,但当然,大量的设计选择和小细节可以很快改变这一点。

UPDATE(如何在没有C99支持的情况下编译它):

嗯,这里的问题是Xy可能是任意长度的二维数组,即你想调用transpose() with any二维数组(这就是为什么你要给它m and n对于尺寸)。

C 没有直接方法将任意大小的二维数组传递给函数。 C99 中添加了此类支持。如果您想在 C89 中执行此操作,一个已知的解决方法是利用数组在连续内存位置中线性布局的事实,从而将其视为一维数组m*n漂浮。换句话说,您可以滚动自己的索引。由于 C 数组按行优先顺序存储,Xy[i][j]是相同的Xy_flat[i*n+j]。所以,实际上,transpose()接收指向第一个元素的指针Xy,并对待Xy作为一维数组。我们只需更换Xy[i][j] with Xy[i*n+j]:

/* C89 version */
#include <stdlib.h>

float (*transpose2(int m, int n, float Xy[]))[5000][3000] {
    float (*result)[5000][3000] = malloc(sizeof(*result));
    int i, j;
    for(i = 0; i < m; i++) {
        for(j = 0; j < n; j++) {
            (*result)[i][j] = Xy[j*n+i];
        }
    }
    return result;
}

对于来自 Java 的人来说,这可能看起来很奇怪且不平凡,但 C 通常在较低级别上工作。

要使用这个函数,你必须给它一个指向第一个元素的指针Xy。这是一个例子:

float matrix[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
float (*transposed)[5000][3000] = transpose(3, 3, &matrix[0][0]);
/* Use (*transposed)[i][j]... */
free(transposed);

如果你不想和(*array)[5000][3000]由于固定的硬编码维度,您当然可以使用其他答案中的解决方案,但始终牢记指针与指针之间的差异float和一个二维浮点数组。由于您似乎更喜欢这种方法,因此代码如下所示:

float **allocate_mem_m(int m, int n)
{
 int i;
 float **arr = malloc(n*sizeof(*arr));
 for(i=0;i<n;i++)
   {
     arr[i]=malloc(m*sizeof(**arr));
   }
 return arr;
} 


float **transpose(int m, int n, float Xy[]) {
  int i,j;
  float **result = allocate_mem_m(m,n);
  for(i = 0; i < m; i++) {
    for(j = 0; j < n; j++) {
      result[i][j] = Xy[j*n+i];
    }
  }
  return result;
}

我冒昧地改变了你的allocate_mem_m()仅接收维度,并返回带有分配内存的指针。我认为当你使用时它开始变得有点过于复杂float ***。那没有必要。

作为建议,我同样会添加一个free_mem_m()简化释放分配内存的过程:

void free_mem_m(int m, float **array) {
  int i;
  for (i = 0; i < m; i++) {
    free(array[i]);
  }
  free(array);
}

这是完整的代码清单:

#include <stdlib.h>

float **allocate_mem_m(int m, int n)
{
 int i;
 float **arr = malloc(n*sizeof(*arr));
 for(i=0;i<n;i++)
   {
     arr[i]=malloc(m*sizeof(**arr));
   }
 return arr;
} 

void free_mem_m(int m, float **array) {
  int i;
  for (i = 0; i < m; i++) {
    free(array[i]);
  }
  free(array);
}

float **transpose(int m, int n, float Xy[]) {
  int i,j;
  float **result = allocate_mem_m(m,n);
  for(i = 0; i < m; i++) {
    for(j = 0; j < n; j++) {
      result[i][j] = Xy[j*n+i];
    }
  }
  return result;
}

以及一个示例用法:

int main(void) {
  float Xy[3][3] = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 } };
  float **transposed = transpose(3, 3, &Xy[0][0]);
  int i, j;
  for (i = 0; i < 3; i++)
    for (j = 0; j < 3; j++)
      printf("%f ", transposed[i][j]);
  printf("\n");
  free_mem_m(3, transposed);
  return 0;
}

注意transpose()假设一个方阵(因为你分配了一个块n职位为m漂浮)。如果你想将其与矩形矩阵一起使用,则必须分配m保持块n相反,它会漂浮。

现场演示工作:http://ideone.com/CyNdpn http://ideone.com/CyNdpn

最后说明:将 2D 数组视为 1D 数组的技巧既古老又棘手;它通常被认为是不好的做法(在我看来),你应该避免这种聪明的代码。但如果您不想使用 C99 功能,那么您就只剩下这了。

对于感兴趣的读者,冒着成为垃圾邮件发送者的风险,我在我的博客中写了两篇关于将这个想法推广到具有 N 维的任意数组的文章。它对为什么需要这样做以及如何做进行了更深入的技术解释:http://codinghighway.com/?p=1159 http://codinghighway.com/?p=1159 and http://codinghighway.com/?p=1206 http://codinghighway.com/?p=1206

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

矩阵转置从 Java 移植到 C,类型不兼容问题 的相关文章

随机推荐

  • SqlDependency 与 SqlCacheDependency

    它们之间的主要区别是什么以及何时应该使用它们 我最初的理解是 SqlCacheDependency 使用轮询 但我读到它对于 ASP NET 2 0 也没有 我想知道哪个最适合在 ASP NET Web 服务器下缓存 linq 查询 这将是
  • 在后台接收推送通知

    我知道很多地方都涉及到这一点 但我无法弄清楚 我使用 Urban Airship 来推送通知 一切似乎都很好 除了当我的应用程序在后台时 didReceiveRemoteNotification没有接到电话 它在前台运行 我能够正确处理消息
  • Echo PHP 变量作为输入字段的值[重复]

    这个问题在这里已经有答案了 我有一个带有多个输入标签的简单 HTML 表单 在页面加载时 我向表单提供数据以回显数据库中字段的当前值 然后用户可以修改这些值并再次提交以执行更新
  • 使用 Lodash 或 Underscore 按多列对对象进行分组

    我有以下对象records notes id 1 description hey userId 2 replyToId null postId 2 parentId null id 5 description hey test userId
  • 线程“main”java.net.ConnectException中出现异常:连接被拒绝:连接[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我正在尝试
  • 如何彻底卸载Visual Studio 2010?

    我一直在寻找一个干净的解决方案来完全并最终从我的计算机中删除 Visual Studio 2010 当您安装 Visual Studio 时 它还会在 添加 删除程序 面板中安装一堆程序 大约 55 个 appwiz cpl 我已经尝试过微
  • ABPeoplePickerNavigationController 随着 iOS8 的变化?

    由于我已将 iPhone 上的 XCode 6 0 6A313 和 iOS 8 0 12A365 更新为 gm 种子 因此 ABPeoplePickerNavigationController 代码无法像以前一样工作 iOS 7 1 2 如
  • AWS Step Functions 与 Luigi 的编排对比

    我的团队有一个针对小型项目的整体服务 但为了重新架构和扩展 我们计划迁移到 Amazon AWS 的云服务 并评估编排是否将 Luigi 作为容器任务运行或使用 AWS Step Functions 我对他们中的任何一个都没有任何经验 尤其
  • Qt 在菜单项单击上显示模式对话框(.ui)

    我想制作一个简单的 关于 模式对话框 从 帮助 gt 关于应用程序 菜单调用 我已经使用 QT Creator ui 文件 创建了一个模式对话框窗口 菜单 关于 槽中应包含什么代码 现在我有了这段代码 但它显示了一个新的模式对话框 不是基于
  • 如何检索 ItemsControl 中项目的 DataTemplate(和特定对象)?

    我已经看到了非常相似问题的解决方案 但它并不适用于我的问题 也就是说 这篇文章 http blogs msdn com wpfsdk archive 2007 04 16 how do i programmatically interact
  • geom_scatterpie 重叠中的饼图

    我想找到一种方法来防止 scatterpie 中的饼图相互重叠 我知道我可以进一步减小半径 但不想让它们比现有的更小 Position jitter 根本不起作用 这是一个可重现的示例 library ggplot2 library ggm
  • Userfrosting 辅助函数的最佳实践

    在使用 userfrosting 的项目中拥有自定义代码 函数库 的最佳实践是什么 到目前为止 我修改了现有的 userfrosting 控制器 这使得简洁的代码变得臃肿 我想有一个很好的方法可以将自定义函数保留在一个地方 它不会干扰 Us
  • Spyder IDE 自动缩进

    是否有任何快捷方式可以在编辑器中自动缩进标记行 例如 在 MATLAB 中存在 CTRL I 快捷键 Matlab语法可以匹配开始结束语句if while for等通过寻找end声明 在 Python 中 这些缩进是不明确的 被定义为嵌套缩
  • java正则表达式

    谁能帮我在java正则表达式中做以下事情吗 我需要从给定字符串的第五个位置读取 3 个字符 忽略前后找到的任何内容 例子 testXXXtest 预期结果 XXX 你根本不需要正则表达式 只需使用子字符串 yourString substr
  • 如何使用自定义命名空间创建 SyndicateFeed

    如何生成包含下图中显示的命名空间的 Atom Feed Atom feed 的所有节点都必须以 a 开头 这就是我现在正在做的事情 但它不起作用 SyndicationFeed feed new SyndicationFeed XmlQua
  • 在 Ktor 中发送 application/x-www-form-urlencoded

    我不知道如何发送application x www form urlencoded POST在 Ktor 中请求 我看到一些submitFormKtor 文档中的帮助程序 但他们没有按预期发送请求 我想要的是复制这个卷曲线行为 curl d
  • Scala Play 2.2 Slick 1.0.1 - 未来 { Try {...} } 等待空闲的可用连接超时

    我有一个 scala html 页面 它在 Play 2 2 1 Scala 2 10 2 Slick 1 0 1 Postgres 9 3 应用程序中进行 AJAX 调用 以下同步代码工作正常 它解析请求查询字符串并调用该方法School
  • 如何在 Asp.Net MVC 3 中的所有视图中实现 @using?

    我想做的就是包括这个 using MyProject WebUI Properties 在我的所有视图中 无需在每个视图中键入它 有没有办法在 ViewStart 或 Web Config 中执行此操作 谢谢 将您的命名空间添加到视图 we
  • 将实例变量传递给 js.erb 文件(Rails 3 / jQuery)

    我有一个 index html erb 文件 其中包含以下内容 这将呈现 user html erb 并输出一个用于对每个用户执行特定操作的按钮 user id action remote gt true gt 我已经将我的用户控制器设置为
  • 矩阵转置从 Java 移植到 C,类型不兼容问题

    我必须在 C 中移植一些 Java 方法 有 Java 背景 但我在 C 编程方面完全是菜鸟 In java float traspose float Xy float result new float 5000 3000 for int