0

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);
}
Tomas
  • 31
  • 1
  • 8
  • 2
    Show an exemple of input and desired output. – Jabberwocky Nov 20 '14 at 15:10
  • never cast the result of malloc() – Peter Miehle Nov 20 '14 at 15:13
  • @MichaelWalz There is no outputting part yet, because I can't get whole information into dynamic array. – Tomas Nov 20 '14 at 15:15
  • You mean a palindrome? –  Nov 20 '14 at 15:16
  • @Pickle Yeah, palindromes. Didn't knew the word. But palindrome-part is not the problem. Dynamic array is. – Tomas Nov 20 '14 at 15:17
  • still not sure, where the problem is: is it a crash or is it presenting wrong output? – Peter Miehle Nov 20 '14 at 15:17
  • @PeterMiehle I currently have 4 words (what are they doesn't matter), last 4 printfs print 3rd word, (null) and segmentation error while I want them to print all 4 words that are in file. – Tomas Nov 20 '14 at 15:27
  • `printf("%s\r\n", element->str);`... `element` replace with `beginning` – BLUEPIXY Nov 20 '14 at 15:29
  • 1
    It looks like your while loop never moves passed the second elements. Correct me if I'm wrong but at some point shouldn't you say `element = element->next` ? – amura.cxg Nov 20 '14 at 15:29
  • @amura.cxg i am allocating memory directly to element->next (I could be wrong although, thats my first time with dynamic memory) – Tomas Nov 20 '14 at 15:37
  • @TomasČerkauskas that's correct, you are but after the first loop, `element` is still pointing to the struct you created outside the loop. So each iteration of the loop is overwriting the second `element->next` in the list. I may be wrong, but does the second `printf` print out the last word in the file? – amura.cxg Nov 20 '14 at 15:40
  • @TomasČerkauskas : In the meantime I understood what you want by reading the other comments. – Jabberwocky Nov 20 '14 at 16:50

3 Answers3

1

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.

amura.cxg
  • 2,348
  • 3
  • 21
  • 44
0

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.

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
0

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.

BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70