0

I need to create 2 separate functions readLine() and readLines() in C. The first one has to return the pointer to the input string and the second one should return the array of pointers of input strings. readLines() is terminated with a new line character. I am getting some errors, probably something with memory, sometimes it works, sometimes it doesn't. Here is the code:

char* readLine() {
   char pom[1000];
   gets(pom);
   char* s = (char*)malloc(sizeof(char) * strlen(pom));
   strcpy(s, pom);

   return s;
}

And here is readLines()

char** readLines() {
   char** lines = (char**)malloc(sizeof(char*));
   int i = 0;
   do {
       char pom[1000];
       gets(pom);
       lines[i] = (char*)malloc(sizeof(char) * strlen(pom));
       strcpy(lines[i], pom);
       i++;
   } while (strlen(lines[i - 1]) != 0);

   return lines;
}

In the main, I call these functions as

char* p = readLine();
char** lines = readLines();
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • `"readLines() is terminated with a new line character"` -- What does this mean? Does it mean that the function `readLines` should continue reading until it finds an empty line? Or does it mean that the array returned by `readLines` should contain an empty string containing only a newline character, in order to mark the end of the array? Or does it mean both? – Andreas Wenzel May 17 '21 at 17:27
  • It means that it should continue reading until it finds an empty string. What is returned from the function is the array of strings in the input before the empty line. Thank you for the answer below, I'm gonna take a look real qucik. – Petar Vasiljevic May 17 '21 at 17:31
  • How is the function `main` supposed to know how many lines are returned by `readLines`? Is the function `readLines` supposed to mark the end of the array with a pointer containing the value `NULL`? – Andreas Wenzel May 17 '21 at 17:34
  • Can't we just iterate over lines and check if strlen(lines[i]) == 0. Then we know that it is the empty line? Considering that an empty line is in the array. – Petar Vasiljevic May 17 '21 at 17:38
  • Yes, that is possible. However, it is more common (and also more efficient) to mark the end of the array with a pointer containing the value `NULL`. – Andreas Wenzel May 17 '21 at 17:43
  • Yes, thank you. I still have some bugs, hopefully, I will fix them. – Petar Vasiljevic May 17 '21 at 17:48

1 Answers1

1

When allocating memory for a string using malloc, you should allocate enough memory for the entire string, including the terminating null character.

In your case, strcpy will cause a buffer overflow, because the destination buffer isn't large enough.

You should change the line

char* s = (char*)malloc(sizeof(char) * strlen(pom));

to

char* s = (char*)malloc( sizeof(char) * (strlen(pom)+1) );

and change the line

lines[i] = (char*)malloc(sizeof(char) * strlen(pom));

to

lines[i] = (char*)malloc( sizeof(char) * (strlen(pom)+1) );

Also, the line

char** lines = (char**)malloc(sizeof(char*));

is wrong, as it only allocates enough memory for a single pointer. You need one pointer per line. Unfortunately, you don't know in advance how many lines there will be, so you also don't know how many pointers you will need. However, you can resize the buffer as required, by using the function realloc.

Although it is unrelated to your problem, it is worth noting that the function gets has been removed from the ISO C standard and should no longer be used. It is recommended to use fgets instead. See this question for further information: Why is the gets function so dangerous that it should not be used?

Also, in C, it is not necessary to cast the return value of malloc. This is only necessary in C++. See this question for further information: Do I cast the result of malloc?

In your code, you first increment i using the statement i++; and then you reconstruct the previous value of i by subtracting 1:

while (strlen(lines[i - 1]) != 0);

This is unnecessarily cumbersome. It would be better to write

while (strlen(lines[i++]) != 0);

and remove the line i++;. That way, you no longer have to subtract by 1.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39