我在將數字從檔案存盤到一維陣列時遇到問題。我想存盤數字而不給陣列int numberArray[11]的大小。這些是我試圖從 input.txt 檔案中讀取的數字
200 53 65 98 183 37 122 14 124 65 67
int main()
{
FILE *myFile;
myFile = fopen("input.txt", "r");
//read file into array
int numberArray[11];
int i;
if (myFile == NULL)
{
printf("Error Reading File\n");
exit (0);
}
//Store number to array
for (i = 0; i < 11; i )
{
fscanf(myFile, "%d,", &numberArray[i] );
}
/*
//Print array
for (i = 0; i < 11; i ){
printf("%d\n", numberArray[i]);
}
*/
//Close the file
fclose(myFile);
//FCFS the array
FCFS(numberArray);
return 0;
}
正如您在我的代碼中看到的那樣,我創建了一個大小為 11 的 int 陣列,因為我試圖將 11 個數字讀入陣列。假設我不知道輸入檔案中的數字。如何分配陣列?
Ps 我的代碼有效,但我只想知道在這種情況下有效的方法是什么。
uj5u.com熱心網友回復:
這個問題可能有點模糊,但我想你想知道如何設法從檔案中讀取可變數量的資料。實際上有很多方法可以管理它……其中一些是:
- 讀取檔案并僅在分配之前計算數字(不讀取資料)。然后分配陣列并讀取資料。
- 每次陣列變短時,動態分配和重新分配陣列大小的兩倍。
- 使用串列:)
方法一:
int count = 0;
int var;
while(fscanf(myFile, "%d", &var) == 1){ //included only a snippet instead of full code
count ;
}
int numberArray[count];
//iterate again and read the data
方法二:
int curr_size = 2; //you can take any positive integer, but be wary of heap overflow(large allocation)
int i = 0;
int* varr = malloc (sizeof(int) * curr_size);
while(fscanf(myFile, "%d", &varr[i ]) == 1){
if(i == curr_size){
curr_size *= 2; //you can do instead of *, depends on what you're dealing with... '*' can sometimes lead to unnecessary allocation of big chunks of memory
int* temp = realloc(varr, sizeof(int)*curr_size);
if(temp == NULL) { printf("Error allocating"); return -1;}
free(varr);
varr = temp;
}
}
// 'i' will give you total numbers read you can realloc if you like
//if you use it for reading string be sure to account for '\0' //if you use it for reading string be sure to account for '\0'
方法3:使用串列資料結構存盤可變數量的資料。那會容易得多
方法 2 是程式員之間從 c 中的源讀取可變大小的字串(字符序列)最常用的方法之一。
方法 1 對初學者來說會更容易。
方法 3 將更容易讀取整數。
嘗試一切會幫助你成長。
uj5u.com熱心網友回復:
有2個經典解決方案2這個
首先是在檔案中有一個數字,指示有多少個數字,并使用 VLA 調整陣列的大小。IE
int num;
fscanf(myFile, "%d", &num);
int numbers[num];
(應檢查 fscanf 的回傳值是否為 1)
第二個是使用 malloc 動態分配空間 - 比如 5 開始 - 并使用 realloc 將陣列的大小保持加倍,直到到達檔案末尾
int size = 5;
int count = 0;
int *numbers = malloc(size * sizeof(int));
int numin;
while (fscanf(myFile, "%d", &numin) != EOF){
if(count== size){
size *= 2;
numbers = realloc(numbers, size * sizeof(int));
}
count ;
numbers[count] = numin;
}
uj5u.com熱心網友回復:
當想要讀取和存盤未知數量的任何內容時,您必須為所讀取的任何內容提供有效的存盤空間。您通常通過使用或分配一塊記憶體malloc(),并將新分配的記憶體塊的起始地址分配給適當型別的指標來做到這一點。calloc()realloc()
要根據需要增加記憶體塊的大小,您需要跟蹤當前allocated存盤的物件數量和數量used。當used == allocated您必須realloc()使用帶有realloc().
您使用臨時指標的原因是realloc()失敗時回傳NULL。如果您分配給您的實際指標而不是臨時指標,那么您將地址覆寫到您的指標持有的當前記憶體塊中NULL。這會造成記憶體泄漏,因為無法再釋放該記憶體塊。
如果事件realloc()失敗,臨時指標將設定為NULL,但存盤在原始指標中的當前記憶體塊的地址不會被釋放,并且它保持有效,將收集到的資料保存到故障點。該資料有效且可用,因此無需在realloc()失敗時退出。
每次您都可以根據自己的喜好增加記憶體realloc(),但最好避免為每個新添加的物件重新分配。(即使記憶體被mmap編輯,這也是低效的)。一種在記憶體增長和所需重新分配數量之間提供合理平衡的方案是每次需要重新分配時將當前分配的大小加倍。當您完成分配的記憶體時,不要忘記free()它。
一個簡短的例子,它從作為命令列第一個引數提供的檔案名中讀取整數(或者stdin如果沒有提供引數,則默認讀取)可以這樣寫:
#include <stdio.h>
#include <stdlib.h>
#define NINTS 1 /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
int val, *arr = NULL; /* val to read and ptr to memory */
size_t allocated = 0, used = 0; /* number ints allocated & used */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("fopen-fp");
return 1;
}
while (fscanf (fp, "%d", &val) == 1) { /* for each int read from file */
if (used == allocated) { /* check if realloc needed */
if (!allocated) { /* not allocated set to NINTS */
allocated = NINTS;
}
/* always realloc using a temproary pointer */
void *tmp = realloc (arr, 2 * allocated * sizeof *arr);
if (!tmp) { /* validate EVERY allocation */
perror ("realloc-tmp");
break; /* break on error, arr still OK */
}
arr = tmp; /* set arr to newly allocated block */
allocated *= 2; /* update the number of ints allocated */
}
arr[used ] = val; /* add value to block of memory */
}
for (size_t i = 0; i < used; i ) /* output results */
printf ("%3zu - %d\n", i, arr[i]);
free (arr); /* don't forget to free what you allocate */
}
(注意: realloc()只要設定了指標,就可以用于第一次分配NULL)
示例使用/輸出
使用您的示例,您可以執行以下操作:
$ echo "200 53 65 98 183 37 122 14 124 65 67" | ./bin/dynarrint
0 - 200
1 - 53
2 - 65
3 - 98
4 - 183
5 - 37
6 - 122
7 - 14
8 - 124
9 - 65
10 - 67
記憶體使用/錯誤檢查
在您撰寫的任何動態分配記憶體的代碼中,對于分配的任何記憶體塊,您有兩個責任:(1)始終保留指向記憶體塊起始地址的指標,(2)它可以在沒有時被釋放更需要。
您必須使用記憶體錯誤檢查程式,以確保您不會嘗試訪問記憶體或寫入超出/超出分配塊的邊界,嘗試讀取或基于未初始化值的條件跳轉,最后確認釋放所有分配的記憶體。
對于 Linuxvalgrind是正常的選擇。每個平臺都有類似的記憶體檢查器。它們都易于使用,只需通過它運行您的程式即可。
$ echo "200 53 65 98 183 37 122 14 124 65 67" | valgrind ./bin/dynarrint
==12405== Memcheck, a memory error detector
==12405== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==12405== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==12405== Command: ./bin/dynarrint
==12405==
0 - 200
1 - 53
2 - 65
3 - 98
4 - 183
5 - 37
6 - 122
7 - 14
8 - 124
9 - 65
10 - 67
==12405==
==12405== HEAP SUMMARY:
==12405== in use at exit: 0 bytes in 0 blocks
==12405== total heap usage: 6 allocs, 6 frees, 5,240 bytes allocated
==12405==
==12405== All heap blocks were freed -- no leaks are possible
==12405==
==12405== For counts of detected and suppressed errors, rerun with: -v
==12405== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始終確認您已釋放所有已分配的記憶體并且沒有記憶體錯誤。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/465495.html
標籤:C
下一篇:如何顯式型別轉換指標
