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; }