• ベストアンサー
  • すぐに回答を!

C言語解読

  • 質問No.3656859
  • 閲覧数342
  • ありがとう数1
  • 気になる数0
  • 回答数2
  • コメント数0

お礼率 33% (3/9)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define dBufferSize (32768)
#define dPrintFmt "#d: %s\n"

typedef struct _NODE NODE;
struct _NODE {
char *line;
NODE *next;
};

int RemoveReturnCode(char *string);
NODE *MakeNode(char *string);
int FreeNodeList(NODE *node);
void FreeNode(NODE *node);
int PrintNoceList(NODE *node);
NODE *ReverseNodeList(NODE **head);

int main(void){
char buffer[dBufferSize];
NODE *head = NULL;

while (fgets(buffer, dBufferSize, stdin) != NULL){
NODE *pivot;

RemoveReturnCode(buffer);
pivot = MakeNode(buffer);
if (pivot == NULL) return FreeNodeList(head);
pivot->next = head;
head =pivot;
}
PrintNodeList(head);
ReverseNodelist(&head);
PrintNodeList(head);
FreeNodeList(head);

return 0;
}

int RemoveReturnCode(char *str){
char *p;

if (str == NULL) return -1;
for (p = str; *p != '\n' && *p != '\r' && *p != '\0'; p++)
;
*p = '\0';

return p - str;
}

NODE *MakeNode(char *str){
NODE *node;

if(str == NULL)return NULL;

node = (NODE *)calloc(1,sizeof(NODE));
if(node != NULL){
char *p = (char *)calloc(strlen(str)+1, sizeof(char));

if (p != NULL){
node->line = strcpy(p, str);
node->next = NULL;
}
else{
free(node);
node = NULL;
}
}

return node;
}

int FreeNodeList(NODE *node){
int ct = 0;

while (node != NULL){
NODE *next = node->next;

FreeNode(node);
ct++;
node = next;
}

return ct;
}

void FreeNode(NODE *node){
free(node->line);
free(node);
}

int PrintNodeList(NODE *node){
int ct;

for (ct = 0; node != NULL; node = node->next, ct++)
printf(dPrintFmt, ct+1, node->line);

return ct;
}

NODE *ReverseNodeList(NODE **head){
NODE *reverse = NULL;
NODE *node = *head;

while (node != NULL){
NODE *next = node->next;

node->next = reverse;
reverse = node;
node = next;
}

return *head = reverse;
}



このプログラムは単方向リストを利用して複数行のデータを格納していくものであるという
ものらしいのですが、そのようなヒントがあっても、まったく解読できません、
手も足も出ない状態です。

できれば、初心者に近い私にもわかるように、関数ごとの解説をおねがいします!!

エラーがでるかもしれないのですが・・・大体の意味にはかわりないと思いますので、宜しくお願いします!!

質問者が選んだベストアンサー

  • 回答No.2
  • ベストアンサー
コメントで解説を加えておきました。
基本的なアルゴリズムですので、構造は難しくないと思います。
一度ご自分でリストを作成するプログラムを記述することをお勧めします。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define dBufferSize (32768) // 1行分の文字列を保持するためのバッファのサイズ
#define dPrintFmt "%d: %s\n" // 文字列を表示する際の書式

// 連結リストを実現するための構造体
// NODE構造体をつなげてリストを作成する
typedef struct _NODE NODE;
struct _NODE {
char *line; // 文字列へのポインタ
NODE *next; // 次のNODEへのポインタ
};

int RemoveReturnCode(char *string);
NODE *MakeNode(char *string);
int FreeNodeList(NODE *node);
void FreeNode(NODE *node);
int PrintNodeList(NODE *node);
NODE *ReverseNodeList(NODE **head);

int main(void){
char buffer[dBufferSize]; // 1行分の文字列を保持するバッファ
NODE *head = NULL;

// 標準入力から1行毎に文字列を読み取り、連結リストに格納
while (fgets(buffer, dBufferSize, stdin) != NULL){
NODE *pivot;

RemoveReturnCode(buffer); // 文字列末尾の改行コードを削除
pivot = MakeNode(buffer); // 新規NODE作成
if (pivot == NULL) return FreeNodeList(head); // NODE作成に失敗した場合は、リストを削除して終了
// 作成したNODEをリスト先頭に挿入
pivot->next = head;
head = pivot;
}
PrintNodeList(head); // リストを表示
ReverseNodeList(&head); // リストを逆転
PrintNodeList(head); // リストを表示
FreeNodeList(head); // リストを削除

return 0;
}

/*
文字列末尾の改行コードを削除
@param str 文字列
@return 文字列長
*/
int RemoveReturnCode(char *str){
char *p;

if (str == NULL) return -1;
for (p = str; *p != '\n' && *p != '\r' && *p != '\0'; p++)
;
*p = '\0';

return p - str;
}

/*
新規に文字列を保持するNODE作成
@param str 文字列
@return 作成したNODE(作成失敗の場合NULL)
*/
NODE *MakeNode(char *str){
NODE *node = NULL;

if(str == NULL)return NULL;

node = (NODE *)calloc(1,sizeof(NODE));
if(node != NULL)
{
// node領域確保成功
char *p = (char *)calloc(strlen(str)+1, sizeof(char)); // 文字列を保持する領域を確保
if (p != NULL)
{
// p領域確保成功
node->line = strcpy(p, str); // 文字列をコピー
node->next = NULL;
}
else
{
// p領域確保失敗
free(node);
node = NULL;
}
}
else
{
// node領域確保失敗
node = NULL;
}
return node;
}

/*
連結リストを削除
@param node 先頭のNODE
@return 削除したNODEの数
*/
int FreeNodeList(NODE *node){
int ct = 0;

while (node != NULL){
NODE *next = node->next;
FreeNode(node);
ct++;
node = next;
}

return ct;
}

/*
単一のNODEを削除
@param node 削除するNODE
*/
void FreeNode(NODE *node){
free(node->line);
free(node);
}

/*
連結リストが保持する文字列を1行毎に表示
@param node 先頭のNODE
@return 表示した行数
*/
int PrintNodeList(NODE *node){
int ct;

for (ct = 0; node != NULL; node = node->next, ct++)
printf(dPrintFmt, ct+1, node->line);

return ct;
}

/*
連結リストを逆転
@param head 先頭のNODEへのダブルポインタ
*/
NODE *ReverseNodeList(NODE **head){
NODE *reverse = NULL;
NODE *node = *head;

while (node != NULL){
NODE *next = node->next;

node->next = reverse;
reverse = node;
node = next;
}

return *head = reverse;
}
お礼コメント
32i

お礼率 33% (3/9)

お礼遅くなってごめんなさい。
C言語にCASL、とプログラミングに翻弄された
日々がいったん落ち着くまで時間がかかりました。

そういってる間に試験が近づいています。。
また、回答者様にはくだらない問題かもしれませんが、
気が向けば、手助けをお願いいたします。

ありがとうございました。
投稿日時:2008/01/12 20:58

その他の回答 (全1件)

  • 回答No.1

ベストアンサー率 22% (50/220)

 
 向こうの人に失礼なことはやめましょう。

 初心者なら、解るようになるまで勉強しましょう。
いきなり二階へ飛び上がるのは無理です。
ちゃんと階段を一段づつ上がりましょう。
 

 
結果を報告する
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。
関連するQ&A

その他の関連するQ&Aをキーワードで探す

ピックアップ

ページ先頭へ