Tomas
Tomas

Reputation: 31

Dynamic memory C

My task is to create program that reads all the words from file and puts into output file those words, that are identical from beginning to end (i mean aha, oho, asdsa, assa, etc). And task requires usage of dynamic memory (university), but I have been stuck in this place for days because I can't find why it doesn't want to do what I intend to do. I have 4 words in file. Those 4 printfs should print all words, but my program prints 3rd word, (null) and segmentation error. I use one-sided dynamic memory. Please explain why it doesn't work, because I can't do it myself. Thank you in advance! Code:

/*
 * Task: Write program, that finds all words from file which reads from beginning to end (lets call them mirror-type words)
 */

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

struct elements
{
        char str[255];
        struct elements *next;
};

/* Function checks if given word is mirror-type word */
int is_mirror(char str[255])
{
        int length = strlen(str);

        int to = (length % 2 == 1) ? (length - 1) / 2 : length / 2;

        int i = 0;
        while (i < to)
        {
                if (str[i] != str[length-i-1]) return 0;

                i++;
        }
        return 1;
};

int main()
{
        FILE *in;
        in = fopen("3_12.in", "r");
        if (in == NULL)
        {
                printf("Input file doesnt exist.\r\n");
                return 0;
        }

        char str[255];
        fscanf(in, "%s", str);

        struct elements *beginning, *element;

        element = (struct elements *) malloc(sizeof(struct elements));
        strcpy(element->str, str);

        beginning = element;

        do
        {
                fscanf(in, "%s", str);

                element->next = (struct elements *) malloc(sizeof(struct elements));
                strcpy(element->str, str);

                if (feof(in))
                {
                        element->next = NULL;
                        break;
                }
        }
        while(1);

        printf("%s\r\n", element->str);
        printf("%s\r\n", element->next->str);
        printf("%s\r\n", element->next->next->str);
        printf("%s\r\n", element->next->next->next->str);

        fclose(in);
}

Upvotes: 0

Views: 135

Answers (3)

BLUEPIXY
BLUEPIXY

Reputation: 40145

change

beginning = element;

do
{
        fscanf(in, "%s", str);

        element->next = (struct elements *) malloc(sizeof(struct elements));
        strcpy(element->str, str);

        if (feof(in))
        {
                element->next = NULL;
                break;
        }
}
while(1);

printf("%s\r\n", element->str);
printf("%s\r\n", element->next->str);
printf("%s\r\n", element->next->next->str);
printf("%s\r\n", element->next->next->next->str);

to

beginning = element;

while(EOF!=fscanf(in, "%s", str)){
    element->next = (struct elements *) malloc(sizeof(struct elements));
    element = element->next;
    strcpy(element->str, str);
}
element->next = NULL;

printf("%s\n", beginning->str);
printf("%s\n", beginning->next->str);
printf("%s\n", beginning->next->next->str);
printf("%s\n", beginning->next->next->next->str);

and add palindrome check.

Upvotes: 0

amura.cxg
amura.cxg

Reputation: 2427

Looking at your code it looks likes you missed a step in your loop. You never advance passed the second word because element is never updated.

Code Snippet

do
{
    fscanf(in, "%s", str); //Get the string

    element->next = (struct elements *) malloc(sizeof(struct elements)); //Create a new element at the end of the list

    element = element->next; //Move forward to the newly created element

    strcpy(element->str, str); //Copy the read string into the newly create element's `str`

    //If we've hit the end of the file, put a null at the end of the list and break
    if (feof(in))
    {
            element->next = NULL;
            break;
    }
}
while(1);

Check out this page it has some great information on linked lsits (which is what you're using).

Edit 1

I noticed an error with the original code I had written. Where str is set it was overwriting the original element's str value. The code would never create a list longer than 1 element and that one element would always have the last word in the file followed by a null.

Upvotes: 1

gsamaras
gsamaras

Reputation: 73366

Here is how it should be with two words to be read.

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

struct elements {
  char str[255];
  struct elements *next;
};

int main() {
  FILE *in;
  in = fopen("test.txt", "r");
  if (in == NULL) {
    printf("Input file doesnt exist.\r\n");
    return 0;
  }

  char str[255];
  fscanf(in, "%s", str);

  struct elements *beginning, *element;

  element = malloc(sizeof(struct elements));
  strcpy(element->str, str);
  element->next = NULL;

  beginning = element;

  do {
    fscanf(in, "%s", str);
    element = malloc(sizeof(struct elements));
    strcpy(element->str, str);
    element->next = NULL;

    beginning->next = element;

    if (feof(in)) {
      break;
    }
  } while (1);

  printf("%s\r\n", beginning->str);
  printf("%s\r\n", beginning->next->str);


  fclose(in);
  free(beginning->next);
  free(beginning);
}

The test.txt

aabb
sam

So, you are trying to build one linked list. I create in the above example one node, set the first word read to it element->str, and element->next to NULL.

Then I set the beginning to that node. Note that instead of beginning, people usually use head, since it's the first node of the list.

Then I do the same thing for the next word and I am inserting the new node as the second node of the list.


You see that you need to build a list, because this is getting big. I learnt how to do that through this code.


Do not cast what malloc() returns.

Upvotes: 0

Related Questions