- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试将两个 double 从输入加载到一个二维数组中,该数组由每个用户输入动态重新分配。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int count;
double number1, number2, **numbers;
while (scanf("%lf,%lf", number1, number2) != EOF) {
count++;
numbers = (double**) realloc(numbers, count * 2 * sizeof (double));
if (numbers == NULL) {
exit(1);
}
numbers[count][0] = number1;
numbers[count][1] = number2;
}
return 0;
}
程序编译没有问题,但每次我尝试在数组中存储一个值时都会失败(这可能是内存问题)。
谁能告诉我如何在我的程序中正确地重新分配二维数组?
最佳答案
你有几个问题。
numbers = 0;
或 count = 0
因此在开始第一个 realloc() 之前变量中有一个不确定的值
调用。这是个坏消息。scanf()
调用不正确;你没有传递指向它的指针。ASCII 艺术
+---------+
| numbers |
+---------+
|
v
+------------+ +---------------+---------------+
| numbers[0] |---->| numbers[0][0] | numbers[0][1] |
+------------+ +---------------+---------------+
| numbers[1] |---->| numbers[1][0] | numbers[1][1] |
+------------+ +---------------+---------------+
| numbers[2] |---->| numbers[2][0] | numbers[2][1] |
+------------+ +---------------+---------------+
您实际上需要存储在numbers
中的指针、指针数组、和 double
数组。目前,您没有为指针数组分配空间,这就是您遇到麻烦的原因。 double 组可以是连续的或不连续的(即每一行可以单独分配,但在一行内,当然分配必须是连续的)。
工作代码:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int count = 0;
double number1, number2;
double **numbers = 0;
while (scanf("%lf,%lf", &number1, &number2) != EOF)
{
numbers = (double **) realloc(numbers, (count + 1) * sizeof(*numbers));
if (numbers == NULL)
exit(1);
numbers[count] = (double *)malloc(2 * sizeof(double));
if (numbers[count] == 0)
exit(1);
numbers[count][0] = number1;
numbers[count][1] = number2;
count++;
}
for (int i = 0; i < count; i++)
printf("(%8.2f, %8.2f)\n", numbers[i][0], numbers[i][1]);
for (int i = 0; i < count; i++)
free(numbers[i]);
free(numbers);
return 0;
}
注意:这仍然不是好的代码。特别是,使用中的每次增加一个机制是不好的。模因 pointer = realloc(pointer, newsize);
也很糟糕;如果分配失败,您将无法释放先前分配的内存。您应该使用 newptr = realloc(pointer, newsize);
,然后在 pointer = newptr;
之前进行内存检查。
输入文件:
12.34,23.45
34.56,45.67
56.78,67.89
78.90,89.01
输出数据:
( 12.34, 23.45)
( 34.56, 45.67)
( 56.78, 67.89)
( 78.90, 89.01)
没有在 valgrind
下正式运行,但我相信它会没问题。
What is the best solution for saving inputs into array without knowing how many inputs I have to store ? Or maybe it is just this complicated in C compared to Java or PHP?
除了“增量一”部分,这是关于它在 C 中的工作方式,至少如果你想使用两个索引索引结果:numbers[i][0]
等
另一种方法是像您所做的那样分配空间(除了不是“递增一个”),然后使用表达式来索引数组:double *numbers = ...;
和 numbers[i*2+0]
和 numbers[i*2+1]
在你的情况下,但在更一般的情况下,数组有 ncols
列,使用 numbers[i*ncols + j]
访问行 i
和列 j
。您用 numbers[i][j]
的符号便利性来换取内存分配的增加的复杂性。 (还要注意,对于这种机制,数组的类型是 double *numbers;
而不是 double **numbers;
,就像你的代码中那样。)
避免“增加一个”的替代方案通常在每次分配时使用双倍的空间量。您可以决定使用 malloc()
进行初始分配,然后使用 realloc()
来增加空间,或者您可以只使用 realloc()
知道如果传入的指针为 NULL,那么它将执行与 malloc()
等效的操作。 (实际上,realloc()
是一个完整的内存分配管理封装在一个函数中;如果您以 0 大小调用它,它将free()
内存而不是分配.) 人们争论是否(ab)像那样使用realloc()
是个好主意。由于C89/C90及以后版本的C标准有保障,足够安全,省去了一次函数调用,所以我倾向于直接使用realloc()
:
#include <stdio.h>
#include <stdlib.h>
static void free_numbers(double **array, size_t size)
{
for (size_t i = 0; i < size; i++)
free(array[i]);
free(array);
}
int main(void)
{
int count = 0;
double number1, number2;
double **numbers = 0;
double maxnum = 0;
while (scanf("%lf,%lf", &number1, &number2) != EOF)
{
if (count == maxnum)
{
size_t newnum = (maxnum + 2) * 2; /* 4, 12, 28, 60, ... */
double **newptr = (double **)realloc(numbers, newnum * sizeof(*numbers));
if (newptr == NULL)
{
free_numbers(numbers, count);
exit(1);
}
maxnum = newnum;
numbers = newptr;
}
numbers[count] = (double *)malloc(2 * sizeof(double));
if (numbers[count] == 0)
{
free_numbers(numbers, count);
exit(1);
}
numbers[count][0] = number1;
numbers[count][1] = number2;
count++;
}
for (int i = 0; i < count; i++)
printf("(%8.2f, %8.2f)\n", numbers[i][0], numbers[i][1]);
free_numbers(numbers, count);
return 0;
}
这段代码用valgrind
检查没有问题;所有分配的代码都被释放。请注意使用函数 free_numbers()
来释放错误路径中的内存。当它在像此处这样的 main()
函数中运行时,这并不重要,但当工作在一个可能被许多程序使用的函数中完成时,这绝对是重要的。
关于c - 如何在 C 中正确地重新分配二维数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20036408/
我在 Web 应用程序中尝试了一些字节码操作,到目前为止,效果很好。现在我需要在代码中的某些特定位置注入(inject)一些字节代码。我用 switch 语句和 method.inserAt(); 尝
我正在尝试对数组中的对象值求和,然后计算每个值相对于总数的百分比。 这里是数组: [ { "ratiototale": [ [ { "0":
我在接口(interface)中有以下方法.. Task> SearchAsync(TU searchOptions); 效果很好。 现在我正在尝试进行单元测试以测试何时出现问题 - 代码会抛出异常。
我似乎无法让 reveal 开始工作,我已经严格遵守所有内容,添加 modernizr,添加插件,添加 css(reveal 显然包含在 foundation 中),在开始时初始化 foundatio
我正在尝试移植 raspberrypi's userspace 的位从 C 到 golang 的代码,我遇到了一个涉及 ioctl() 的程序。 我在执行 C 代码时遇到了问题 #define MAJ
我一直在尝试用纯 Java 制作一个简单的游戏,但在绘图时遇到了问题。我正在尝试保持相对较高的帧速率,但是 JFrame.repaint() 不能被“强制”并且只是在下一个可用机会重绘帧的请求这一事实
给定一个字符串 "2*(i+j) = 20 我想返回 ((lambda x: x >= 20), ['i']) 我可以然后直接提供给 constraint。 最佳答案 您正在寻找 eval 的替代方法
我对改进我的 javascript 代码以使其成为正确的 OOP 很感兴趣....目前我倾向于做这样的事情: jQuery(document).ready(function () { Page
我有一个调用两个动画 Action 的事件监听器。不幸的是,它们的开始有少量错开(例如,函数中的第一个首先开始)。 有谁知道正确同步它们的方法吗? 这是我的代码: $("#nav ul li a").
我只需要检查目录是否存在!但是,如果目录是“E:\Test”,其中 E: 是 CD/DVD 驱动器,并且上面没有插入磁盘,我会看到以下 Delphi 和 Windows 问题。 第一种方法: func
同样的问题: https://stackoverflow.com/questions/11294207/exchange-web-services-argumentexception-using-my
如果您跳转到 this question 中的第一个答案你会看到他使用 Employee.prototype = new Person(); 将 Person.prototype 继承到 Employ
我需要知道如何正确地遍历元素的 ArrayList 并计算元素在列表中出现的次数,而无需事先知道该元素。我尝试了几种方法并且有一种目前有效,但我觉得它很丑陋且不合适。 为了更深入地解释,我有一个 ja
我有一个用 Python 编写的(非常基本但工作完美的)AWS lambda 函数,但是它具有嵌入式凭证以连接到:1)外部网络服务2) DynamoDB 表。 该函数的作用相当基本:它针对服务发布登录
我很好奇 Tornado 推荐的查询 Redis(或任何数据库)的方法是什么。 我见过一些像 https://gist.github.com/357306 这样的例子但他们似乎都在使用对 redis
这更像是一个“我做得对吗”的问题。 快速背景故事:我已经构建了一个 gradle 插件(在一个独立的 gradle/groovy 项目中)。我在另一个 java 项目中使用它。客户项目通过以下方式引用
在我的代码中,我有: function handleMessage() { const twilio = require('twilio')(process.env.TWILIO_ACCOUNT_
我正在努力在 Linux 中刷新嵌入式设备的先前 ROM 转储。我以前的转储包含 oob 数据。我是用nandwrite -n -N -o/dev/mtd0 backup.bin写的,然后再做一次RO
我正在尝试使用 go 为 react-router 提供服务,我已经做到了,但我遇到了麻烦,我认为我做的方式不正确,或者不完整。我正在使用 Mux。我遇到的麻烦是当我按下 时在我的应用程序中,它正确
我正在尝试 promise JSON.parse 方法,但不幸的是没有任何运气。这是我的尝试: Promise.promisify(JSON.parse, JSON)(data).then((resu
我是一名优秀的程序员,十分优秀!