2013年12月17日火曜日

開発環境

C実践プログラミング 第3版 (Steve Oualline (著)、 望月 康司 (監訳) (翻訳)、谷口 功 (翻訳)、オライリー・ジャパン)のⅢ部(高度なプログラミング概念)の17章(高度なポインタ)、17-12(プログラミング実習)、実習17-1.を解いてみる。

その他参考書籍

17-12(プログラミング実習)、実習17-1.

コード

sample.c

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

struct node{
    char *word;
    int i;
    int linenos[100];
    struct node *left;
    struct node *right;
};

static struct node *root = NULL;
static int current_lineno = 1;

void memory_error(void)
{
    fprintf(stderr, "Error:Out of memory\n");
    exit (8);
}

void add_list(struct node *node, int n)
{
    node->linenos[node->i] = n;
    node->i = node->i + 1;
}

void print_lineno(struct node *node)
{
    int j;
    for(j = 0; j < node->i; j++){
        printf("%d ", node->linenos[j]);
    }
    printf("\n");
}

char *save_string(char *string)
{
    char *new_string;
    
    new_string = malloc((unsigned) (strlen(string) + 1));
    
    if (new_string == NULL){
        memory_error();
    }
    strcpy(new_string, string);
    return (new_string);
}

void enter(struct node **node, char *word)
{
    int result;
    char *save_string();
    void memory_error();
    void add_list(struct node *node, int n);
    if ((*node) == NULL){
        (*node) = malloc(sizeof(struct node));
        if ((*node) == NULL){
            memory_error();
        }
        (*node)->word = save_string(word);
        add_list((*node), current_lineno);
        (*node)->left = NULL;
        (*node)->right = NULL;
        return;
    }
    
    result = strcmp((*node)->word, word);
    
    if (result == 0){
        add_list((*node), current_lineno);
        return;
    }

    if (result < 0){
        enter(&(*node)->right, word);
    } else {
        enter(&(*node)->left, word);
    }
}

void scan(char *name)
{
    char word[100];
    int index;
    int ch;
    FILE *in_file;
    
    in_file = fopen(name, "r");
    if (in_file == NULL){
        fprintf(stderr, "Error:Unable to open %s\n", name);
        exit(8);
    }
    while (1){
        while(1){
            ch = fgetc(in_file);
            if (ch == '\n'){
                current_lineno++;
            }
            if(isalpha(ch) || (ch == EOF)){
                break;
            }
        }
        if (ch == EOF){
            break;
        }
        word[0] = ch;
        for (index = 1; index < sizeof(word); ++index){
            ch = fgetc(in_file);
            if (!isalpha(ch)){
                break;
            }
            word[index] = ch;
        }
        word[index] = '\0';
        enter(&root, word);
    }
    fclose(in_file);
}

void print_tree(struct node *top)
{
    if (top == NULL){
        return;
    }
    print_tree(top->left);
    printf("%-10s: ", top->word);
    print_lineno(top);
    print_tree(top->right);
}

int main(int argc, char *argv[])
{
    if(argc != 2){
        fprintf(stderr, "Error:Wrong numbr of parameters\n");
        fprintf(stderr, "      on the command line\n");
        fprintf(stderr, "Usage is:\n");
        fprintf(stderr, "    words 'file'\n");
        exit(8);
    }
    scan(argv[1]);
    printf("単語      : 行\n");
    print_tree(root);
    return (0);
}

makefile

CC=cc
CFLAGS=-g

sample: sample.c
 $(CC) $(CFLAGS) -o sample sample.c

clean:
 rm -f sample

入出力結果(Terminal)

$ make
cc -g -o sample sample.c
$ ./sample sample.c
単語      : 行
EOF       : 101 105 
Error     : 19 92 136 
FILE      : 88 
NULL      : 14 44 57 59 64 65 91 124 
Out       : 19 
Unable    : 92 
Usage     : 138 
Wrong     : 136 
add       : 23 56 63 72 
argc      : 133 135 
argv      : 133 142 
break     : 102 106 112 
ch        : 87 97 98 101 101 105 108 110 111 114 
char      : 7 38 38 40 51 54 83 85 133 
command   : 137 
ctype     : 2 
current   : 15 63 72 99 
d         : 33 
else      : 78 
enter     : 51 77 79 117 
error     : 17 45 55 60 
exit      : 20 93 140 
fclose    : 119 
fgetc     : 97 110 
file      : 88 90 91 97 110 119 139 
fopen     : 90 
for       : 32 109 
fprintf   : 19 92 136 137 138 139 
h         : 1 2 3 4 
i         : 8 25 26 26 32 
if        : 44 57 59 71 76 91 98 101 105 111 124 135 
in        : 88 90 91 97 110 119 
include   : 1 2 3 4 
index     : 86 109 109 109 114 116 
int       : 8 9 15 23 31 53 56 86 87 133 133 
is        : 138 
isalpha   : 101 111 
j         : 31 32 32 32 33 
left      : 10 64 79 127 
line      : 137 
lineno    : 15 29 63 72 99 129 
linenos   : 9 25 33 
list      : 23 56 63 72 
main      : 133 
malloc    : 42 58 
memory    : 17 19 45 55 60 
n         : 19 23 25 35 56 92 98 136 137 138 139 143 
name      : 83 90 92 
new       : 40 42 44 47 48 
node      : 6 10 11 14 23 23 25 25 26 26 29 29 32 33 51 51 56 56 57 58 58 59 62 63 64 65 69 72 77 79 122 
numbr     : 136 
of        : 19 136 
on        : 137 
open      : 92 
parameters: 136 
print     : 29 122 127 129 130 144 
printf    : 33 35 128 143 
r         : 90 
result    : 53 69 71 76 
return    : 48 66 73 125 145 
right     : 11 65 77 130 
root      : 14 117 144 
s         : 92 128 
save      : 38 54 62 
scan      : 83 142 
sizeof    : 58 109 
static    : 14 15 
stderr    : 19 92 136 137 138 139 
stdio     : 1 
stdlib    : 4 
strcmp    : 69 
strcpy    : 47 
string    : 3 38 38 40 42 42 44 47 47 48 54 62 
strlen    : 42 
struct    : 6 10 11 14 23 29 51 56 58 122 
the       : 137 
to        : 92 
top       : 122 124 127 128 129 130 
tree      : 122 127 130 144 
unsigned  : 42 
void      : 17 17 23 29 51 55 56 83 122 
while     : 95 96 
word      : 7 51 62 62 69 69 77 79 85 108 109 114 116 117 128 
words     : 139 
$

行数の格納にはリンクリストを使った方がいいけど、途中でポインタとかで頭がごちゃごちゃしてきたので、とりあえず通常の配列に格納。もっとポインタ、リンクリストに慣れたら配列をリンクリストに置き換えてみることに。

0 コメント:

コメントを投稿