我知道同样的问题之前已被问过一百次,但是他们要么没有帮助我,要么没有回答。
我想读取一个文本文件,其中包含一些整数,格式如下:
1;50
2;40
3;180
这个文件可以永远存在,所以我无法创建一个固定大小的数组。到目前为止,我所做的总结部分(完整代码不是这样的,我检查过文件是否为空,制作文件指针,将它们放在不同的函数中等):
int **mymatrix;
mymatrix =(int **) malloc(sizeof(int*)*1);
fscanf(file, "%d", &mymatrix[0]);
fscanf(file, ";%d", &mymatrix[1]);
并打印出来:
printf("%d", *mymatrix[0]);
printf(" %d", *mymatrix[0]);
我看了一些类似的问题并从中学到了malloc系列。
我尝试过做fscanf(file, "%d;%d", something)
并用*,**,&,&&并尝试[0],[1]但仍然无法读取任何内容。
我的代码上不需要打印部分(也尝试了所有可能的组合,但没有运气)。我在scanf之后放置了断点,但Visual Studio将mymatrix显示为<无法读取内存>。
所以,应该有一个我没试过的scanf的组合。如果有人可以帮助我,我非常感激。
答案 0 :(得分:2)
首先,int **mymatrix;
不是矩阵/ 2D数组,不能代表一个。
说,你应该使用指向1D数组/矩阵的指针:
// avoid magic numbers!
#define COLS 2
// Points to the matrix. Starts without matrix
int (*mymatrix)[COLS] = NULL;
尽管它的类型,但它可以指向2D数组。作为一般规则,指向N
维度数组的"指针"可用于处理N+1
维度的"数组。
// the amount to grow the array (min. 1, but that is inefficient)
#define GROW_LENGTH 10
// this holds the total number of rows in the array
size_t length = 0;
// row to store next entry
size_t row = 0;
// buffer for input data
int buffer[COLS];
// read data until failure
while ( scanf("%d;%d", &buffer[0], &buffer[1]) == 2 ) {
if ( row >= length ) {
// enlarge the array for another block
int (*p)[COLS] = realloc(mymatrix,
sizeof(*mymatrix) * (length + GROW_LENGTH));
if ( p == NULL ) {
// realloc failed
// release the matrix and terminate (can be changed to more inteligent behaviour)
free(mymatrix);
exit(1);
}
// update variables
mymatrix = p;
length += GROW_LENGTH;
}
// store the data into the matrix
mymatrix[row][0] = buffer[0];
mymatrix[row][1] = buffer[1];
// next position in buffer
row++;
}
if ( mymatrix == NULL ) {
// nothing has been read
}
// process the data.
// `row` contains the number of rows with data
完成后不要忘记释放阵列:
free(mymatrix);
上面的代码是一个片段。当然,它需要一些标准的标题和功能。最好的方法是将读取部分包装到自己的函数中,并为调用者提供一个干净的接口。它也从stdin读取;更改为fscanf
很简单。
此外,打印部件是直接的,只是在所有行上循环。并打印每一列。
请注意,此代码最多会分配GROW_LENGTH - 1
个未使用的行。设置为1以完全没有开销,但效率较低,因为每行都会调用realloc
。最佳平衡取决于应用程序,操作系统等。
答案 1 :(得分:1)
首先,您对git config diff.dummy "dummy line"
的参数与格式字符串不匹配。 fscanf
是mymatrix[0]
,因此int *
是&mymatrix[0]
。使用int **
进行编译会警告您。
此外,您为{1}}的1个元素数组分配空间,但是您不会填充该指针。
您需要分配一个2 -Wall -Wextra
的数组来分配给int *
的第一个元素,然后将每个元素的地址传递给int
:
mymatrix
然后你打印它们:
fscanf
在阅读每个后续行时,您需要int **mymatrix;
mymatrix = malloc(sizeof(int*)*1); // don't cast the return value of malloc
mymatrix[0] = malloc(sizeof(int)*2); // same here
fscanf(file, "%d", &mymatrix[0][0]);
fscanf(file, ";%d", &mymatrix[0][1]);
代替printf("%d", mymatrix[0][0]);
printf(" %d", mymatrix[0][1]);
并跟踪您拥有的行数以及您所在的行。
答案 2 :(得分:1)
像这样:
print data[data.artist.isnull()]
artist
0 NaN
realloc版本。
svnadmin dump
答案 3 :(得分:1)
除了所有其他精细答案之外,为什么不使用指向int 2 数组的指针(或者你的元素的大小是什么)?在您的情况下,这是一种最佳方法。不需要使用指向int 的指针的指针。这使得分配和释放内存变得复杂。 指向数组的指针可以为您提供单个块分配,单个释放所有已分配的内存以及所需的2D索引。
如果您正在从文件中读取并存储整数对的集合,则只需使用指向数组的指针,例如
int (*arr)[2] = NULL;
这使得用malloc
或calloc
分配一次调用来分配存储的初始对数,并使内存释放一次。例如,如果变量maxn
为64
,那么要分配一块内存来保存从文件中读取的第一对64
整数,只需:
arr = calloc (maxn, sizeof *arr);
无需单独调用为每个2位整数分配存储空间,当您达到64
的初始限制时,只需realloc
数组并继续运行即可。每当当前索引MAXN
达到限制realloc
时,以下使用常量64
到idx
对另外的maxn
对(新的内存块是也归零):
if (++idx == maxn) {
printf ("\n reallocating %zu to %zu\n", maxn, maxn + MAXN);
size_t szelem = sizeof *arr;
void *tmp = realloc (arr, (maxn + MAXN) * szelem);
if (!tmp) {
fprintf (stderr, "realloc() error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
arr = tmp;
memset (arr + maxn * szelem, 0, MAXN * szelem);
maxn += MAXN;
}
为方便起见,将所有部分放在一起并使用一些简单的错误检查功能,您可以执行类似以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* constants for number of columns, buffer chars, and initial allocation */
enum { NCOL = 2, MAXC = 32, MAXN = 64 };
void *xcalloc (size_t nmemb, size_t sz);
void *xrealloc (void *ptr, size_t psz, size_t *nelem);
FILE *xfopen (const char *fn, const char *mode);
int main (int argc, char **argv) {
char buf[MAXC] = {0};
char *fmt = "%d;%d";
int (*arr)[NCOL] = NULL;
size_t i, idx = 0, maxn = MAXN;
FILE *fp = argc > 1 ? xfopen (argv[1], "r") : stdin;
/* alloc mem for array of MAXN elements */
arr = xcalloc (maxn, sizeof *arr);
while (fgets (buf, MAXC, fp)) { /* read each line of input */
int a, b; /* parse line for values */
if (sscanf (buf, fmt, &a, &b) != NCOL) continue;
arr[idx][0] = a, arr[idx][1] = b;
if (++idx == maxn) /* realloc as needed */
arr = xrealloc (arr, sizeof *arr, &maxn);
}
if (fp != stdin) fclose (fp); /* close if not stdin */
for (i = 0; i < idx; i++)
printf (" array[%3zu][0] : %4d [1] : %d\n",
i, arr[i][0], arr[i][1]);
free (arr); /* free allocated memory */
return 0;
}
/** xcalloc allocates memory using calloc and validates the return. */
void *xcalloc (size_t nmemb, size_t sz)
{ register void *memptr = calloc (nmemb, sz);
if (!memptr) {
fprintf (stderr, "xcalloc() error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
return memptr;
}
/** realloc 'ptr' to array of elements of 'psz' to 'nelem + MAXN' elements */
void *xrealloc (void *ptr, size_t psz, size_t *nelem)
{ void *tmp = realloc ((char *)ptr, (*nelem + MAXN) * psz);
if (!tmp) {
fprintf (stderr, "realloc() error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
memset (tmp + *nelem * psz, 0, MAXN * psz); /* zero new memory */
*nelem += MAXN;
return tmp;
}
/** fopen with error checking - short version */
FILE *xfopen (const char *fn, const char *mode)
{ FILE *fp = fopen (fn, mode);
if (!fp) {
fprintf (stderr, "xfopen() error: file open failed '%s'.\n", fn);
// return NULL; /* choose appropriate action */
exit (EXIT_FAILURE);
}
return fp;
}
示例输入
对64
对进行初始分配,重新分配是强制读取整个文件。 (您可以在每次迭代时将初始大小设置为1和realloc
,但效率非常低 - MAXN
的初始大小必须至少为1,并且应设置为某个合理预期的数字给出您的数据的元素)
$ cat dat/2d_data.txt
1;354
2;160
3;205
4;342
...
98;464
99;130
100;424
示例使用/输出
$ ./bin/array_ptr2array_realloc <dat/2d_data.txt
array[ 0][0] : 1 [1] : 354
array[ 1][0] : 2 [1] : 160
array[ 2][0] : 3 [1] : 205
array[ 3][0] : 4 [1] : 342
...
array[ 97][0] : 98 [1] : 464
array[ 98][0] : 99 [1] : 130
array[ 99][0] : 100 [1] : 424
内存使用/错误检查
在你动态分配内存的任何代码中,你有2 responsibilites 关于分配的任何内存块:(1)总是保留一个指向起始地址的指针内存块,(2)当不再需要时,它可以释放。
必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,尝试读取或基于未初始化的值跳转,最后确认您已释放所有内存你分配的记忆。对于Linux valgrind
是正常的选择。
$ valgrind ./bin/array_ptr2array_realloc <dat/2d_data.txt
==2796== Memcheck, a memory error detector
==2796== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==2796== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==2796== Command: ./bin/array_ptr2array_realloc
==2796==
array[ 0][0] : 1 [1] : 354
array[ 1][0] : 2 [1] : 160
array[ 2][0] : 3 [1] : 205
array[ 3][0] : 4 [1] : 342
...
array[ 97][0] : 98 [1] : 464
array[ 98][0] : 99 [1] : 130
array[ 99][0] : 100 [1] : 424
==2796==
==2796== HEAP SUMMARY:
==2796== in use at exit: 0 bytes in 0 blocks
==2796== total heap usage: 2 allocs, 2 frees, 1,536 bytes allocated
==2796==
==2796== All heap blocks were freed -- no leaks are possible
==2796==
==2796== For counts of detected and suppressed errors, rerun with: -v
==2796== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
始终确认释放所有堆块 - 不可能泄漏并且同样重要错误摘要:0个上下文中的0个错误。
查看所有答案,如果您有任何其他问题,请与我们联系。在诸如此类的许多情况下,使用指向数组的指针非常有意义。它简化了内存的分配和释放,并保留了您的2D索引。
答案 4 :(得分:0)
如果将 float x, y, r, g, b, radius;
void setup()
{
size(800, 700);
smooth();
frameRate(15);
}
void draw()
{
handleRedBox();
}
void handleRedBox() {
background(255);
stroke(255, 0, 0);
color from = color(100, random(255), 2);
color to = color(0, 200, 0);
color interA = lerpColor (to, from, .44);
int x = 100;
while (x < width/2 || x> width/2 ) {
int y = 100;
while (y <height/2 || y > height/2) {
blendMode(DIFFERENCE);
noStroke();
fill(interA);
quadstuff();
strokeWeight(5);
stroke(0, random(255), 0);
line(width/2, height/2, mouseY, mouseX);
translate(width, height);
rotate(radians(frameCount));
y = y + 50;
}
x = x + 50;
}
ghostcirc();
ghostcirc2();
}
void ghostcirc() {
int w = 0;
while (w < width) {
int q = 0;
while (q <height) {
blendMode(ADD);
fill(random(61), random(90), random(250));
ellipse(255, 255, 100, 100);
;
noStroke();
translate(width, height);
rotate(radians(frameCount));
q = q + 100;
}
w = w + 50;
}
}
void ghostcirc2() {
for (int w= 0; w < width; w+=10) {
blendMode(ADD);
fill(random(61), random(90), random(250));
ellipse(50, 50, 75, 75);
;
noStroke();
translate(width, height);
rotate(radians(frameCount));
//if (keyPressed == true){
// fill(random(100), random(90), random(250));
}
}
void quadstuff() {
int rad = 60; // Width of the shape
float xpos, ypos; // Starting position of shape
float xspeed = 2.8; // Speed of the shape
float yspeed = 2.2; // Speed of the shape
xpos = width/2;
ypos = height/2;
//ellipse(mouseX+x, mouseY+y, 100,100);
quad(xpos, ypos, rad, rad, mouseX+rad, mouseY+rad, xspeed, yspeed);
stroke(0);
strokeWeight(5);
}
定义为mymatrix
,您可以阅读第一行:
int mymatrix[3][2]
相同的代码适用于定义为fscanf(file, "%d;%d", &mymatrix[0][0], &mymatrix[0][1]);
的{{1}},如果它指向动态初始化的mymatrix
数组指针数组,如下所示:
int **mymatrix
然后可以在runtinme中定义矩阵的int
和mymatrix=(int**)calloc(lines, sizeof(int*)); // intialize the array of array
for (inti=0; i<lines; i++)
mymatrix[i]=(int*)calloc(cols, sizeof(int)); //intialise each array
的数量。
答案 5 :(得分:-1)
您必须malloc
将记忆转移到mymatrix[0]
。
mymatrix[0]= (int *) malloc ( sizeof (int) *2);
此外,在mymatrix malloc
中,1实际上表示您将拥有的最大行数。所以你最多可以有1行。