C:使用malloc和realloc将初始内存加倍

我还在学习动态内存如何工作以及malloc,realloc业务的新function,需要真正的帮助。 我的目标是读取包含一些段落的文件,并将这些行动态存储在一个字符串数组中。 可存储的初始行数为10,如果不足,我们需要将内存数量加倍并打印带行号的消息,我们将内存加倍。

int main(int argc, char* argv[]) { char* lines; int line = 0; lines = malloc(10 * sizeof(char)); while(fgets(lines, sizeof(lines), stdin) { if(lines[strlen(lines)-1] != '\n') { lines = realloc(lines, 5); line++; printf("Reallocating to %d lines", line); { } } 

我完全陷入困境,需要任何我能找到的帮助。

使用您的代码,您将能够只存储一个段落。 在你的循环lines变量一直被覆盖。 此外,看看realloc()原型:

 void *realloc(void *ptr, size_t size); 

什么手册页说:

realloc()函数将ptr指向的内存块的大小更改为size字节。

所以,你总是将你的lines变量改为5的大小。你没有增加它的大小。
一种可能的方法:

  • 有一个缓冲区,你在那里存储由fgets()读取的行,
  • 有一个指向指针的动态数组; 将char** lines视为char* lines[SOME_SIZE]
  • 每次fgets()成功时,将内存分配给当前由缓冲区保存的存储行,然后将其分配给数组中的指针。
  • 如果达到行的限制,将行的大小加倍并在数组上调用realloc()

和Alter Mann一样,我用q来退出循环。
这是完整的代码:

 #include  #include  #include  int main(void) { char** lines = NULL; int i; int curr_row = 0; int rows = 5; int columns = 100; char buf[100]; lines = (char**)malloc(rows*sizeof(char*)); while (fgets(buf, columns, stdin) != NULL) { if (strcmp(buf, "q\n") == 0) { break; } lines[curr_row] = malloc(strlen(buf)+1); strcpy(lines[curr_row], buf); curr_row++; if (curr_row == rows) { rows *= 2; lines = (char**)realloc(lines, rows*sizeof(char*)); printf("reallocated lines to %d rows\n",rows); } } printf("\nYOUR PARAGRAPH: \n"); for (i = 0; i < curr_row; i++) { printf("%s",lines[i]); free(lines[i]); } free(lines); return 0; } 

永远记得free()分配的内存。

使用realloc你可以增加行数。

q退出循环:

 #include  #include  #include  #define BUF_LEN 64 extern char *strdup(const char *); int main(void) { char **arr = NULL; char buf[BUF_LEN]; size_t i, n = 0; while (fgets(buf, BUF_LEN, stdin)) { if (strcmp(buf, "q\n") == 0) break; arr = realloc(arr, sizeof(*arr) * (n + 1)); if (arr == NULL) { perror("realloc"); exit(EXIT_FAILURE); } arr[n] = strdup(buf); if (arr[n++] == NULL) { perror("strdup"); exit(EXIT_FAILURE); } } for (i = 0; i < n; i++) { printf("%s", arr[i]); free(arr[i]); } free(arr); } 

void* realloc (void* ptr, size_t size);

将内存块重新分配给ptr指向的第一个字节。

解决此问题的一种方法是:您需要累积在某个变量中存储文件所需的字节数,并将此值传递给realloc调用。

另一种方法是如果你需要将文件读入内存我想这可以在没有realloc情况下完成:只是初步获取文件长度。

还有一件事: malloc(10 * sizeof(char))为10个字符分配内存,而不是10行。

UPD:

这是一个没有realloc读取文件的实现。 也许它被夸大了。

 #include  #include  #include  /* * Illustrates reading file into memory */ int main(int argc, char** argv) { // Checking command line arguments if(argc != 2) { printf("Usage:\nexec_name path/to/file"); } // Opens file by path specified in first command line argument FILE* fileDesc = fopen(argv[1], "r"); // We got a data structure that describes file // Errors are possible if(!fileDesc) { printf("Error opening file %s", argv[1]); } // Figuring out file length while(!feof(fileDesc)) // feof() returns 0 if it encountered an end of file fgetc(fileDesc); // Reads unsigned char from file and advances file cursor inside fileDesc data structure // Errors are possible if( ferror(fileDesc) ) { perror(argv[1]); return EXIT_FAILURE; } // At this point cursor of fileDesc stands at the end of file // Getting offset of the cursor, ie number of bytes long int numOfBytes = ftell(fileDesc); // Errors are possible if(numOfBytes == -1L) { printf("Error while reading file %s", argv[1]); return EXIT_FAILURE; } // Allocating memory to read a file char* fileBuf = malloc(numOfBytes * sizeof(char)); // Placing cursor at the beginning of the file rewind(fileDesc); // BTW, you can imagine reading a file as operating with a magnetic tape: // read one byte, advanced tape, reached end of tape, rewinded tape. // This goes back to the old times when streamers were actually used as a persistent memory. // Reading file long int actRead = (long int)fread(fileBuf, sizeof(char), numOfBytes, fileDesc); // Assertions are nice things to control internal state of the program and localize errors assert(numOfBytes == actRead); printf("Read %i bytes", actRead); return EXIT_SUCCESS; }