Home > OS >  How to return a struct from a struct function?
How to return a struct from a struct function?

Time:12-29

//The Last attempt//


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

struct WordNode {
  char word;
  int line;
  struct WordNode* left;
  struct WordNode* right;
};

struct WordNode createNode(char word, int line) {
  struct WordNode* node=NULL;
  node =malloc(sizeof(struct WordNode));
  node->word = word;
  node->line = line;
  node->left = NULL;
  node->right = NULL;
  return node;
}

struct WordNode insert(struct WordNode* root, char word, int line) {
  if (root==NULL) {
    return createNode(word, line);
  }

  int cmp = strcmp(word, root->word);
  if (cmp == 0) {
    // word already exists in tree, so do nothing
    return root;
  } else if (cmp < 0) {
    root->left = insert(root->left, word, line);
  } else {
    root->right = insert(root->right, word, line);
  }

  return root;
}

int main(int argc, char argv[]) {
  if (argc != 2) {
    printf("Usage: %s <filename>\n", argv[0]);
    return 1;
  }

  char filename = argv[1];
  FILE *file = fopen("D:\TXTFolder\Text1.txt", "r");
  if (file == NULL) {
    perror("Error opening file");
    return 1;
  }

  struct WordNode *root = NULL;

  char line[256];
  int lineNumber = 1;
  while (fgets(line, sizeof(line), file)) {
    char word = strtok(line, " \n\t");
    while (word != NULL) {
      root = insert(root, word, lineNumber);
      word = strtok(NULL, " \n\t");
    }
    lineNumber  ;
  }

  fclose(file);

  return 0;
}

This is a program that reads a text file and stores unique words from that text file in a binary search tree in alphabetical order and this program also stores in that same binary search tree the index of lines in which those stored unique words were mentioned in C.

There seem to have errors in the two functions createNode() and insert() because they are both supposed to return a struct but it seems I can't.

CodePudding user response:

malloc(sizeof(struct WordNode)) allocates enough memory to store a struct WordNode and returns a pointer to that memory; the address of that memory. You assign that to a struct WordNode* (a pointer to a struct WordNode), and if you want to return that you need to return a pointer to a struct WordNode.

//              v returns a pointer
struct WordNode *createNode(char word, int line) {
  // malloc returns a pointer
  struct WordNode* node = malloc(sizeof(struct WordNode));

  node->word = word;
  node->line = line;
  node->left = NULL;
  node->right = NULL;

  // this is a pointer
  return node;
}

...and everywhere else you return a pointer to a WordNode.

You could return a copy of the struct Node...

struct WordNode createNode(char *word, int line) {
  struct WordNode* node=NULL;
  node =malloc(sizeof(struct WordNode));
  node->word = word;
  node->line = line;
  node->left = NULL;
  node->right = NULL;

  //     v dereferences the pointer so it refers to the actual memory
  return *node;
}

...but now you'd can't check things like node == NULL.

Get used to working with pointers.


Other issues are that your "word" is a single character, a char, but you're treating it as a string. Strings in C are a pointer to an array of characters, a char *.

struct WordNode {
  //   v pointer
  char *word;
  int line;
  struct WordNode* left;
  struct WordNode* right;
};

...and everywhere else you use word needs to be a char *word.

You also need to declare argv[] as an array of character pointers (strings).

//                      v array of strings
int main(int argc, char *argv[]) {

strtok does not copy the word, it simply points to the word in the original string. When you store the word returned from strtok, it is pointing to memory in line. line is overwritten each time you read a line, so the stored words will be overwritten.

You need to copy the word to new memory. Use strdup.

  // line's memory is overwritten each time fgets is called
  while (fgets(line, sizeof(line), file)) {
    // word points to memory in line
    char word = strtok(line, " \n\t");
    while (word != NULL) {
      //                  vvvvvvvvvvvv copy the word from line to new memory
      root = insert(root, strdup(word), lineNumber);
      // word points to memory in line
      word = strtok(NULL, " \n\t");
    }
    lineNumber  ;
  }

Backslashes in double-quoted strings indicate the following character has special meaning, like \n for a newline and \t for a tab. If you mean a literal backslash, use \\.

  FILE *file = fopen("D:\\TXTFolder\\Text1.txt", "r");

CodePudding user response:

to return a struct from a struct function?

Simply return the struct like code would return an int.

struct WordNode createNode(char word, int line) {
  //struct WordNode* node=NULL;
  //node =malloc(sizeof(struct WordNode));
  //node->word = word;
  //node->line = line;
  //node->left = NULL;
  //node->right = NULL;
  struct WordNode node = {.word = word, .line = line, .left = NULL, .roght = NULL};
  return node;
}

This is not a good idea though. Better to allocate memory and return a pointer to the struct WordNode.

Very few words can be saved in a char. A word like 'A', 'I', 'O' so far more likely the function should accept a pointer to characters (char *) and the createNode() would allocate a copy of that referenced string.

For my_strdup(), see this.

struct WordNode *createNode(const char *word, int line) {
  struct WordNode* node = malloc(sizeof node[0]);
  if (node) {
    node->word = my_strdup(word);
    node->line = line;
    node->left = NULL;
    node->right = NULL;
  }
  return node;
}
  • Related