0

Why doesn't this main print anything? It should print the first word in the file.

int main(int argc, char *argv[])
{
  FILE *file = fopen(argv[1], "r");
  int n = atoi(argv[2]);

  char **words = new char*[n];
  for(int i = 0; i < n; i++)
    {
      fscanf(file, "%s ", words[i]);
    }
  cout << words[0] << endl;
}
Fábio Junqueira
  • 2,701
  • 21
  • 20
Elliot Gorokhovsky
  • 3,610
  • 2
  • 31
  • 56

2 Answers2

2

words[i] is a pointer that points to a random memory location. Make sure to make it point to allocated memory.

//Now words[i] points to the 1000 bytes allocated with the new keyword
words[i] = new char[1000];
//fscan will write the input to those bytes
fscanf(file, "%s ", words[i]);
Fábio Junqueira
  • 2,701
  • 21
  • 20
  • What if I don't know how many bytes the words will need? How can I look at each word, see how many bytes it needs, and then allocate that many bytes? Would I use a temp variable? – Elliot Gorokhovsky Feb 03 '16 at 03:28
  • To figure out how big the line you are reading is, you must read it until you reach the line terminator. One way of doing this is by allocating a large memory buffer, reading the data into it, and checking if the line terminator was found. If it wasn't, realloc a larger buffer, read more data into it, and check again. Here is a example: http://stackoverflow.com/questions/2532425/read-line-from-file-without-knowing-the-line-length – Fábio Junqueira Feb 03 '16 at 12:16
2

char **words = new char*[n]; will allocate a buffer to hold n pointers to char, words is just a pointer to an array of pointers. You need allocate enough memory for words[i](the pointer to ) to hold the string:

for (i=0; i < n; ++i ) {
    words[i] = new char[your_max_string_len];
}

Optionally you can use getline extension of GNU(if you use gcc) to do what you want:

size_t len = 0;
ssize_t read;
read = getline(&words[i], &len, stdin);
...
free(words[i]);

Actually, there is no magic in this function, it just does the memory allocation under the hood to save yours, and it's your responsibility to free it.

jfly
  • 7,715
  • 3
  • 35
  • 65
  • What if I don't know how many bytes the words will need? How can I look at each word, see how many bytes it needs, and then allocate that many bytes? Would I use a temp variable? – Elliot Gorokhovsky Feb 03 '16 at 03:42
  • If you don't read the string, how can you know the length of the string? But you need allocate enough memory when you read the string:) – jfly Feb 03 '16 at 03:47
  • So I would read it into a temp variable, then look at the length of the string in the temp variable, then copy it into the array? – Elliot Gorokhovsky Feb 03 '16 at 03:53
  • Yes, you can use a `char[your_max_string_len]` as a temp variable to read the string ,the `strcpy` to the allocated memory. – jfly Feb 03 '16 at 03:57
  • 1
    Optionally you can use `getline` [extension of GNU](http://man7.org/linux/man-pages/man3/getline.3.html) to do what you want: `read = getline(&words[i], &len, stdin)` – jfly Feb 03 '16 at 04:00
  • @RenéG You should be using `std::string` and `getline`so you don't need to be allocating memory or worrying about buffer sizes. – crashmstr Feb 03 '16 at 04:24
  • @crashmstr The class uses C++, but we haven't learned any actual C++ yet, we're basically just using the C subset for now. Except for the streams. – Elliot Gorokhovsky Feb 03 '16 at 05:46