全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2085
推到 Plurk!
推到 Facebook!

鏈結串列+結構指標

答題得分者是:syntax
hsien0701
一般會員


發表:4
回覆:10
積分:2
註冊:2008-12-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2009-10-22 01:15:04 IP:114.43.xxx.xxx 訂閱
各位高手大大好:
以下為小弟的程式碼,目的為將每個fin00%d.txt檔(各16筆10進位數字)
共有四個,用串列的方式,最後在一次輸出為一個48筆的out.txt檔

#include
#include
#include
#include

#define size 160

void Read (char file_name[40]); //讀.txt副程式

struct node
{
unsigned char buffer_1D[size];
struct node *next;
};
typedef struct node Node;
Node *first, *current, *previous;

int main(void)
{
int i=0,j=0,n=0;
int Data_num=1;
char InName[40] ="fin000.txt";
//char OutNmae[40] ="fout000.txt";

for(Data_num=1;Data_num<=4; Data_num )
{
sprintf(InName,"fin00%d.txt",Data_num);
//sprintf(OutNmae,"fout00%d.txt",Data_num);
current = (Node*)malloc(sizeof(Node*));

Read (InName); //讀.txt檔副程式

///----------------以下為串列部分-------------
current = (Node*)malloc(sizeof(Node*));
scanf("%d",current->buffer_1D);
if(Data_num==0)
{
first=current;
}
else
{
previous->next=current;
current->next=NULL;
previous=current;
}

}
current=first;
while(current!=NULL)
{
previous=current;
current=current->next;
free(previous);
}
//----------------------------------------
return 0;
}
void Read ( char file_name[40])
{
int i=0,j=0,n=0;
unsigned char in0;

unsigned char *input;
input = (unsigned char*)malloc(160*sizeof(void*));

FILE *fp_input;
fp_input = fopen(file_name,"rb");
if(fp_input == NULL)
{
printf( "\n Can't open file %s",file_name);
system("pause");
exit(0);
}
n=0;
while ((fscanf(fp_input, "%d\n",&in0))!=EOF)
{
*input=in0;
current=*input;//????????出現錯誤訊息
n ;
}
fclose(fp_input);
free(input);
}


小弟可以把每個.txt檔裡面的資訊一個一個讀出來,
但是沒有辦法把讀出來的資料讀進去指標結構current當中
以便利用串列把所有資料串起來,
在current=*input;會出現
error C2440: '=' : cannot convert from 'unsigned char' to 'struct node *'
Conversion from integral type to pointer type requires reinterpret_cast
, C-style cast or function-style cast

請各位救救我,我僵在這近四天了,
會這樣的目的是因為要應負將來資料庫不斷的存放
但是總不能每次都把程式打開來再改變一些陣列大小
所以做了這個小實驗
請各位好心人士幫幫忙,指點指點要如何改程式,或是給別的建議
還有就是我這種想法型的通嗎??
我只為傳統的C而已.....XD....感激不盡 拜託拜託!!
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#2 引用回覆 回覆 發表時間:2009-10-22 08:48:23 IP:59.125.xxx.xxx 訂閱
總不能每次都把程式打開來再改變一些陣列大小 <---- Why not ?


current=*input;//????????出現錯誤訊息
這錯誤是當然的

struct node
{
unsigned char buffer_1D[size];
struct node *next;
};

current 是結構,當然不能指派給 node 錯誤訊息說的很清楚 --> cannot convert from 'unsigned char' to 'struct node *'

因為你 buffer_1D 是宣告固定的大小,且是自動建立的,所以你必須要手動複製資料進去,可以使用迴圈,或是記憶體複製函式

memcpy(current->buffer_1D, input, size) 應該是這樣,若有小差異,請看看函式 Help,自己修正

如是你結構宣告 unsigned char *buffer_1D ,這樣,你只要 current->buffer_1D = input 這樣就可以了,至於為什麼,我想你應該要懂,如果不懂,先去看看書上指標應用一節再說

同時你的程式如果是這樣,感覺錯誤不少,有完整貼出來嗎?,提示在其下,紅字

===================引 用 hsien0701 文 章===================
各位高手大大好:
以下為小弟的程式碼,目的為將每個fin00%d.txt檔(各16筆10進位數字)
共有四個,用串列的方式,最後在一次輸出為一個48筆的out.txt檔

#include
#include
#include
#include

#define size 160

void Read (char file_name[40]); //讀.txt副程式

struct node
{
unsigned char buffer_1D[size];
struct node *next;
};
typedef struct node Node;
Node *first, *current, *previous;

int main(void)
{
int i=0,j=0,n=0;
int Data_num=1;給 for 迴圈的變數,不用初始化,同時最好不要混用給 for 會圈的變數與一般變數,但初始化也不算錯誤,只是多此一舉
char InName[40] ="fin000.txt";
//char OutNmae[40] ="fout000.txt";

for(Data_num=1;Data_num<=4; Data_num )
{
sprintf(InName,"fin00%d.txt",Data_num);
//sprintf(OutNmae,"fout00%d.txt",Data_num);
current = (Node*)malloc(sizeof(Node*));

Read (InName); //讀.txt檔副程式
A-->
///----------------以下為串列部分-------------
<--B
current = (Node*)malloc(sizeof(Node*)); 若 A--><--B 間沒有對 current 加以保存或處理,這一行,會造成剛剛讀進來的資料,再也參考不到
scanf("%d",current->buffer_1D); 假設這一行是你故意加的,所以正式程式不會出現
if(Data_num==0)混用fo4迴圈,若沒有再重設,永遠不會等於 0
{
first=current;
}
else
{
previous->next=current; 你必須確認 previous 不是 null,在上面程式碼,沒有看到,這裡也沒有檢核,這樣的話一定會出錯一次
current->next=NULL;這一行不需要,應該改在宣告 current 記憶體後,就初始化為 null
previous=current;
}

}
current=first;
while(current!=NULL)
{
previous=current;
current=current->next;
free(previous);
}
//----------------------------------------
return 0;
}
void Read ( char file_name[40])
{
int i=0,j=0,n=0;
unsigned char in0;

unsigned char *input;
input = (unsigned char*)malloc(160*sizeof(void*));

FILE *fp_input;
fp_input = fopen(file_name,"rb");
if(fp_input == NULL)
{
printf( "\n Can't open file %s",file_name);
system("pause");
exit(0);
}
n=0;
這裡,這個 Read(xxx) 與 current 是弱關連,使用前應該檢核 current 是否不為 null 再繼續
while ((fscanf(fp_input, "%d\n",&in0))!=EOF)
{
*input=in0;
current=*input;//????????出現錯誤訊息
如果這裡要這樣用應該是 current->buffer_1D[x] = in0;不需要在多個 input (while 前要加入 x = 1;)
如果是要先收集在 input 才指派,那 current->buffer_1D = input 應該放在 while 迴圈結束後,同時 buffer_1d 應為 char * 型態
x ;
if (x > size) {跳離迴圈}

n ;
}
fclose(fp_input);
free(input);
}
最後,一堆變數沒用到,如果是沒貼出來,那就算了,不然,沒用到,就不應宣告,就這樣

小弟可以把每個.txt檔裡面的資訊一個一個讀出來,
但是沒有辦法把讀出來的資料讀進去指標結構current當中
以便利用串列把所有資料串起來,
在current=*input;會出現
error C2440: '=' : cannot convert from 'unsigned char' to 'struct node *'
Conversion from integral type to pointer type requires reinterpret_cast
, C-style cast or function-style cast

請各位救救我,我僵在這近四天了,
會這樣的目的是因為要應負將來資料庫不斷的存放
但是總不能每次都把程式打開來再改變一些陣列大小
所以做了這個小實驗
請各位好心人士幫幫忙,指點指點要如何改程式,或是給別的建議
還有就是我這種想法型的通嗎??
我只為傳統的C而已.....XD....感激不盡 拜託拜託!!
hsien0701
一般會員


發表:4
回覆:10
積分:2
註冊:2008-12-15

發送簡訊給我
#3 引用回覆 回覆 發表時間:2009-10-22 19:29:05 IP:114.43.xxx.xxx 訂閱
syntax大大感謝您:

您上ㄧ篇的指導給我的啟示 這是我修改過後的程式碼
可是輸出都是只輸出最後一個.txt裡頭的資訊
可否請您在指點一下怎嚜把四個.txt的資訊循序輸入經串列一起輸出成ㄧ個.txt檔
因為我不知道怎嚜觀看動態記憶體裡頭的資訊
我只能不停的輸出成.txt檔的結果看到底有沒有每筆資料都讀出
所以可否請各位教學一下..拜託拜託!!


#include
#include
#include
#include

#define size 160
void Read (char file_name[40]);
void write ();
void append();
int Data_num;

struct node
{
unsigned char buffer_1D[size];
struct node *next;
};
typedef struct node Node;
Node *first, *current;

unsigned char *output;
unsigned char buffer[4*size]={0};


int main(void)
{
int i=0,j=0,n=0;
output = (unsigned char *)malloc(sizeof(void*));

char InName[40] ="fin000.txt";

for(Data_num=1;Data_num<=4; Data_num )
{
sprintf(InName,"fin00%d.txt",Data_num);
first = (Node*)malloc(sizeof(Node*));
Read (InName);
first->next=NULL;
current=first;
printf(" %d\n",current->buffer_1D[n]);
system("pause");
append();
while(first!=NULL)
{
first=first->next;
}
write();
}
return 0;
}

void append()
{
Node *previous;
previous=(Node*)malloc(sizeof(Node*));
current->next=previous;

previous->next=NULL;
current=previous;
}

void Read ( char file_name[40])
{
int i=0,j=0,n=0;
unsigned char in0;

FILE *fp_input;
fp_input = fopen(file_name,"rb");
if(fp_input == NULL)
{
printf( "\n Can't open file %s",file_name);
system("pause");
exit(0);
}
n=0;
while ((fscanf(fp_input, "%d\n",&in0))!=EOF)// && first!=NULL)
{
first->buffer_1D[n]=in0;
buffer[n]=in0;
n ;
//printf("%d %d %d\n",n,first->buffer_1D[n] ,in0);
//system("pause");
if(n>size)
{
break;
}
}
fclose(fp_input);
}

void write()
{
FILE *fp_output;
int i=0,j=0,n=0;
fp_output =fopen("out.txt","wb");
if (fp_output == NULL)
{
printf("\n Can't open file \n");
}
else
{
for(n=0; n {
*output=buffer[n];
fprintf(fp_output," %d \n",*output);
}
}
fclose(fp_output);

}

syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#4 引用回覆 回覆 發表時間:2009-10-23 09:44:02 IP:59.125.xxx.xxx 訂閱
1. first = (...)malloc... 改為 current = (...) malloc ... , 使用 current 操作,(first, previous 就只是用來記錄,不可以用 malloc)
如果使用正向取得串列(使用 first,與現在這種方式),需要加上,如果是迴圈第一次執行就將 current = first
2. read()中,n = 1 , n > size or n = 0 , n >= size 會圈才會在 1 ~ size,不然 n = 0, n > size 會跑 size 1 次
3. append() 中,如果是第一次(previous = null 或其他判斷條件),則 previous = current,然後結束,如果不是就 previous->next = current, previous = current,然後結束
4. 既然使用串列 參數 buffer 就是多餘的
5. while (first != Null) 搬移到 write() 內,替換調 else 內的 for
6. 迴圈為先用 current = first ,然後會圈內 fprint 改輸出 current->buffer_1D,最後 current = current->next,迴圈做到 current->next 沒有東西為止,就可以輸出整個串列的資料

===================引 用 hsien0701 文 章===================
syntax大大感謝您:

您上ㄧ篇的指導給我的啟示 這是我修改過後的程式碼
可是輸出都是只輸出最後一個.txt裡頭的資訊
可否請您在指點一下怎嚜把四個.txt的資訊循序輸入經串列一起輸出成ㄧ個.txt檔
因為我不知道怎嚜觀看動態記憶體裡頭的資訊
我只能不停的輸出成.txt檔的結果看到底有沒有每筆資料都讀出
所以可否請各位教學一下..拜託拜託!!


#include
#include
#include
#include

#define size 160
void Read (char file_name[40]);
void write ();
void append();
int Data_num;

struct node
{
unsigned char buffer_1D[size];
struct node *next;
};
typedef struct node Node;
Node *first, *current;

unsigned char *output;
unsigned char buffer[4*size]={0};


int main(void)
{
int i=0,j=0,n=0;
output = (unsigned char *)malloc(sizeof(void*));

char InName[40] ="fin000.txt";

for(Data_num=1;Data_num<=4; Data_num )
{
sprintf(InName,"fin00%d.txt",Data_num);
first = (Node*)malloc(sizeof(Node*));
Read (InName);
first->next=NULL;
current=first;
printf(" %d\n",current->buffer_1D[n]);
system("pause");
append();
while(first!=NULL)
{
first=first->next;
}
write();
}
return 0;
}

void append()
{
Node *previous;
previous=(Node*)malloc(sizeof(Node*));
current->next=previous;

previous->next=NULL;
current=previous;
}

void Read ( char file_name[40])
{
int i=0,j=0,n=0;
unsigned char in0;

FILE *fp_input;
fp_input = fopen(file_name,"rb");
if(fp_input == NULL)
{
printf( "\n Can't open file %s",file_name);
system("pause");
exit(0);
}
n=0;
while ((fscanf(fp_input, "%d\n",&in0))!=EOF)// && first!=NULL)
{
first->buffer_1D[n]=in0;
buffer[n]=in0;
n ;
//printf("%d %d %d\n",n,first->buffer_1D[n] ,in0);
//system("pause");
if(n>size)
{
break;
}
}
fclose(fp_input);
}

void write()
{
FILE *fp_output;
int i=0,j=0,n=0;
fp_output =fopen("out.txt","wb");
if (fp_output == NULL)
{
printf("\n Can't open file \n");
}
else
{
for(n=0; n
{
*output=buffer[n];
fprintf(fp_output," %d \n",*output);
}
}
fclose(fp_output);

}

編輯記錄
syntax 重新編輯於 2009-10-23 09:45:15, 註解 無‧
hsien0701
一般會員


發表:4
回覆:10
積分:2
註冊:2008-12-15

發送簡訊給我
#5 引用回覆 回覆 發表時間:2009-10-24 00:43:52 IP:114.43.xxx.xxx 訂閱
syntax大您好:
可否請您下面兩點..再多說明一些些

1. first = (...)malloc... 改為 current = (...) malloc ... , 使用 current 操作,(first, previous 就只是用來記錄,不可以用 malloc)
如果使用正向取得串列(使用 first,與現在這種方式),需要加上,如果是迴圈第一次執行就將 current = first
6. 迴圈為先用 current = first ,然後會圈內 fprint 改輸出 current->buffer_1D,最後 current = current->next,迴圈做到 current->next 沒有東西為止,就可以輸出整個串列的資料

在次感謝您的指導^____^
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#6 引用回覆 回覆 發表時間:2009-10-24 14:46:36 IP:140.127.xxx.xxx 訂閱
你的邏輯,有點混亂,所以建議你,在沒有能夠很熟練或很清楚的操作,單一參數多意義的操作,盡量避免 (就算老手,沒強烈好處,也是不會去用)
最好先將事情單純化

用來建立資料的參數,與用來記錄的參數分開,你會永遠輸出最後一筆,或發生永遠輸出第一筆,表示,你的輸出正確了,但是資料的存取卻還不正確
所以 first, last, previous 等用來記錄的,都只用來記錄,指的是只接受其他參數最為指派對象,如 first = current ,而不用來建立新物件,如 first = new, first = ... malloc ...等
同時參數的名稱,要有正確的意義 first ,我個人認為,一般人有也是如此認為,first 指的是第一個,第一次,所以 fisrt = ... malloc 並不適當,改為 current 表示「目前、當下」會叫好,然後統一以下相對應、相同的參數
(不過要是你堅持,也是可以使用 first 為其名稱,只要你自己不混淆,因為寫程式當下不會,但改天回頭看時,也要不會混淆才行,這樣才表示該名稱,是你內心真的認為的意義,不然將來必定會發生,自己寫的程式,自己看不懂)

正向取得串列,會用一個參數 (如 first),記錄第一筆資料,同時使用 next 連接到下一筆,一旦記錄後,該參數就不在接受新指派數值,所以會進行判定是否第一次

你原來的 append() 會新建物件 previous = ... malloc ...,不知道你是否清楚,這動作的意涵?
previous 應該是紀錄上一筆是什麼,而不是新建一個物件,同時新建的物件 buffer_1D 內是空的,那這動作的意義何在?
你有意識到這意涵嗎?
同時 current->next 應是指到下一筆,而不是前一筆 previous (如果我對 previous 等變數名稱與你所認知不同,只要調整我或你的認知,整個邏輯一該還是正確的,只是,你的程式前後的參數邏輯是相反的,所以才會跟你說,參數名稱不是亂取就可以,要對自己有正確、固定的意義)

再來,既然只使用 current 操作新建節點,應該只會有 current 會 malloc,同時也只有新建物件時,會用上

程式可以使用這樣方式來輸出串列 (語法不是正確的語言,請自行依據語言版本修正,此僅邏輯)
current = first 取開頭
while current->next != null 做到沒有下一筆,即最後,為止
{
printf ... current->buffer_1d ... 輸出資料
current = current->next 取下一筆
}

===================引 用 hsien0701 文 章===================
syntax大您好:
可否請您下面兩點..再多說明一些些

1. first = (...)malloc... 改為 current = (...) malloc ... , 使用 current 操作,(first, previous 就只是用來記錄,不可以用 malloc)
如果使用正向取得串列(使用 first,與現在這種方式),需要加上,如果是迴圈第一次執行就將 current = first
6. 迴圈為先用 current = first ,然後會圈內 fprint 改輸出 current->buffer_1D,最後 current = current->next,迴圈做到 current->next 沒有東西為止,就可以輸出整個串列的資料

在次感謝您的指導^____^
hsien0701
一般會員


發表:4
回覆:10
積分:2
註冊:2008-12-15

發送簡訊給我
#7 引用回覆 回覆 發表時間:2009-10-24 18:27:28 IP:118.161.xxx.xxx 訂閱
syntax大您好:
我意會您的說法..把我重新寫好的程式給您看
順便註解我的意義......請您過目一下...拜託拜託!!
也方便請您在給予指教...感激您^^
我會努力學習的!!

#include
#include
#include
#include
#define size 160

void Read (char file_name[40]);
void write ();
void append();
int Data_num;

struct node
{
unsigned char buffer_1D[size];
struct node *next;
};
typedef struct node Node;

linked list的基礎就是struct,所以先建立一個自訂的struct型別,因為linked list是靠struct串聯起來,所以最後要多一個struct pointer指向下一個struct
Node *current=NULL;
Node *previous=NULL;
Node *first=NULL;

建立linked list最基本需要三個指標,first指向linked list的第一個structcurrent指向目前剛建立的struct
prev則指向前一個struct,目的在指向下一個struct

int main(void)
{
int i=0,j=0,n=0;
output = (unsigned char *)malloc(sizeof(void*));

char InName[40] ="fin000.txt";

for(Data_num=1;Data_num<=4; Data_num )
{
sprintf(InName,"fin00%d.txt",Data_num);
current = (Node*)malloc(sizeof(Node*));

if(Data_num==4)
{
current=NULL;
}
current->next=NULL;




malloc()
並不是一定會成功,若記憶體不足時,仍然會失敗,所以必須判斷是否傳回NULL


























一個新的
node,一定是linked list最後一個node,所以將current->nextnull



Read (InName);
正式將輸入的資料填進struct

if (first == NULL)
{
first= current;
}
else
{
previous->next = current;
}
previous = current;
判斷若是第一個node,則將目前的node當成head,若不是第一個node,則將前一個node指向目前的node,完成linked list
連接。最後將目前的node當成前一個node,以備指向下一個node
write();
}
return 0;
}

void Read ( char file_name[40])
{
int i=0,j=0,n=0;
unsigned char in0;

FILE *fp_input;
fp_input = fopen(file_name,"rb");
if(fp_input == NULL)
{
printf( "\n Can't open file %s",file_name);
system("pause");
exit(0);
}
n=1;
while ((fscanf(fp_input, "%d\n",&in0))!=EOF)// && first!=NULL)
{
first->buffer_1D[n]=in0;
n ;
printf("%d %d %d\n",n,first->buffer_1D[n] ,in0);
system("pause");
if(n>size)
{
break;
}
}
fclose(fp_input);
}


void write()
{
current = first;
FILE *fp_output;
int i=0,j=0,n=0;
fp_output =fopen("out.txt","wb");
if (fp_output == NULL)
{
printf("\n Can't open file \n");
}
while(current->next != NULL )
{
fprintf(fp_output," %d \n",current->buffer_1D);
previous = current;
current = current->next;
free(previous);
}
fclose(fp_output);

由於malloc()是將記憶體放在head,而不是放在stack,所以並不會隨著function的結束而釋放,必須要手動使用free()釋放記憶體,
否則會造成memory leak
}

hsien0701
一般會員


發表:4
回覆:10
積分:2
註冊:2008-12-15

發送簡訊給我
#8 引用回覆 回覆 發表時間:2009-10-25 23:42:43 IP:114.37.xxx.xxx 訂閱
syntax大大您好:

我重新張貼..因為我有些地方貼錯了!!不好意思!!
還是一樣我意會您的說法..註解我的程式涵義.....
請您過目一下...拜託拜託!!
也方便請您在給予指教...感激您^^
因為這支程式跑完第一個.txt檔之後就中止了
我實在不太了解我程式這樣的編排 哪裡出了問題
希望可以在勞駕您診斷...我會努力學習的 感謝!!

#include
#include
#include
#include

#define size 160
void Read (char file_name[40]);
void write ();
int Data_num;

struct node
{
unsigned char buffer_1D[size];
struct node *next;
};
typedef struct node Node
;

linked list的基礎就是struct,所以先建立一個自訂的struct型別,因為linked list是靠struct串聯起來,所以最後要多一個struct pointer指向下一個struct
Node *current=NULL;
Node *previous=NULL;
Node *first=NULL;

建立linked list最基本需要三個指標,first指向linked list的第一個structcurrent指向目前剛建立的struct
prev則指向前一個struct,目的在指向下一個struct


int main(void)
{
int i=0,j=0,n=0;
output = (unsigned char *)malloc(sizeof(void*));

char InName[40] ="fin000.txt";

for(Data_num=1;Data_num<=5; Data_num )
{
sprintf(InName,"fin00%d.txt",Data_num);
current = (Node*)malloc(sizeof(Node*));

//printf("%d %d \n",Data_num,current->buffer_1D[1]);
//system("pause");
if(Data_num==5)
{
current=NULL;
}
current->next=NULL;


malloc()並不是一定會成功,若記憶體不足時,仍然會失敗,所以必須判斷是否傳回NULL

























一個新的
node,一定是linked list最後一個node,所以將current->nextnull


Read (InName);
正式將輸入的資料填進struct
if (first == NULL)
{
first= current;
}
else
{
previous->next = current;
}
previous = current;

判斷若是第一個node,則將目前的node當成head,若不是第一個node,則將前一個node指向目前的node,完成linked list
連接。最後將目前的node當成前一個node,以備指向下一個node

write();
}
return 0;
}


void Read ( char file_name[40])
{
int i=0,j=0,n;
unsigned char in0;

FILE *fp_input;
fp_input = fopen(file_name,"rb");
if(fp_input == NULL)
{
printf( "\n Can't open file %s",file_name);
system("pause");
exit(0);
}
n=1;
while ((fscanf(fp_input, "%d\n",&in0))!=EOF)
{
current->buffer_1D[n]=in0;
printf("%d %d %d\n",n,current->buffer_1D[n] ,in0);
system("pause");
n ;
if(n>size)
{
break;
}
}
fclose(fp_input);
}


void write()
{
FILE *fp_output;
int i=0,j=0,n=0;
fp_output =fopen("out.txt","wb");
if (fp_output == NULL)
{
printf("\n Can't open file \n");
}
current = first;
while(current->next!=NULL)
{
fprintf(fp_output," %d \n",current->buffer_1D);
previous = current;
current = current->next;
free(previous);
}
fclose(fp_output);

由於malloc()是將記憶體放在head,而不是放在stack,所以並不會隨著function的結束而釋放,必須要手動使用free()釋放記憶體,
否則會造成memory leak

}


syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#9 引用回覆 回覆 發表時間:2009-10-26 10:15:49 IP:59.125.xxx.xxx 訂閱
1.
如要做到這樣

--> malloc()並不是一定會成功,若記憶體不足時,仍然會失敗,所以必須判斷是否傳回NULL <--

程式應該是

if (current != null) {才工作}



if (current == null) {輸出錯誤訊息,並結束工作}

2.
write () 要放在 for(Data_num=1;Data..... {}
的迴圈以外

你可以思考一下,為何這樣做?

3.
是要,一次讀取完畢,一次顯示,然後一次釋放
或是,一次讀取完畢,分次顯示,然後一次釋放
或是,一次讀取完畢,分次顯示,然後分次釋放
..................................................................
一共 8 總方式的組合,你的程式屬於哪一種?
為什麼顯示為第一次以後,就沒有了?是否跟你釋放記憶體的時機有關?

4.
--> 由於malloc()是將記憶體放在head,而不是放在stack,所以並不會隨著function的結束而釋放,必須要手動使用free()釋放記憶體 <--

這句話是對的,但怪怪的,因為 malloc() 所宣告的,不管放在哪裡,都與 function 是否結束無關
如果照上句話來看,隱含著另一個解釋,就是

如果 malloc 將資料宣告在 stack,就會隨著 function 結束而釋放,所以不用手用 free
(一個「因」--> 「果」,如果反推不成立,那正推也相對沒意義,所以如果正推存在,那必也存在反推)
但事實是只要是 malloc 宣告出來的,都必須使用 free
而且,不管 function 區域內所宣告的非指標參數,是使用 stack (或是 heap) ,都會自動釋放,這是編譯器幫我們做的(以 stack 為例,凡 push 進去的,也都必須 pop 出來,只是目前我們使用 stack ,並不保證,不會有使用 heap 的編譯器出現)
另外 heap 與 stack 都是記憶體的一個區塊,只是我們人定義該區塊為 heap 或是 stack

這是觀念上的一點澄清

程式已經很接近正確,如果你都很清楚了,那接下來,可以思考分割方式,為何要將 read(), write() 獨立出來?以及有些地方的程式碼是否有效率 (通常越少動作達到功能,效率就越高)

===================引 用 hsien0701 文 章===================
syntax大大您好:

我重新張貼..因為我有些地方貼錯了!!不好意思!!
還是一樣我意會您的說法..註解我的程式涵義.....
請您過目一下...拜託拜託!!
也方便請您在給予指教...感激您^^
因為這支程式跑完第一個.txt檔之後就中止了
我實在不太了解我程式這樣的編排 哪裡出了問題
希望可以在勞駕您診斷...我會努力學習的 感謝!!

#include
#include
#include
#include

#define size 160
void Read (char file_name[40]);
void write ();
int Data_num;

struct node
{
unsigned char buffer_1D[size];
struct node *next;
};
typedef struct node Node
;

linked list的基礎就是struct,所以先建立一個自訂的struct型別,因為linked list是靠struct串聯起來,所以最後要多一個struct pointer指向下一個struct
Node *current=NULL;
Node *previous=NULL;
Node *first=NULL;

建立linked list最基本需要三個指標,first指向linked list的第一個structcurrent指向目前剛建立的struct
prev則指向前一個struct,目的在指向下一個struct


int main(void)
{
int i=0,j=0,n=0;
output = (unsigned char *)malloc(sizeof(void*));

char InName[40] ="fin000.txt";

for(Data_num=1;Data_num<=5; Data_num )
{
sprintf(InName,"fin00%d.txt",Data_num);
current = (Node*)malloc(sizeof(Node*));

//printf("%d %d \n",Data_num,current->buffer_1D[1]);
//system("pause");
if(Data_num==5)
{
current=NULL;
}
current->next=NULL;


malloc()並不是一定會成功,若記憶體不足時,仍然會失敗,所以必須判斷是否傳回NULL

























一個新的
node,一定是linked list最後一個node,所以將current->nextnull


Read (InName);
正式將輸入的資料填進struct
if (first == NULL)
{
first= current;
}
else
{
previous->next = current;
}
previous = current;

判斷若是第一個node,則將目前的node當成head,若不是第一個node,則將前一個node指向目前的node,完成linked list
連接。最後將目前的node當成前一個node,以備指向下一個node

write();
}
return 0;
}


void Read ( char file_name[40])
{
int i=0,j=0,n;
unsigned char in0;

FILE *fp_input;
fp_input = fopen(file_name,"rb");
if(fp_input == NULL)
{
printf( "\n Can't open file %s",file_name);
system("pause");
exit(0);
}
n=1;
while ((fscanf(fp_input, "%d\n",&in0))!=EOF)
{
current->buffer_1D[n]=in0;
printf("%d %d %d\n",n,current->buffer_1D[n] ,in0);
system("pause");
n ;
if(n>size)
{
break;
}
}
fclose(fp_input);
}


void write()
{
FILE *fp_output;
int i=0,j=0,n=0;
fp_output =fopen("out.txt","wb");
if (fp_output == NULL)
{
printf("\n Can't open file \n");
}
current = first;
while(current->next!=NULL)
{
fprintf(fp_output," %d \n",current->buffer_1D);
previous = current;
current = current->next;
free(previous);
}
fclose(fp_output);

由於malloc()是將記憶體放在head,而不是放在stack,所以並不會隨著function的結束而釋放,必須要手動使用free()釋放記憶體,
否則會造成memory leak

}


hsien0701
一般會員


發表:4
回覆:10
積分:2
註冊:2008-12-15

發送簡訊給我
#10 引用回覆 回覆 發表時間:2009-10-27 00:29:03 IP:114.43.xxx.xxx 訂閱
syntax大大晚安您好:

我反覆畫著圖,觀看您那四點指教
目前可以解決了只讀取ㄧ個.txt檔的問題了
提出三個疑問,懇請您再次賜教^^

1.
我主程式有達到您第ㄧ點地建議嗎??
2.
假如我是想"ㄧ次讀取完畢,ㄧ次顯示,然後ㄧ次釋放"
我這樣編排有錯嗎??
或是我這樣編排方式是屬於哪ㄧ種呢??
3.
我輸出的部份 時在是不知道問題出在哪
無法輸出 可以請您在輸出的部份稍作提是嗎??

感謝您這幾天的指導,原本自己畫的流程圖自己也看不太懂
現在有進步了...非常感激您!!

程式碼如下 請您過目 :

Node *current;
Node *previous=NULL;
Node *first=NULL;

unsigned char *output;
int main(void)
{
int i=0,j=0,n=0;
char InName[40] ="fin000.txt";

for(Data_num=1;Data_num<=4; Data_num )
{
sprintf(InName,"fin00%d.txt",Data_num);
current = (Node*)malloc(sizeof(Node*));
if(current!=NULL)
{
current->next=NULL;
Read (InName);
if (first == NULL)
{
first= current;
}
else
{
previous->next = current;
}
previous = current;
//printf("%d %d \n",Data_num,previous ->buffer_1D[1]);
//system("pause");
}
else
{
//printf("over\n");
//system("pause");
exit(0);
}
}
write();
free(previous);
return 0;
}

void Read ( char file_name[40])
{
int i=0,j=0,n;
unsigned char in0;

FILE *fp_input;
fp_input = fopen(file_name,"rb");
if(fp_input == NULL)
{
printf( "\n Can't open file %s",file_name);
system("pause");
exit(0);
}
n=1;
while ((fscanf(fp_input, "%d\n",&in0))!=EOF)
{
current->buffer_1D[n]=in0;
n ;
if(n>size)
{
break;
}
}
fclose(fp_input);
}


void write()
{
FILE *fp_output;
int i=0,j=0,n=0;
fp_output =fopen("out.txt","wb");
if (fp_output == NULL)
{
printf("\n Can't open file \n");
}
current = first;
while(current->next!=NULL)
{
fprintf(fp_output," %d \n",current->buffer_1D);
//previous=current;
current = current->next;
}
fclose(fp_output);
}

syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#11 引用回覆 回覆 發表時間:2009-10-29 08:06:32 IP:59.125.xxx.xxx 訂閱
1. 基本上就是這樣
2. ㄧ次讀取完畢,ㄧ次顯示,然後只有釋放了 previous
一次釋放全部,跟一次列印全部訊息,可用一樣的邏輯,列印處改成將下一個指標先記錄,才釋放 (如此應該會多用一個暫時記錄參數)
3.你知道 fprintf(fp_output," %d \n",current->buffer_1D); 這一行這樣寫的輸出結果嗎?


===================引 用 hsien0701 文 章===================
syntax大大晚安您好:

我反覆畫著圖,觀看您那四點指教
目前可以解決了只讀取ㄧ個.txt檔的問題了
提出三個疑問,懇請您再次賜教^^

1.
我主程式有達到您第ㄧ點地建議嗎??
2.
假如我是想"ㄧ次讀取完畢,ㄧ次顯示,然後ㄧ次釋放"
我這樣編排有錯嗎??
或是我這樣編排方式是屬於哪ㄧ種呢??
3.
我輸出的部份 時在是不知道問題出在哪
無法輸出 可以請您在輸出的部份稍作提是嗎??

感謝您這幾天的指導,原本自己畫的流程圖自己也看不太懂
現在有進步了...非常感激您!!

程式碼如下 請您過目 :

Node *current;
Node *previous=NULL;
Node *first=NULL;

unsigned char *output;
int main(void)
{
int i=0,j=0,n=0;
char InName[40] ="fin000.txt";

for(Data_num=1;Data_num<=4; Data_num )
{
sprintf(InName,"fin00%d.txt",Data_num);
current = (Node*)malloc(sizeof(Node*));
if(current!=NULL)
{
current->next=NULL;
Read (InName);
if (first == NULL)
{
first= current;
}
else
{
previous->next = current;
}
previous = current;
//printf("%d %d \n",Data_num,previous ->buffer_1D[1]);
//system("pause");
}
else
{
//printf("over\n");
//system("pause");
exit(0);
}
}
write();
free(previous);
return 0;
}

void Read ( char file_name[40])
{
int i=0,j=0,n;
unsigned char in0;

FILE *fp_input;
fp_input = fopen(file_name,"rb");
if(fp_input == NULL)
{
printf( "\n Can't open file %s",file_name);
system("pause");
exit(0);
}
n=1;
while ((fscanf(fp_input, "%d\n",&in0))!=EOF)
{
current->buffer_1D[n]=in0;
n ;
if(n>size)
{
break;
}
}
fclose(fp_input);
}


void write()
{
FILE *fp_output;
int i=0,j=0,n=0;
fp_output =fopen("out.txt","wb");
if (fp_output == NULL)
{
printf("\n Can't open file \n");
}
current = first;
while(current->next!=NULL)
{
fprintf(fp_output," %d \n",current->buffer_1D);
//previous=current;
current = current->next;
}
fclose(fp_output);
}

hsien0701
一般會員


發表:4
回覆:10
積分:2
註冊:2008-12-15

發送簡訊給我
#12 引用回覆 回覆 發表時間:2009-10-30 00:30:47 IP:114.43.xxx.xxx 訂閱
syntax大大您好:
感謝您的回答!!

3.你知道 fprintf(fp_output," %d \n",current->buffer_1D); 這一行這樣寫的輸出結果嗎?
回答:
這一行的顯示出來的數值,來由我不曉得..所以才不知道debug怎嚜下手

for(Data_num=1;Data_num<=4; Data_num )
{
sprintf(InName,"fin00%d.txt",Data_num);
current = (Node*)malloc(sizeof(Node*));
if(current!=NULL)
{
current->next=NULL;
Read (InName);
if (first == NULL)
{
first= current;
}
else
{
previous->next = current;
}
previous = current;
/*
printf("%d %d %d %d %d %d %d\n",Data_num,&first
,&previous,¤t
,first->buffer_1D[1],previous->buffer_1D[1],current->buffer_1D[1]);
system("pause");*/ }

不過再此處個人我覺得四個檔案資料是有循序進來

else
{
//printf("over\n");
//system("pause");
exit(0);
}
}
write();
free(previous);



1.還是我write位置放錯了 所以printf出來值怪怪的???
2.因為我想要 循序讀出來四個檔 最後一次輸出 我write跟free()的時機點也不對是嗎??

感謝您的教導^^
hsien0701
一般會員


發表:4
回覆:10
積分:2
註冊:2008-12-15

發送簡訊給我
#13 引用回覆 回覆 發表時間:2009-10-31 22:30:56 IP:114.43.xxx.xxx 訂閱
syntax大您好:

很報歉常常佔用您太多時間,
我有比較懂您的提示了,謝謝
目前可以循序讀取四個檔,最後全部輸出成一個檔

程式碼修改後如下:

#define size 160
void Read (char file_name[40]);
void write ();
int Data_num;

struct node
{
unsigned char buffer_1D[size];
struct node *next;
};
typedef struct node Node;

Node *current;
Node *previous=NULL;
Node *first=NULL;

int main(void)
{
int i=0,j=0,n=0;
char InName[40] ="fin000.txt";

for(Data_num=1;Data_num<=4; Data_num )
{
sprintf(InName,"fin00%d.txt",Data_num);
current = (Node*)malloc(sizeof(Node));

if(current!=NULL)
{
Read (InName);
if (first == NULL)
{
first= current;
}
else
{
previous->next = current;
current->next=NULL;
}
previous = current;
}
else
{
exit(0);
}


}
write();
free(previous);
return 0;
}

void Read ( char file_name[40])
{
int i=0,j=0,n;
unsigned char in0;

FILE *fp_input;
fp_input = fopen(file_name,"rb");
if(fp_input == NULL)
{
printf( "\n Can't open file %s",file_name);
system("pause");
exit(0);
}
n=1;
while ((fscanf(fp_input, "%d\n",&in0))!=EOF)
{
current->buffer_1D[n]=in0;
//printf("%d %d %d %d\n",Data_num,n,¤t,current->buffer_1D[n]);
//system("pause");
n ;
}
fclose(fp_input);
}


void write()
{
FILE *fp_output;
int i=0,j=0,n;
fp_output =fopen("out.txt","wb");
if (fp_output == NULL)
{
printf("\n Can't open file \n");
}
current = first;
while(current!=NULL)
{
for(n=1; n<=size; n )
{
fprintf(fp_output," %d \n",current->buffer_1D[n]);
if(n==size)
{
//printf("%d %d %d %d\n",Data_num,n,¤t,current->buffer_1D[size]);
//system("pause");
}
previous=current;
}
fprintf(fp_output,"\n");
current = current->next;
}
fclose(fp_output);
}



但是我發現在read()中
printf("%d %d %d %d\n",Data_num,n,¤t,current->buffer_1D[n]);
資料無誤的循序輸入

但是在write()中
printf("%d %d %d %d\n",Data_num,n,¤t,current->buffer_1D[size]);
也就是每個檔最後ㄧ筆資料 都是怪怪的數值,
當然每個檔前159筆資訊都是輸出正確的,唯讀最後ㄧ筆資訊輸出會有錯
而這些數值,是原始檔案裡頭根本沒有的,所以我也不清楚他為何產生的
第一個檔第160筆為48
第二個檔第160筆為96
第三個檔第160筆為144
第四個檔第160筆為0

請您讓我在這個主題做最後ㄧ次的發問好嗎??
拜託您了^^
系統時間:2017-10-18 22:40:14
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!