我对 C 编程还很陌生,但是 fprintf()
和 printf()
的行为很奇怪,我很困惑为什么——我需要一些帮助来理解并诊断此问题。
fprintf()
删除数组元素
首先,我将一个填充的 malloc 分配的四元素 char** 数组传递给一个简单的函数,该函数将写入一个文件,数组中的所有内容都显示正常,所有四个元素都包含正确的数据。 main() 中的函数调用如下所示。我的数组是header。
注意:由于函数头参数的原因,我不得不将这个普通的 (char** array)
转换为这个函数参数中的常量。我们的教授给了我们头文件,我们无法更改其中的任何内容。
pgmWrite((const char**) header, (const int**) matrix,
rowPixels, colPixels, outFile);
接下来,在执行 fprintf() 和 printf() 函数之前停止调试器,显示数组的屏幕截图仍然填充了我的 4 个元素。
pgmWrite()
- Showing array is still fine
执行fprintf()后观察数组的第4个元素。
After fprintf()
executes, element 3 memory is wiped out.
运行时,printf()
执行数组打印,与调试器中显示的完全相同,在第 3 个元素处结束。通常在那个地方不打印任何东西,或者在极少数情况下打印垃圾字符。 printf()
的行为与 fprintf()
的工作方式完全相同。
伙计们,我在这里不知所措,请帮助我理解我做错了什么。我只能提供这两个屏幕截图,基于我是新成员。我会尽力提供尽可能多的信息。谢谢。这是我的程序的简化版本。请记住,教授给了我们函数声明并告诉我们不能更改它们。所以,我必须使用我这里的东西。此外,由于这是 fileIO,您需要找到一个 *.pgm 文件来测试它。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define rowsInHeader 4
#define maxSizeHeadRow 200
int ** pgmRead( char **header, int *numRows, int *numCols, FILE *in ){
// INITIALIZING
char *headArr[rowsInHeader][maxSizeHeadRow];
char buffer[100];
int r = 0;
fpos_t pos;
// CREATE: Header
while (r < 4){
// IF: Row in pgm file header lists the dimensions of matrix
if (r == 2){
// CURSOR: Saving pointer location in file (see notes in header for method reference)
fgetpos(in, &pos);
// ASSIGN: Dereference column and row pointers from file
fscanf(in, "%d %d", numCols, numRows);
// CURSOR: Moving back to saved pointer location (see notes in header for method reference)
fsetpos(in, &pos);
}
// ASSIGN: Copying header row into array
fgets(buffer, maxSizeHeadRow, in);
strcpy((char*)headArr[r], buffer);
// POINTER: Reference pointer to headArr[]
header[r] = (char*)headArr[r];
// TRAVERSE: To next row in file
r++;
}
// NOTE: Placeholder for return type
return 0;
}
int pgmWrite( const char **header, const int **pixels, int numRows, int numCols, FILE *out ){
// INITIALIZING
int i = 0;
// WRITE: Header
for (i = 0; i < rowsInHeader; i++){
fprintf(out, "%s", header[i]);
printf("%s", header[i]);
}
return 0;
}
int main(int argc, char *argv[]){
char **header = (char**)malloc(rowsInHeader * sizeof(char));
FILE *inFile = fopen("smallFile.pgm", "r");
FILE *outFile = fopen("TestPicture.ascii.pgm", "w");;
int rowPixels = 0;
int colPixels = 0;
int **matrix = NULL;
// READ & WRITE
matrix = pgmRead(header, &rowPixels, &colPixels, inFile);
pgmWrite((const char**)header, (const int**)matrix, rowPixels, colPixels, outFile);
// FINALIZING
fclose(inFile);
free(header);
return 0;
}
最佳答案
您没有正确分配数组。这一行:
char **header = (char**)malloc(rowsInHeader * sizeof(char));
使 header
指向未初始化的内存区域,大小为 4
字节。
然后在您的 PGM 函数中编写:
header[r] = (char*)headArr[r];
代码header[r]
表示访问headArr
指向的空间中存储的第r
指针。但是由于该空间只有 4 个字节大,所以您实际上是在注销到远处的狂野蓝色。
此外,(char *)headArr[r]
是一个错误。如果你没有使用强制转换,你的编译器会警告你这个错误。您应该避免在代码中使用强制转换,尤其是使用它们来消除警告。你在对编译器说“嘘,我知道我在做什么”,而实际上你并不知道自己在做什么。
headArr
的整个方法从一开始就存在缺陷:即使您实际上编写了正确的代码来实现您正在尝试的内容,您也会将指针返回到空间中,该空间在函数返回。
基本上整个 pgmRead
函数是一团糟,从头开始会更容易。但是这一次,请仔细考虑分配内存的时间和位置,以及表达式的类型,不要使用强制转换。让 pgmRead
函数完成所有分配。
(不幸的是,根据您的描述,您似乎必须使用强制转换来调用 pgmWrite
函数,因为它的签名有错误。const int **
应该是 const int * const *
,对于 const char **
也是类似的。我建议实际更改 pgmWrite
的签名因此,让你的程序工作,然后一旦一切正常,然后回到你被迫使用的损坏版本。)
阅读 C FAQ - arrays and pointers也可能有用。
关于C - fprintf() & printf() 删除数组元素内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33724173/