1

I have written this code and i don't know why it has the following two problems:

1)It copys strings from the text file in to the Odd parts of the Array (ex:lines[3] or lines[5] )

2)It doesn't copy all the file but stops whenever it wants and crashes in the end.

Please help me with this and if someone can tell me how to copy a specific string from an text file in C it would be much appreciated !

C CODE :

#include <stdio.h>

int height, length;

int main()
{

  int i;
  char **lines;
  FILE *tfile = fopen("this.txt", "r");

  if (tfile != NULL )
  {
    fscanf(tfile, "%d %d", &height, &length);
    printf("here:%d,%d\n", height, length);
    /*dynamic equasition of memory with malloc*/
    lines = (char **) malloc(sizeof(char *) * (height + 1));/*height + 1 ('\0')*/
    for (i = 0; i < 2 * height; i++)
    {
      lines[i] = (char *) malloc(sizeof(char) * (length + length + 1));/*height + height ('|') + 1 ('\0')*/
    }

    for (i = 0; i < (2 * height); i++)
    {
      fgets(lines[i], ((2 * length) + 1 + 1), tfile);/*length='spaces' + length+1='|' + 1='\0'*/
      if (i % 2 != 0)
      {
        printf("%s\n", lines[i]);
      }
    }
    fclose(tfile);
  }
  else
  {
    printf("Error: unable to open file.");
  }

  free(lines);
  return 0;
}

TEXT FILE (this.txt) :

http://www.csd.uoc.gr/~hy100/glid.txt

Every answer is much appreciated. IT

5
  • 1
    You have undefined behavior in your code: You allocate height + 1 entries for the lines array (note: it doesn't have to be zero terminated, only the actual strings in the array need that), but then you loop to allocate 2 * height string in the array thereby overwriting your allocated memory with height - 1 entries. Commented Jan 18, 2014 at 11:53
  • 1
    Also, in C you should not cast the return of malloc. Commented Jan 18, 2014 at 11:54
  • There are also other cases of possible undefined behavior and buffer overflows. Commented Jan 18, 2014 at 11:55
  • 1
    Also, include <stdlib.h> for the prototypes of malloc and free. It's good that you clean up and free(lines), but you also have to free all lines[i] that you have allocated (before freeing lines). Commented Jan 18, 2014 at 11:58
  • what is your expected result? Commented Jan 18, 2014 at 13:11

2 Answers 2

1

Lets analyze your code:

#include <stdio.h>
// you did not include <stdlib.h> needed for malloc, so to suppress the compiler 
// warning you have casted the return value of malloc, which is not needed.

int height, length; // no need to make these global as of now.

int main()
{

  int i;
  char **lines;
  FILE *tfile = fopen("this.txt", "r");

  if (tfile != NULL )
  {
    fscanf(tfile, "%d %d", &height, &length);
    printf("here:%d,%d\n", height, length);
    /*dynamic equasition of memory with malloc*/
    lines = (char **) malloc(sizeof(char *) * (height + 1));/*height + 1 ('\0')*/
// you only need height in above line, not height+1,
// '\0' is needed for sting, this is an array of strings.
// also casting is not needed.
    for (i = 0; i < 2 * height; i++) // You have allocated height+1, but trying to access 2*height, this invokes undefined behavior.
    {
      lines[i] = (char *) malloc(sizeof(char) * (length + length + 1));/*height + height ('|') + 1 ('\0')*/
// after examining the text file you provided, I think you need length +length +2
// length number of ' ' + length number of '|' + one more '|' + '\0' 
    }

    for (i = 0; i < (2 * height); i++)
    {
      fgets(lines[i], ((2 * length) + 1 + 1), tfile);/*length='spaces' + length+1='|' + 1='\0'*/
// You have allocated length + length+ 1, i.e. 2*length+1, but reading 2*length+2
// this will invoke undefined behavior.
      if (i % 2 != 0)
// this will print the odd line, as i%2!=0 is true when i is odd,
// I think this is desirable as in your file even lines only have '\n'
      {
        printf("%s\n", lines[i]);
      }
    }
    fclose(tfile);
  }
  else
  {
    printf("Error: unable to open file.");
  }

  free(lines);
// This is not the proper way to free. You have to free in the same way you have allocated.
  return 0;
}

Here is my modification:

#include <stdio.h>
#include <stdlib.h> // for malloc

int main()
{

  int i;
  char **lines;
  int height, length; //local to main
  FILE *tfile = fopen("this.txt", "r");

  if (tfile != NULL )
  {
    fscanf(tfile, "%d %d", &height, &length);
    printf("here:%d,%d\n", height, length);
    /*dynamic equasition of memory with malloc*/
    lines = malloc(sizeof(char *) * (height)); // no need to cast the return value
    for (i = 0; i < height; i++)
    {
      lines[i] = malloc(sizeof(char) * (2*length + 2));/*height' '+height'|'+ 1'|'+1'\0'*/
    }

    for (i = 0; i < height; i++)
    {
      fgets(lines[i], 2*length+2, tfile);/*height' '+height'|'+ 1'|'+1'\0'*/
      if (i % 2 != 0)
      {
        printf("%s\n", lines[i]);
      }
    }
    fclose(tfile);
  }
  else
  {
    printf("Error: unable to open file.");
  }

    for (i = 0; i < height; i++)
    {
      free(lines[i]); // free all the strings
    }
  free(lines); // free the string array
  return 0;
}
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you very much for your answer.But the program with your modifications doesn't print the hole array.
No it does not. It prints the odd lines. If you want to print the whole file, then remove the if (i % 2 != 0) line
Thank you very much for your answer.But the program with your modifications doesn't print the hole array. oh and can you chek out this one : stackoverflow.com/questions/21206749/…
If you run it you will see it does not put anything in the even parts of the lines array. its blank .
read one less byte per line. I am sure, you can control the output by yourself now.
|
0
#include <stdio.h>

int main()
{
   FILE *fp = NULL;
   int line = 0, readLineStart = 0, readLineStop = 0, startIndex = 0, endIndex = 0;
   char buffer[512], *cPtr = NULL;

   fp = fopen("file.txt", "r");
   if(fp == NULL)
   {
      return -1;
   }

   readLineStart = 3;
   readLineStop = 6;
   startIndex = 2;
   endIndex = 9; //must startIndex < endIndex
   while(fgets(buffer, 512, fp) != NULL)
   {
      line++;
      if(line >= readLineStart && line <= readLineStop)
      {
         printf("Line:%s", buffer);
         cPtr = buffer;
         *(cPtr + endIndex) = '\0';
         printf("Get:%s\n", cPtr + startIndex);
      }
   }
   fclose(fp);
   return 0;
}

4 Comments

The OP needs a two dimensional char array, i.e, array of strings. Where are you storing all the lines? will not it be over written?
@Dipto, It's just an example, how to read portion of a line which read from file. He has to collect all (cPtr + startIndex) output in two dimensional array, if he want so.
then clarify that in your answer, Other wise, there is a chance to get down vote.
@Dipto, I have modified the answer. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.