C语言 分割错误:11,而试图打印数组与50k项



我正在尝试将具有50k项的数组打印到文件中,但只有当我设置少量项(例如5k)时才能完成。

void fputsArray(int *arr, int size, char *filename)
{
char *string = (char*)calloc( (8*size+1), sizeof(char) );
for(int i = 0; i < size; i++)
sprintf( &string[ strlen(string) ], "%dn", arr[i] );
FILE *output;
char fullFilename[50] = "./";
output = fopen(strcat(fullFilename, filename), "w");
fputs(string, output);
fclose(output);
free(string);
}

size为50000,在#DEFINE中定义。这是工作代码。但是如果我删除8乘以的大小,我应该是工作的,不工作。我得到了在这种情况下分割错误:11为什么我应该分配8倍以上的内存比我需要?

假设输入到你的函数是正确的:

void fputsArray(int *arr, int size, char *filename)

尺寸应按size_t给出。

{
char *string = (char*)calloc( (8*size+1), sizeof(char) );

不需要清除内存(calloc),malloc和设置string[0] = ''就足够了。根据定义,sizeof( char )总是1。并且不应该强制转换分配的结果。

实际上,整个结构是不必要的,但那是后面的事。

for(int i = 0; i < size; i++)
sprintf( &string[ strlen(string) ], "%dn", arr[i] );
除了string + strlen( string )更简单,并且应该总是有{ }

围绕语句之外,实际上并没有那么糟糕。还是没必要那么复杂。

FILE *output;
char fullFilename[50] = "./";
output = fopen(strcat(fullFilename, filename), "w");

文件名总是相对于当前工作目录的,所以"./"是不必要的。您应该strcat将其放入静态缓冲区之前检查文件名长度。

fputs(string, output);

啊,但是你还没有检查fopen是否真的成功了!

fclose(output);
free(string);
}

总而言之,我见过更糟的。然而,你的数字是否真的适合你的缓冲区是一种猜测,最重要的是,整个内存的诡计是不必要的。考虑:

void printArray( int const * arr, size_t size, char const * filename )
{
FILE * output = fopen( filename, "w" );
if ( output != NULL )
{
for ( size_t i = 0; i < size; ++i )
{
fprintf( output, "%dn", arr[i] );
}
fclose( output );
}
else
{
perror( "File open failed" );
}
}

我认为这比试图找出你的记忆猜测哪里出错要好得多。


编辑:再考虑一下,我想让这个函数接受FILE *参数而不是文件名,这将使您能够灵活地打印到已经打开的流(如stdout),并且还允许您在更高的地方对fopen进行错误处理,这可能具有提供有用信息的额外功能。

size为50000,在#DEFINE中定义。这是工作代码。但是如果我删除8乘以大小,我应该是工作的,不工作。我得到在这种情况下分割错误:11为什么我应该分配8倍以上的内存比我需要?

你写的是这个大小估计:

char *string = (char*)calloc( (8*size+1), sizeof(char) );

但是使用的数组是int[],您将在磁盘中每行写入一个值,如

sprintf( &string[ strlen(string) ], "%dn", arr[i] );

这似乎没有必要复杂。至于大小,假设所有值都为INT_MIN,即(在limits.h中)

#define INT_MIN     (-2147483647 - 1)

表示4字节整数。所以有11个碳。只是这一点。10位数字加上一个符号表示信号。这将为您提供任何int值。为'n'

添加1但是…

  • 为什么要使用calloc() ?

  • 为什么不使用适合所有可能值的size * 12-byte数组?

  • 为什么要声明一个新的char*来保存char格式的值,而不是立即使用fprintf()?

  • 为什么void而不是返回像-1这样的错误或在成功的情况下写入磁盘的项目的数量?

返回程序

如果你真的想在一次对fputs()的调用中将数组写入磁盘,在内存中保存整个大字符串,考虑sprintf()返回写入的字节数,所以这是你需要用作指向输出字符串的指针的值…

如果你想使用内存分配,你可以用块来分配。考虑一下,如果所有值都低于999,那么50,000行每行的字节将不超过4个字节。但是如果所有的值都是等于INT_MIN的常量,那么每行最多12个字节。

因此,您可以使用sprintf()的返回值来更新指向字符串的指针,并在需要时使用realloc(),例如,在几个k字节的块中分配。(如果你真的想这么做,请回信,我可以贴一个例子)

C Example

下面的代码按照您尝试的方式写入文件,并返回写入的总字节数。它取决于数组的值。最大就是我说的,每行12字节…

int fputsArray( unsigned size, int*  array , const char* filename)
{
static char string[12 * MY_SIZE_ ] = {0};
unsigned ix = 0; // pointer to the next char to use in string
FILE*    output = fopen( filename, "w");
if ( output == NULL ) return -1;
// file is open
for(int i = 0; i < size; i+= 1)
{
unsigned used = sprintf( (string + ix), "%dn", array[i] );
ix += used;
} 
fputs(string, output);
fclose(output);
return ix;
}

使用fprintf()

这段代码使用fprintf()写相同的文件,而且更简单…

int fputsArray_b( unsigned size, int*  array , const char* filename)
{
unsigned ix = 0; // bytes written
FILE*    output = fopen( filename, "w");
if ( output == NULL ) return -1;
// file is open
for(int i = 0; i < size; i+= 1)
ix += fprintf( output, "%dn", array[i]);
fclose(output);
return ix;
}

使用2个函数的完整测试

#define     MY_SIZE_ 50000
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int fputsArray(const unsigned,int*,const char*);
int fputsArray_b(const unsigned,int*,const char*);
int main(void)
{
int value[MY_SIZE_];
srand(210726); // seed for today :)
value[0] = INT_MIN; // just to test: this is the longest value
for ( int  i=1; i<MY_SIZE_; i+=1 ) value[i] = rand();
int used = fputsArray( MY_SIZE_, value, "test.txt");
printf("%d bytes written to diskn", used );
used = fputsArray_b( MY_SIZE_, value, "test_b.txt");
printf("%d bytes written to disk using the alternate functionn", used );
return 0;
}

int fputsArray( unsigned size, int*  array , const char* filename)
{
static char string[12 * MY_SIZE_ ] = {0};
unsigned ix = 0; // pointer to the next char to use in string
FILE*    output = fopen( filename, "w");
if ( output == NULL ) return -1;
// file is open
for(int i = 0; i < size; i+= 1)
{
unsigned used = sprintf( (string + ix), "%dn", array[i] );
ix += used;
} 
fputs(string, output);
fclose(output);
return ix;
}
int fputsArray_b( unsigned size, int*  array , const char* filename)
{
unsigned ix = 0; // bytes written
FILE*    output = fopen( filename, "w");
if ( output == NULL ) return -1;
// file is open
for(int i = 0; i < size; i+= 1)
ix += fprintf( output, "%dn", array[i]);
fclose(output);
return ix;
}

程序写入两个相同的文件…

相关内容

  • 没有找到相关文章

最新更新