将二叉树打印到用户提供的文件

时间:2017-02-21 19:25:58

标签: c binary-tree

我正在编写一个程序,该程序应该从文件中获取文本并按字母顺序排列所有单词,并在每个单词旁边写入它出现的行。我将所有内容打印到另一个文件时遇到问题。我将结果打印到控制台,但不知道如何将其打印到文件中。有人可以帮忙吗? 这是我的代码

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

void help() {
    printf("This program counts symbols and words in each line. \n"
           " You have to write a name of the program, -i and input name, \n"
           " and -o and output name, remember to put .txt after \n"
           " input and output name and .exe after program name. \n "); // TODO
}

int CommandConsole(int argc, char *argv[], char limiter[]) {
    int i;

    for (i = 1; i < argc; i++) {
        if (argv[i][0] == limiter[0] && argv[i][1] == limiter[1]) { //strcmp
            break;
        }
    }
    return i + 1;
}

typedef struct lineNode {
    int line;
    struct lineNode *right;
} lineNode_t;

typedef struct node {
    char *word;
    lineNode_t *lineNodeHead;
    struct node *left, *right;
} node_t;

lineNode_t *insertLineCount(lineNode_t *line, int lineCount) {
    if (line == NULL) {
        if ((line = (lineNode_t *)malloc(sizeof(lineNode_t))) != NULL) {
            line->right = NULL;
            line->line = lineCount;
        }
    } else {
        line->right = insertLineCount(line->right, lineCount);
    }
    return line;
}

node_t *inserttree(node_t *tree, char *currentWord, int lineCount) {
    if (tree == NULL) {
        if ((tree = (struct node *)malloc(sizeof(struct node))) != NULL) {
            tree->left = NULL;
            tree->right = NULL;
            strcpy(tree->word, currentWord);
            tree->lineNodeHead = insertLineCount(NULL, lineCount);
        }
    } else
    if (strcmp(tree->word, currentWord) > 0) {
        tree->left = inserttree(tree->left, currentWord, lineCount);
    } else
    if (strcmp(tree->word, currentWord) < 0) {
        tree->right = inserttree(tree->right, currentWord, lineCount);
    } else {
        tree->lineNodeHead = insertLineCount(tree->lineNodeHead, lineCount);
    }

    return tree;
}

void freetree(struct node *tree) {
    if (tree != NULL) {
        free(tree->word);
        freetree(tree->left);
        freetree(tree->right);
        free(tree);
    }
}

void printLineCount(lineNode_t *line, FILE *fileout) {
    while (line != NULL) {
        printf("%d, ", line->line);
        line = line->right;
    }
    printf("\n\n");
}

void printtree(struct node *tree, FILE *fileout) {
    if (tree != NULL) {
        printtree(tree->left, fileout);
        printf("%s found in:\n", tree->word);
        printLineCount(tree->lineNodeHead, fileout);
        printtree(tree->right, fileout);
    }
}

void freeTreeLine(struct node *tree) {
    while (tree->lineNodeHead != NULL) {
        struct node *aux = tree->lineNodeHead;
        tree->lineNodeHead = tree->lineNodeHead->right;
        free(aux);
    }
}

void freeTree(struct node *tree) {
    if (tree->left != NULL) {
        freetree(tree->left);
    }
    if (tree->right != NULL) {
        freetree(tree->right);
    }
    freeTreeLine(tree);
    free(tree->word);
    free(tree);
}

int main(int argc, char *argv[]) {
    struct node *tree = NULL;
    int letter = '\0';
    char word[100];
    int i = 0;
    int lineCount = 0;

    if (argc == 5) {
        FILE *filein = fopen(argv[CommandConsole(argc, argv, "-i")], "r");
        FILE *fileout = fopen(argv[CommandConsole(argc, argv, "-o")], "w");
        if (filein != NULL) {
            while ((letter = fgetc(filein)) != EOF && i < 99) {
                if (isalnum(letter) == 1 || letter == 39) {
                    word[i] = letter;
                    word[++i] = '\0';
                } else {
                    if (letter == '\n') {// new line
                        lineCount++;
                    }
                    tree = inserttree(tree, word, lineCount);
                    for (int j = 0; j < i; j++) {
                        //fputc(word[j], fileout);
                        word[j] = ' ';
                    }
                    i = 0;
                }
            }
            //            printtree(tree,fileout);
            fclose(filein);
            fclose(fileout);
        } else {
            printf("File error!\n");
        }
    } else {
        help();
    }
    return 0;
}

2 个答案:

答案 0 :(得分:0)

您应该在树形打印功能中使用printf,而不是使用fprintf

void printLineCount(lineNode_t *line, FILE *fileout) {
    while (line != NULL) {
        fprintf(fileout, "%d, ", line->line);
        line = line->right;
    }
    fprintf(fileout, "\n\n");
}

void printtree(struct node *tree, FILE *fileout) {
    if (tree != NULL) {
        printtree(tree->left, fileout);
        fprintf(fileout, "%s found in:\n", tree->word);
        printLineCount(tree->lineNodeHead, fileout);
        printtree(tree->right, fileout);
    }
}

此外,fprintf(fileout, "%s found in:\n", tree->word);只应在tree->lineNodeHeadNULL的情况下执行。

另请注意:

  • isalnum(letter) == 1不正确。 isalnum()<ctype.h>中的其他字符类函数如果参数不是字母或数字则返回0,如果参数不是非零。不要比较== 1,只需撰写isalnum(letter)

  • 你有2个函数:freeTree()释放行号,freetree()释放行号。前者称之为后者。这是不正确的,因为行号不会被释放到第一级以下。

  • 不要对39等ASCII值进行硬编码,而是使用字符常量'\''

答案 1 :(得分:0)

Finished code with some lovely comments in Polish!

    #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "tree.h"
void help()
{
    printf("This program shows You words in alphabetical order as well as in which lines they occur. \n You have to write a name of the program, -i and input name, \n and -o and output name, remember to put .txt after \n input and output name and .exe after program name. \n "); // TODO
}
int CommandConsole(int argc, char *argv[], char limiter[])
{
    int i;
    for (i = 1; i < argc; i++) {//przeleć wszystkie argumenty
        if (argv[i][0] == limiter[0] && argv[i][1] == limiter[1]) //strcmp
        {
            break;
        }
    }
    return i + 1;
}



typedef struct lineNode//lista z numerami kolejnych linii koljnego wyrazu (tego samego)
{
    int line;//numer tej lini
    struct lineNode *right;//wskaźnik na następny numer
}lineNode_t;

typedef struct node//jedno dżewo
{
    char *word;//jakie slowo
    lineNode_t *lineNodeHead;//wskaznik na liste z numerami kolejnych linii wyrazu tego slowa u gory
    struct node *left, *right;//wskaznik na lewo i prawo w dżewie
}node_t;

lineNode_t *insertLineCount(lineNode_t *line, int lineCount) {//a dopierdol mu kolejną linie do listy linii

    if (line != NULL) {//jeśli linia nie jest nullem to dopiero wtedy możesz się dostać do pola, wartości, czy jak chuj chcesz to nazywać struktury (w node to jest word, lineNodeHead, left i right
        if (line->right == NULL)//sprawdzasz czy następna strzałka prowadzi do czegoś konkretnego czy nie ma następnej wartości
        {
            line->right = (lineNode_t *)malloc(sizeof(lineNode_t));//zaalokuj pamięć na kolejny element listy
            //żeby nam nie wyjebało błędu to dwie linijki niżej
            line->right->right = NULL;//musimy mu powiedzieć, że następny na nic nie wskazuje
            line->right->line = lineCount;//musimy do nastepnego wpisać to linie o którą się tutaj rozchodzi

        }
        else {//następna strzałka prowadzi na coś, czyyyyyli...
            line->right = insertLineCount(line->right, lineCount);//czyyyli sprawdzamy następna szczałke
        }
    }
    else {//żadnej struktury ni ma, czyli ja tworzymy (Albo jak znajduje słowo po raz pierwszy, albo jak doszedł (hehe) do końca listy i musi dodać kolejńa linie w której jest słowo
        line = (lineNode_t *)malloc(sizeof(lineNode_t));
        line->right = NULL;//to masz opisane troche wyżej
        line->line = lineCount;
    }
    return line;//zwracamy wartość żeby ten poprzedni z rekurencji wiedział o co cho
}

node_t *inserttree(node_t *tree, char *currentWord, int lineCount)
{
    if (tree == NULL)//jeżeli dżewo nie istnieje LUB doszliśmy w rekurencji do końca dżewa (znaleźliśmy miejsce dla naszego słowa)
    {
        tree = (struct node *) malloc(sizeof(struct node)); //alokujemy pamięć na to to

        tree->left = NULL;//skoro dopiero tworzymy, to on nic pod sobą ni ma
        tree->right = NULL;
        tree->word = malloc(sizeof(char)*(strlen(currentWord) + 1)); //alokujemy pamięć na słowo
        strcpy(tree->word, currentWord);//kopiujemy słowo z naszej tablicy na wskaźnik który przed chwilą zaalokowaliśmy
        tree->lineNodeHead = insertLineCount(NULL, lineCount); //trzeba przelecieć (ehehehehe) liste linii i wrzucić tam nową linie

    }
    else if (strcmp(tree->word, currentWord) > 0) {//tree->word byłoby przed currentWord w słowniku
        tree->left = inserttree(tree->left, currentWord, lineCount);//czyli lecimy w lewo()
    }
    else if (strcmp(tree->word, currentWord) < 0) {//tree->word byłoby po currentWord w słowniku
        tree->right = inserttree(tree->right, currentWord, lineCount);//czyli lecimy w prawo
    }
    else {//Doszliśmy (hehe) do momentu w którym nie może iść ani w lewo ani w prawo, bo słowa są te same !!!!!!!!!!!!1!1!!11!1111!!!1jedenjedenjedenascie
        tree->lineNodeHead = insertLineCount(tree->lineNodeHead, lineCount);
    }

    return tree;//przypisaliśmy odpowiednie wartości no to caller musi wiedzieć co on ma sobie przypisać
}
//DRUKUJEMY KURWAAAAAAAAAAAAA!!!!!!!!!!!!!!!!!!!!!!!!
void printLineCount(lineNode_t *line, FILE *fileout) {

    while (line != NULL) {//przeleć (ehehehehe) całą liste linii żeby ją wypisać

        fprintf(fileout, "%d, ", line->line); //a se wypisze

        line = line->right; //next please
    }
    fprintf(fileout, "\n\n");//a se entery wpisze żeby ładnie wyglądało
}

void printtree(struct node *tree, FILE *fileout)//Wydrukuj mi dżewo ziomek
{

    if (tree != NULL)//przeleć (hehe (to już się robi nudne)) wszystkie elementy w dżewie
    {
        printtree(tree->left, fileout);//wydrukuj mi kurwa to co mam z lewej najpierw ziomek (alfabet, pamiętasz?)
        fprintf(fileout, "%s found in:\n", tree->word);//O, wypisujemy teraz alfabetycznie
        printLineCount(tree->lineNodeHead, fileout);//A teraz ile razy się powtara
        printtree(tree->right, fileout);//No a teraz lecimy w prawo
    }
}


void freeTreeLine(struct node *tree) {//zwalniamy kurwa linie
    while (tree->lineNodeHead != NULL) {//masowe zwolnienia
        lineNode_t *aux = tree->lineNodeHead;   //zastępczy żebyśmy nie zgubili
        tree->lineNodeHead = tree->lineNodeHead->right;//NASTĘPNY KURWA
        free(aux);//zwolnij ten cośmy go nie zgublii bo tacy mądrzy my som
    }
}

void freeTree(struct node *tree)//ZWALNIAMY KURWA DŻEWA
{
    if (tree->left != NULL) {//Jeżeli już pod naszą lewą gałęzią nic nie ma...
        freeTree(tree->left);
    }
    if (tree->right != NULL) {//...Jeżeli już pod naszą prawą gałęzią nic nie ma...
        freeTree(tree->right);
    }
    freeTreeLine(tree);//...To możemy sami siebie zwolnić (żeby ci nad nami mogli siebie zwolnić)
    free(tree->word);
    free(tree);
}


int main(int argc, char * argv[]) {
    struct node *tree = NULL;
    char letter = '\0';
    char word[100];//deklaracje no to wyjebane w sumie
    int i = 0;
    int lineCount = 1;
    if (argc == 5) {
        FILE *filein = fopen(argv[CommandConsole(argc, argv, "-i")], "r");//otwieranie plików to wyjebane
        FILE *fileout = fopen(argv[CommandConsole(argc, argv, "-o")], "w");
        if (filein != NULL) {//jeśli istnieje nasz plik wejścia
            while ((letter = fgetc(filein)) != EOF && i < 99)//pobierz z pliku znak i sprawdź czy to nie koniec pliku albo czy słowo nie jest za długie
            {
                if (letter > 0 && letter < 256) {//jakieś błędy pliku? wyskakiwało letter = -30 i co wtedy masz zrobić? potnij się.
                    if (isalnum(letter) != 0) {//jeśli nasz znak to literka albo apostrof
                        word[i] = letter;//dodaj następny znak do naszego słowa
                        word[++i] = '\0';//NAJPIERW DODAJ JEDEN DO i, a później wpisz do tablicy '\0' (i++ by robiło na odwrót)
                    }
                    else {//jeśli nasze słowo się skończyło
                        if (letter == '\n') {// new line
                            lineCount++;
                        }
                        tree = inserttree(tree, word, lineCount);//wsadź (hehe) je w drzewo
                        i = 0;//resetujemy długość słowa
                    }
                }
            }//ok skońcyzliśmy wypełniać drzewo (lol)
            if (tree != NULL) {//jeśli wgl je stworzyliśmy (bo może być pszypał i plik się otworzy ale jest pusty)
                if (fileout != NULL) //jeśli nasz plik wyjściowy istnieje
                    printtree(tree, fileout);//wypisz

                freeTree(tree);//no i zwolnij niezależnie cyz istnieje czyn nie
            }

            fclose(filein);//zamykamy pliki
            fclose(fileout);
        }
        else {
            printf("File error!\n");
        }
    }
    else
    {
        help();

    }

    return 0;
}