I know this same question has been asked a hundred times before, but they either don't help me or they aren't answered.
我知道同样的问题之前已被问过一百次,但他们要么不帮助我,要么他们没有回答。
I want to read a text file which has some integers in a format like this:
我想读取一个文本文件,其中包含一些整数,格式如下:
1;50
2;40
3;180
this file can go forever so I can't create an array with a fixed size. So far the summarized part of what I have done (full code isn't like this, I have checked if files aren't null, made file pointers, put them in different functions etc.) :
这个文件可以永远存在,所以我不能创建一个固定大小的数组。到目前为止,我所做的总结部分(完整代码不是这样的,我检查过文件是否为空,制作文件指针,将它们放在不同的函数中等):
int **mymatrix;
mymatrix =(int **) malloc(sizeof(int*)*1);
fscanf(file, "%d", &mymatrix[0]);
fscanf(file, ";%d", &mymatrix[1]);
and to print that:
并打印:
printf("%d", *mymatrix[0]);
printf(" %d", *mymatrix[0]);
I have looked some similar questions and learned the malloc line from them. I have tried doing fscanf(file, "%d;%d", something)
and replaced something with every possible combination of *, **, &, && and also tried [0], [1] but still can't read anything.
我看了一些类似的问题,并从中学到了malloc系列。我已经尝试过fscanf(文件,“%d;%d”,某些东西)并用*,**,&,&&的每种可能组合替换了一些东西,并尝试了[0],[1]但仍然无法读取任何东西。
I don't need that print part on my code (also tried every possible combinations but no luck). I had placed breakpoints after scanf's but Visual Studio shows mymatrix as < unable to read memory >.
我不需要在我的代码上打印部分(也尝试了所有可能的组合,但没有运气)。我在scanf之后放置了断点,但Visual Studio将mymatrix显示为 <无法读取内存> 。
So, there should be a combination of scanf that I haven't tried. If anyone can help me on that part, I greatly appreciate it.
所以,应该有一个我没试过的scanf的组合。如果有人可以帮助我,我非常感激。
6 个解决方案
#1
1
Like this:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *fp = fopen("matrix.txt", "r");
if(!fp){
perror("fopen");
return 1;
}
int d1, d2, rows = 0;
while(2 == fscanf(fp, "%d;%d", &d1, &d2))
++rows;
int **matrix = malloc(rows * sizeof(*matrix));
rewind(fp);
rows = 0;
while(2 == fscanf(fp, "%d;%d", &d1, &d2)){
matrix[rows] = malloc(2 * sizeof(**matrix));
matrix[rows][0] = d1;
matrix[rows++][1] = d2;
}
fclose(fp);
//print and free'd
for(int r = 0; r < rows; ++r){
printf("%d %d\n", matrix[r][0], matrix[r][1]);
free(matrix[r]);
}
free(matrix);
return 0;
}
realloc version.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *fp;
int **matrix = NULL;
int d1, d2, r, rows = 0;
fp = fopen("data.txt", "r");
if(!fp){
perror("fopen");
return 1;
}
while(2 == fscanf(fp, "%d;%d", &d1, &d2)){
matrix = realloc(matrix, (rows+1)*sizeof(*matrix));//In the case of large files increase the size that you want to extend. It must have control of the timing.
matrix[rows] = malloc(2 * sizeof(**matrix));
matrix[rows][0] = d1;
matrix[rows][1] = d2;
++rows;
}
fclose(fp);
//print and free'd
for(r = 0; r < rows; ++r){
printf("%d %d\n", matrix[r][0], matrix[r][1]);
free(matrix[r]);
}
free(matrix);
return 0;
}
#2
2
First, int **mymatrix;
is not a matrix/2D array and cannot represent one.
首先,int ** mymatrix;不是矩阵/ 2D数组,不能代表一个。
Said that, you should use a pointer to a 1D array/matrix:
说,你应该使用指向1D数组/矩阵的指针:
// avoid magic numbers!
#define COLS 2
// Points to the matrix. Starts without matrix
int (*mymatrix)[COLS] = NULL;
Despite its type, it can point to a 2D array. As a general rule, a "pointer to an array of N
dimensions" can be used to address an "array of N+1
dimensions.
尽管它的类型,它可以指向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
Don't forget to release the array when done:
完成后不要忘记释放数组:
free(mymatrix);
The code above is a fragment. It requires some standard headers and a function, of course. Best is to wrap the reading part into its own function with a clean interface to the caller. It also reads from stdin; change to fscanf
is simple.
上面的代码是一个片段。当然,它需要一些标准的标题和功能。最好的方法是将读取部分包装到自己的函数中,并为调用者提供一个干净的接口。它也从stdin读取;改为fscanf很简单。
Also the printing part is straight-forward, just loop over all rows. and print each column.
打印部件也是直接的,只是在所有行上循环。并打印每列。
Note that this code will allocate at most GROW_LENGTH - 1
unused rows. Set to 1 to have no overhead at all, but that is less efficient, as realloc
is called fore every row. The best balance depends on the application, OS, etc.
请注意,此代码最多将分配GROW_LENGTH - 1个未使用的行。设置为1以完全没有开销,但效率较低,因为每行调用realloc。最佳平衡取决于应用程序,操作系统等。
#3
1
First, your arguments to fscanf
don't match the format string. mymatrix[0]
is an int *
, so &mymatrix[0]
is an int **
. Compiling with -Wall -Wextra
will warn you of this.
首先,您对fscanf的参数与格式字符串不匹配。 mymatrix [0]是一个int *,所以&mymatrix [0]是一个int **。使用-Wall -Wextra进行编译将警告您这一点。
Also, you allocate space for a 1 element array of int *
, but then you don't populate that pointer.
此外,您为int *的1个元素数组分配空间,但之后您不会填充该指针。
You need to allocate an array of 2 int
to assign to the first element of mymatrix
, then pass the address of each of those to fscanf
:
你需要分配一个2 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]);
Then you print them like this:
然后你打印出来像这样:
printf("%d", mymatrix[0][0]);
printf(" %d", mymatrix[0][1]);
When reading each subsequent line, you'll need to realloc
instead of malloc
and keep track of how many lines you have and which line you're on.
在阅读每个后续行时,您需要重新分配而不是malloc并跟踪您拥有的行数以及您所在的行。
#4
0
If mymatrix
were defined as int mymatrix[3][2]
, you could read the first line doing:
如果mymatrix被定义为int mymatrix [3] [2],你可以阅读第一行:
fscanf(file, "%d;%d", &mymatrix[0][0], &mymatrix[0][1]);
The same code would work with mymatrix
defined as int **mymatrix
, if it would point to a dynamically initialized array of pointers to arrays of int
as follows:
相同的代码可以使用定义为int ** mymatrix的mymatrix,如果它指向一个动态初始化的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
The number of lines
and cols
of the matrix could then be defined at runtinme.
然后可以在runtinme中定义矩阵的行数和列数。
#5
0
In addition to all of the other fine answers, why not use a pointer to array of int 2 (or whatever the size of your elements are)? In your circumstance, this is an optimal approach. There is no need to use a pointer to pointer to int. That complicates allocation and freeing of the memory. A pointer to array gives you single allocation of blocks, single freeing of all allocated memory and the 2D indexing you desire.
除了所有其他精细答案之外,为什么不使用指向int 2数组的指针(或者你的元素的大小是什么)?在您的情况下,这是一种最佳方法。没有必要使用指向int的指针。这使得分配和释放内存变得复杂。指向数组的指针为您提供单个块分配,单个释放所有已分配的内存以及所需的2D索引。
If you are reading from your file and storing a collection of integer pairs, you need only use a pointer to array, e.g.
如果您正在从文件中读取并存储整数对的集合,则只需使用指向数组的指针,例如
int (*arr)[2] = NULL;
That makes allocation with either malloc
or calloc
a single call to allocate storage an initial number of pairs, and makes freeing the memory a single call. For example, if you have a variable maxn
of 64
, then to allocate a block of memory to hold the first 64
pairs of integers read from the file, you need only:
这使得使用malloc或calloc进行单次调用分配存储初始数量的对,并使内存释放一次。例如,如果您的变量maxn为64,那么要分配一块内存来保存从文件中读取的前64对整数,您只需要:
arr = calloc (maxn, sizeof *arr);
There is no need for a separate call to allocate storage for every 2-integers, when your reach your initial limit of 64
, you simply realloc
your array and keep going. The following uses a constant MAXN
to realloc
for an additional 64
pairs each time the current index idx
reaches the limit maxn
(the new block of memory is also zeroed):
没有必要单独调用为每个2整数分配存储,当你达到初始限制64时,你只需重新分配你的数组并继续。每次当前索引idx达到极限maxn时,以下使用常量MAXN重新分配另外64对(新的内存块也归零):
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;
}
Putting all the pieces together and using a few simply error checking functions for convenience, you could do something similar to the following:
为了方便起见,将所有部分放在一起并使用一些简单的错误检查功能,您可以执行类似于以下操作:
#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;
}
Example Input
With an initial allocation for 64
pairs, reallocation is forces in order to read the entire file. (you can set the initial size at 1 and realloc
on every iteration, but that is highly inefficient -- the initial size for MAXN
must be at least 1, and should be set to some reasonably anticipated number of elements given your data)
对于64对的初始分配,重新分配是强制读取整个文件。 (您可以将初始大小设置为1并在每次迭代时重新分配,但效率非常低 - MAXN的初始大小必须至少为1,并且应该设置为给定数据的某些合理预期的元素数)
$ cat dat/2d_data.txt
1;354
2;160
3;205
4;342
...
98;464
99;130
100;424
Example Use/Output
$ ./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
Memory Use/Error Check
内存使用/错误检查
In any code your write that dynamically allocates memory, you have 2 responsibilites regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
在你的动态分配内存的任何代码中,你有2个责任关于任何分配的内存块:(1)总是保留一个指向内存块起始地址的指针,所以,(2)它可以在没有时被释放需要更久。
It is imperative that you use a memory error checking program to insure you haven't written beyond/outside your allocated block of memory, attempted to read or base a jump on an unintitialized value and finally to confirm that you have freed all the memory you have allocated. For Linux valgrind
is the normal choice.
您必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,尝试读取或基于未初始化的值跳转,并最终确认您已释放所有内存分配了。对于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)
Always confirm All heap blocks were freed -- no leaks are possible and equally important ERROR SUMMARY: 0 errors from 0 contexts.
始终确认释放所有堆块 - 不可能发生泄漏,同样重要的错误摘要:0个上下文中的0个错误。
Look over all the answers and let me know if you have any further questions. Using a pointer to array makes a whole lot of sense in a number of situations such as this. It simplifies allocation and freeing of memory and preserves your 2D indexing as well.
查看所有答案,如果您有任何其他问题,请告诉我。在许多情况下使用指向数组的指针非常有意义。它简化了内存的分配和释放,并保留了您的2D索引。
#6
-1
You will have to malloc
the memory to mymatrix[0]
.
你必须将内存malloc到mymatrix [0]。
mymatrix[0]= (int *) malloc ( sizeof (int) *2);
Also, in mymatrix malloc
, 1 actually means the maximum number of rows you will have. So you can at max have 1 row as per that.
此外,在mymatrix malloc中,1实际上表示您将拥有的最大行数。所以你最多可以有1行。
#1
1
Like this:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *fp = fopen("matrix.txt", "r");
if(!fp){
perror("fopen");
return 1;
}
int d1, d2, rows = 0;
while(2 == fscanf(fp, "%d;%d", &d1, &d2))
++rows;
int **matrix = malloc(rows * sizeof(*matrix));
rewind(fp);
rows = 0;
while(2 == fscanf(fp, "%d;%d", &d1, &d2)){
matrix[rows] = malloc(2 * sizeof(**matrix));
matrix[rows][0] = d1;
matrix[rows++][1] = d2;
}
fclose(fp);
//print and free'd
for(int r = 0; r < rows; ++r){
printf("%d %d\n", matrix[r][0], matrix[r][1]);
free(matrix[r]);
}
free(matrix);
return 0;
}
realloc version.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *fp;
int **matrix = NULL;
int d1, d2, r, rows = 0;
fp = fopen("data.txt", "r");
if(!fp){
perror("fopen");
return 1;
}
while(2 == fscanf(fp, "%d;%d", &d1, &d2)){
matrix = realloc(matrix, (rows+1)*sizeof(*matrix));//In the case of large files increase the size that you want to extend. It must have control of the timing.
matrix[rows] = malloc(2 * sizeof(**matrix));
matrix[rows][0] = d1;
matrix[rows][1] = d2;
++rows;
}
fclose(fp);
//print and free'd
for(r = 0; r < rows; ++r){
printf("%d %d\n", matrix[r][0], matrix[r][1]);
free(matrix[r]);
}
free(matrix);
return 0;
}
#2
2
First, int **mymatrix;
is not a matrix/2D array and cannot represent one.
首先,int ** mymatrix;不是矩阵/ 2D数组,不能代表一个。
Said that, you should use a pointer to a 1D array/matrix:
说,你应该使用指向1D数组/矩阵的指针:
// avoid magic numbers!
#define COLS 2
// Points to the matrix. Starts without matrix
int (*mymatrix)[COLS] = NULL;
Despite its type, it can point to a 2D array. As a general rule, a "pointer to an array of N
dimensions" can be used to address an "array of N+1
dimensions.
尽管它的类型,它可以指向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
Don't forget to release the array when done:
完成后不要忘记释放数组:
free(mymatrix);
The code above is a fragment. It requires some standard headers and a function, of course. Best is to wrap the reading part into its own function with a clean interface to the caller. It also reads from stdin; change to fscanf
is simple.
上面的代码是一个片段。当然,它需要一些标准的标题和功能。最好的方法是将读取部分包装到自己的函数中,并为调用者提供一个干净的接口。它也从stdin读取;改为fscanf很简单。
Also the printing part is straight-forward, just loop over all rows. and print each column.
打印部件也是直接的,只是在所有行上循环。并打印每列。
Note that this code will allocate at most GROW_LENGTH - 1
unused rows. Set to 1 to have no overhead at all, but that is less efficient, as realloc
is called fore every row. The best balance depends on the application, OS, etc.
请注意,此代码最多将分配GROW_LENGTH - 1个未使用的行。设置为1以完全没有开销,但效率较低,因为每行调用realloc。最佳平衡取决于应用程序,操作系统等。
#3
1
First, your arguments to fscanf
don't match the format string. mymatrix[0]
is an int *
, so &mymatrix[0]
is an int **
. Compiling with -Wall -Wextra
will warn you of this.
首先,您对fscanf的参数与格式字符串不匹配。 mymatrix [0]是一个int *,所以&mymatrix [0]是一个int **。使用-Wall -Wextra进行编译将警告您这一点。
Also, you allocate space for a 1 element array of int *
, but then you don't populate that pointer.
此外,您为int *的1个元素数组分配空间,但之后您不会填充该指针。
You need to allocate an array of 2 int
to assign to the first element of mymatrix
, then pass the address of each of those to fscanf
:
你需要分配一个2 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]);
Then you print them like this:
然后你打印出来像这样:
printf("%d", mymatrix[0][0]);
printf(" %d", mymatrix[0][1]);
When reading each subsequent line, you'll need to realloc
instead of malloc
and keep track of how many lines you have and which line you're on.
在阅读每个后续行时,您需要重新分配而不是malloc并跟踪您拥有的行数以及您所在的行。
#4
0
If mymatrix
were defined as int mymatrix[3][2]
, you could read the first line doing:
如果mymatrix被定义为int mymatrix [3] [2],你可以阅读第一行:
fscanf(file, "%d;%d", &mymatrix[0][0], &mymatrix[0][1]);
The same code would work with mymatrix
defined as int **mymatrix
, if it would point to a dynamically initialized array of pointers to arrays of int
as follows:
相同的代码可以使用定义为int ** mymatrix的mymatrix,如果它指向一个动态初始化的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
The number of lines
and cols
of the matrix could then be defined at runtinme.
然后可以在runtinme中定义矩阵的行数和列数。
#5
0
In addition to all of the other fine answers, why not use a pointer to array of int 2 (or whatever the size of your elements are)? In your circumstance, this is an optimal approach. There is no need to use a pointer to pointer to int. That complicates allocation and freeing of the memory. A pointer to array gives you single allocation of blocks, single freeing of all allocated memory and the 2D indexing you desire.
除了所有其他精细答案之外,为什么不使用指向int 2数组的指针(或者你的元素的大小是什么)?在您的情况下,这是一种最佳方法。没有必要使用指向int的指针。这使得分配和释放内存变得复杂。指向数组的指针为您提供单个块分配,单个释放所有已分配的内存以及所需的2D索引。
If you are reading from your file and storing a collection of integer pairs, you need only use a pointer to array, e.g.
如果您正在从文件中读取并存储整数对的集合,则只需使用指向数组的指针,例如
int (*arr)[2] = NULL;
That makes allocation with either malloc
or calloc
a single call to allocate storage an initial number of pairs, and makes freeing the memory a single call. For example, if you have a variable maxn
of 64
, then to allocate a block of memory to hold the first 64
pairs of integers read from the file, you need only:
这使得使用malloc或calloc进行单次调用分配存储初始数量的对,并使内存释放一次。例如,如果您的变量maxn为64,那么要分配一块内存来保存从文件中读取的前64对整数,您只需要:
arr = calloc (maxn, sizeof *arr);
There is no need for a separate call to allocate storage for every 2-integers, when your reach your initial limit of 64
, you simply realloc
your array and keep going. The following uses a constant MAXN
to realloc
for an additional 64
pairs each time the current index idx
reaches the limit maxn
(the new block of memory is also zeroed):
没有必要单独调用为每个2整数分配存储,当你达到初始限制64时,你只需重新分配你的数组并继续。每次当前索引idx达到极限maxn时,以下使用常量MAXN重新分配另外64对(新的内存块也归零):
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;
}
Putting all the pieces together and using a few simply error checking functions for convenience, you could do something similar to the following:
为了方便起见,将所有部分放在一起并使用一些简单的错误检查功能,您可以执行类似于以下操作:
#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;
}
Example Input
With an initial allocation for 64
pairs, reallocation is forces in order to read the entire file. (you can set the initial size at 1 and realloc
on every iteration, but that is highly inefficient -- the initial size for MAXN
must be at least 1, and should be set to some reasonably anticipated number of elements given your data)
对于64对的初始分配,重新分配是强制读取整个文件。 (您可以将初始大小设置为1并在每次迭代时重新分配,但效率非常低 - MAXN的初始大小必须至少为1,并且应该设置为给定数据的某些合理预期的元素数)
$ cat dat/2d_data.txt
1;354
2;160
3;205
4;342
...
98;464
99;130
100;424
Example Use/Output
$ ./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
Memory Use/Error Check
内存使用/错误检查
In any code your write that dynamically allocates memory, you have 2 responsibilites regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
在你的动态分配内存的任何代码中,你有2个责任关于任何分配的内存块:(1)总是保留一个指向内存块起始地址的指针,所以,(2)它可以在没有时被释放需要更久。
It is imperative that you use a memory error checking program to insure you haven't written beyond/outside your allocated block of memory, attempted to read or base a jump on an unintitialized value and finally to confirm that you have freed all the memory you have allocated. For Linux valgrind
is the normal choice.
您必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,尝试读取或基于未初始化的值跳转,并最终确认您已释放所有内存分配了。对于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)
Always confirm All heap blocks were freed -- no leaks are possible and equally important ERROR SUMMARY: 0 errors from 0 contexts.
始终确认释放所有堆块 - 不可能发生泄漏,同样重要的错误摘要:0个上下文中的0个错误。
Look over all the answers and let me know if you have any further questions. Using a pointer to array makes a whole lot of sense in a number of situations such as this. It simplifies allocation and freeing of memory and preserves your 2D indexing as well.
查看所有答案,如果您有任何其他问题,请告诉我。在许多情况下使用指向数组的指针非常有意义。它简化了内存的分配和释放,并保留了您的2D索引。
#6
-1
You will have to malloc
the memory to mymatrix[0]
.
你必须将内存malloc到mymatrix [0]。
mymatrix[0]= (int *) malloc ( sizeof (int) *2);
Also, in mymatrix malloc
, 1 actually means the maximum number of rows you will have. So you can at max have 1 row as per that.
此外,在mymatrix malloc中,1实际上表示您将拥有的最大行数。所以你最多可以有1行。