0

I started learning programming with Python a couple months ago, and I decided to learn C because I am interested in lower level languages that let me interact closer to the computers hardware. I'm trying to get some input from a user in C, and I am writing my own little input parser. I'm having some trouble here:

#include <stdio.h>

char prompt()
{
  char resp[]; // Create a variable for the users response

  for (int i = 0; i < 1000; ++i)
  {
    char letter = getchar(); // Get character
    if (letter == '\n') // If the user hits enter break the loop
    {
      break;
    }
    else  // Otherwise append the character to the response array
    {
      resp[i] = letter;
    }
  }

  return resp[];  // Return the response array
}

int main() {
  return 0;
}

I'm receiving errors with this code. The errors specifically say:

error:    definition of variable with array type needs an explicit size or an initializer
      char resp[];

I take it that I must define a set value for an array or assign it something right away. I don't understand how I can grow the character array as the user types the input if arrays in C must have a defined value. I am thinking that using pointers or memory management might work, but I haven't learned a lot about these things yet so if you do have a solution involving pointers, it would be of great help to me if you could briefly explain what the code is doing. In the meantime I will try and find a solution.

coder guy
  • 531
  • 1
  • 3
  • 12
  • 1
    you declared as **response[]** but used in code **resp[]**. – Mukit09 Oct 28 '15 at 02:33
  • 5
    You cannot grow the array as the user types. Arrays have a fixed size in C. Also you cannot return an array. I'd suggest starting with an introductory book, [here is a list](http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list). "The C Programming Language" (2nd. ed.) starts off with tasks similar to what you are doing. – M.M Oct 28 '15 at 02:33
  • To grow the memory as needed, you'll need to understand pointers and dynamic memory allocation (`malloc()` et al). For the time being, define a big enough array in the `main()` function: `char response[1000];`, and pass that array and its size to the function `prompt(response, sizeof(response))`, and accept those parameters in the function: `void prompt(char response[], int size)` and make sure you (a) do not go beyond the end of the array and (b) null terminate the string. Then you can print out what was read in the main program: `printf("You said: %s\n", response);` before exiting. – Jonathan Leffler Oct 28 '15 at 02:41
  • @Mukit Chowdhury Thanks. Edited that. – coder guy Oct 28 '15 at 02:42
  • @Jonathan Leffler I just defined a buffer argument for the function, and then when I create the array within the function, I set the size of the array to the buffer value. Then I made sure the for loop breaks if i <= buff. Do you think that will do the trick for now? – coder guy Oct 28 '15 at 02:46
  • You don't create the buffer in the function; that's the whole point of passing it into the function. That way, you don't run into problems with returning a variable that is no longer in scope, etc. You also allocate a size that is big enough for the largest input you're willing to process (1000 is a good size for that). And you check that the loop goes `int i; for (i = 0; i < size - 1; i++)` and you add `response[i] = '\0';` after the loop — which means you have to define `i` outside the `for` statement so you can use the value after the loop. Also remember to check for EOF before newline. – Jonathan Leffler Oct 28 '15 at 02:50

2 Answers2

1

There isn't a dynamic runtime in C. You need to explicitly allocate resources because your code essentially translates directly into machine instructions.

Here's an example.

#include <stddef.h>
#include <stdlib.h>

#include <stdio.h>

int prompt(const size_t bufsize, char response[bufsize]) {

  if (fgets(response, bufsize, stdin) == NULL)
    return -1; // error

  return 0;
}

int main() {

  const size_t bufsize = 1024;
  char* response = malloc(bufsize); // Create a variable for the users response

  if (!response)
    return -1; // error

  if (prompt(bufsize, response))
    return -1; // error

  printf("%s", response);

  free(response);

  return 0;
}
Jason
  • 3,777
  • 14
  • 27
  • You need `` and not ``. Your call to `prompt()` is erroneous too — type passed and address passed. Using `fgets()` certainly saves some effort. – Jonathan Leffler Oct 28 '15 at 03:45
  • @JonathanLeffler I thought the type additions like `size_t` were ``. – Jason Oct 28 '15 at 03:55
  • You need `` for `malloc()` and `free()`. Types like `size_t` are defined in multiple files, including ``, but also `` and `` and ``, so you relatively seldom need to include ``. – Jonathan Leffler Oct 28 '15 at 04:11
1

You probably want to allocate memory, here's how you would do it>

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

char* prompt()
{
  char* resp; // Create a variable for the users response
  int i;
  resp = malloc(sizeof(char));//allocate space for one char
  for (i = 0; i < 1000; ++i)
  {
    resp = realloc(resp, sizeof(char)*(i+1));//allocate space for one more char
    char letter = getchar(); // Get character
    if (letter == '\n') // If the user hits enter break the loop
    {
      break;
    }
    else  // Otherwise append the character to the response array
    {
      resp[i] = letter;
    }
  }

    return resp;  // Return the response array
  }

int main() {
   char* answer = prompt();
   printf("answer is %s\n", answer);
   return 0;
}

And this will work but it is highly NOT recommended to do it like this because you never free() your allocated memory.

EDIT> How to do it? You might want to avoid creating a new function and do it all in your main(), in that case, when you no longer need your variable simply call free(resp);

Rorschach
  • 734
  • 2
  • 7
  • 22
  • Thanks so much for your documented code and lucid response. And is it not possible to free the memory as soon as the function exits? What if I want to receive input over and over again. Wouldn't a function be preferable over repetition? – coder guy Oct 28 '15 at 02:58
  • It would. However you can only free your memory in the same function you allocate it. So you cant free in `main()` what you allocated elsewhere. However it can be done much easier and smarter. Please look at this response [link](http://stackoverflow.com/a/11656585/3735245) – Rorschach Oct 28 '15 at 03:04
  • 2
    @user3735245 If that were correct, you couldn't use `malloc`, or any of the functions that dynamically allocate memory for the user. Heap memory has a global scope by default. It's always the user's responsibility to define a meaningful scope for heap allocated memory and free it whenever it exits that scope. – Jason Oct 28 '15 at 03:42
  • 1
    Note that reallocating the buffer one byte bigger each time runs the risk of being very expensive (quadratic behaviour). This would be a bigger risk if there was any other memory allocation going on. The normal rule of thumb is to allocate twice as much memory each time you need more. That requires a bit more book-keeping. Also, the code should detect EOF — remember that `getchar()` returns an `int` and not a `char`. – Jonathan Leffler Oct 28 '15 at 03:44
  • 1
    Note that you can and should add `free(answer);` in `main()` after the `printf()`. – Jonathan Leffler Oct 28 '15 at 03:45