您的位置:首页 > 其它

一种开辟多维数组的方法

2015-04-27 21:24 232 查看
#include <iostream>
#include <stdio.h>
using namespace std;
int get_mem2D_double(double ***array2D, int dim0, int dim1);
void free_2D_double(double **array2D);
void main()
{
double **array2D;
get_mem2D_double(&array2D, 5, 2);
free_2D_double(array2D);
}

void error(char* text, int code)
{
fprintf(stderr, "%s\n", text);
exit(code);
}

#define  snprintf _snprintf_s
#define ET_SIZE 300
char errortext[ET_SIZE];
void no_mem_exit(char* messageError)
{
snprintf(errortext, ET_SIZE, "Could not allocate memory: %s", messageError);
error(errortext, 100);
}
int get_mem2D_double(double ***array2D, int dim0, int dim1)
{
int i;
if ((*array2D = (double**)malloc(dim0 * sizeof(double*))) == NULL)
no_mem_exit("get_mem2Ddouble: array2D");
if ((*(*array2D) = (double*)calloc(dim0 * dim1, sizeof(double))) == NULL)
no_mem_exit("get_mem2Ddouble: array2D");
for (i = 1; i < dim0; i++)
(*array2D)[i] = (*array2D)[i - 1] + dim1;

return dim0*(sizeof(double*) + dim1*sizeof(double));
}

void free_2D_double(double **array2D)
{
if (array2D)
{
if (*array2D)
free(*array2D);
else
error("Free_2D_double:trying to free unused memory", 100);
free(array2D);
}
else
{
error("Free_2D_double:trying to free unused memory", 100);
}
}
函数原型:void *calloc(size_t n, size_t size);功 能: 在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。

与malloc的区别:

calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据。int fprintf( FILE *stream, const char *format, ... );fprintf()函数根据指定的format(格式)发送信息(参数)到由stream(流)指定的文件. fprintf()只能和printf()一样工作. fprintf()的返回值是输出的字符数,发生错误时返回一个负值.fprintf是C/C++中的一个格式化写—库函数;其作用是格式化输出到一个流/文件中;原型是intfprintf( FILE *stream, const char *format, [ argument ]...),fprintf()函数根据指定的format(格式)发送信息(参数)到由stream(流)指定的文件。
template <size_t size>int sprintf_s(char (&buffer)[size],const char *format [,argument] ...
); // C++ only
int _snprintf(char *buffer,size_t count,const char *format [,argument] ...
);
int _snprintf(char (&buffer)[size],size_t count,const char *format [,argument] ...
); // C++ only
int _snprintf_s(char *buffer,size_t sizeOfBuffer,size_t count,const char *format [,argument] ...
);
int _snprintf_s(char (&buffer)[size],size_t count,const char *format [,argument] ...
); // C++ only呼呼。。内容还挺多。
这里比较引人注目的是,_snprintf_s为什么在sizeOfBuffer的基础上,还要多加一个count?count似乎是用来控制理想的宽度的。如果得到的字符串超过了count,于是会被截断到count的长度后面再加一个null-teminate当然,更高优先级的应该是sizeOfBuffer,必须不超过这个大小。这个就说到点子上了。如果应该输出的字符串的大小已经达到了sizeOfBuffer,那么就溢出了。溢出的情况下,sprintf_s函数把这当做一个错误,会把buffer缓冲区置为一个空字符串""。而_snprintf_s的好处就是,有了count参数,输出的字符串就算超过缓冲区长度,仍然会有输出,输出字符串被截断到count大小,在这个大小的字符串后面加null-teminate。
当然,如果count被设置成和sizeOfBuffer同样大,或者不合理的更大,那么这个count参数就失去了意义。这时候,如果输出字符串将要达到或者超过sizeOfBuffer,一样导致一个错误,输出缓冲区被置为空字符串。因此,如果希望缓冲区被尽量利用,可以把count参数置为_TRUNCATE,这样的情况下,实际上效果相当于是将count设置为sizeOfBuffer - 1。至于C语言环境下,sprintf_s与_snprintf的对比:注意到,_snprintf的参数用的是count,而sprintf_s的参数用的是sizeOfBuffer。这很能说明问题。看下对_snprintf的说明:Let len be the length of the formatted data string (not including the terminating null).len and count are in bytes for _snprintf, wide characters for _snwprintf.If len < count, then len characters are stored in buffer, a null-terminator is appended, and len is returned.If len = count, then len characters are stored in buffer, no null-terminator is appended, and len is returned.If len > count, then count characters are stored in buffer, no null-terminator is appended, and a negative value is returned.也就是说,_snprintf的count参数明明白白的就是一个count。如果输出字符串刚好达到count,由于期待的最大长度就是count,那么输出字符串肯定要完整,不能截断。但是假如字符串缓冲区的大小其实就是count,这怎么办?MS VCRT的设计者认为,在这种情况下应该把输出字符串的长度告知调用者,让调用者来决定是否自己添加null-teminate。换句话说,调用_snprintf时要注意了,必须检查_snprintf的返回值,如果返回值不是正数,那么还得注意你的字符串缓冲区并不是null-teminate结尾的。总结来说,sprintf_s在缓冲区不够大时会失败,失败时缓冲区中是一个空字符串。_snprintf不会失败,但是必须注意如果缓冲区不够大,缓冲区的内容将不是null-teminate的,必须自己注意字符串的结束。_snprintf_s结合了2者的优点,只要count参数设置合理,函数就不会因缓冲区不够而失败。但是观察_snprintf_s的说明,有一个很有趣的内容。这3族函数中,有失败情况的2个函数sprintf_s和_snprintf_s中,(再次强调,我这里的失败的意思是,调用后缓冲区里是一个空字符串),_set_invalid_parameter_handler设置的错误处理器,在失败的情况下会被调用。而截断的情况下,错误处理器并不会被调用。VC的库开发者总是提供一些怪怪的东西。无论如何,让代码更加安全总是符合大家的总体期望的。另外补充一下,查阅这些字符串安全函数的资料的时候要注意,对微软来说,凡是限制字符串复制长度的函数,这些设计者仍然认为是不安全的,因为逻辑上来说,这些长度参数只是限制了源字符串被复制的长度,而不是目标缓冲区的长度。也就是说,微软的这些设计者认为,安全的方式其实是依赖C++的机制,辨认出目标缓冲区的真正大小,以此实现安全的复制。
</pre><pre>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: