How to store fgets string results into an char array? - c

I am currently getting the following error
Process terminated with status -1073741819
and I suspect its my fgets() but I have no idea why this is happening, any help would be much appreciated.
//Gets Dictionary from file
char* GetDictionary() {
int ArraySize;
int i = 0;
FILE * DictionaryFile;
//Gets first line (in this case it is the amount of Lines)
DictionaryFile = fopen("dictionary.txt", "r");
fscanf(DictionaryFile,"%d", &ArraySize);
ArraySize = ArraySize + 1;
printf("%d", ArraySize);
fclose(DictionaryFile);
//Gets the array
char* Dictionary = malloc(sizeof(char)*ArraySize);
char Temp[ArraySize];
char TempArray[ArraySize];
DictionaryFile = fopen("dictionary.txt", "r");
while(fgets(Temp, sizeof Temp, DictionaryFile)!=NULL) {
Dictionary[i] = Temp;
//Check The array
printf("%s", Dictionary[i]);
i++;
}
fclose(DictionaryFile);
return Dictionary;
}

-1073741819 --> C0000005 and likely has some significance. Maybe use below to discern its meaning.
puts(strerror(-1073741819));
Code has many issues: Here are some corrected to get you going.
1) Allocate an array of pointers, not an array of char
// char* Dictionary = malloc(sizeof(char)*ArraySize);
char** Dictionary = malloc(ArraySize * sizeof *Dictionary);
2) Form a big buffer to read each line
char Temp[100];
3) After reading each line, get rid of the likely trailing '\n'
size_t len = strlen(Temp);
if (len && Temp[len-1] == '\n') Temp[--len] = 0;
4) Allocate memory for that word and save
Dictionary[i] = malloc(len + 1);
assert(Dictionary[i]);
memcpy(Dictionary[i], Temp, len + 1);
5) Robust code frees it allocations before completion
6) Code reads "amount of Lines" twice as file is opened twice. Just leave file open (and not re-open it). #user3386109

You likely want Dictionary to be an array of char strings. That is, Dictionary is an array, and each element in the array is a char *. That makes Dictionary a char **.
For this example, it may be most straightforward to allocate memory for the Dictionary array itself, then allocate memory for its contents. You'll need to free all this when you're done, of course.
char **Dictionary = malloc(sizeof(char *) * ArraySize);
for (int i = 0; i < ArraySize; i++) {
Dictionary[i] = malloc(ArraySize);
}
There are better ways to do this. For one, you might only allocate memory when you need it, for each fgets() return. You could also use strdup() to allocate only the memory you need. You could also pass in Dictionary from the caller, already allocated, so you don't worry about allocating it here.
Later in your program, as #WhozCraig pointed out, you need to copy the string in Temp, like strcpy(Dictionary[i], Temp), in place of Dictionary[i] = Temp. I too am surprised that's not generating a compiler warning!

Related

C - Saving strings into array elements

I have a notepad file with approximately 150,000 words (representing a dictionary). I'm trying to scan in each word and print it to the console. This setup works fine:
void readDictionary(FILE *ifp, int numWords) {
fscanf(ifp, "%d", &numWords);
printf("%d\n", numWords);
int i;
char* words = (char*)malloc(20 * sizeof(char));
for(i = 0; i < numWords; i++) {
fscanf(ifp, "%s", words);
printf("%s\n", words);
}
}
However, this code obviously overwrites "words" each time it loops. I'm trying to get each word to save to a certain array element. I did the following but it instantly crashes (I changed the memory allocation to 2D because I read around here and it seems that is what I am supposed to do):
void readDictionary(FILE *ifp, int numWords) {
fscanf(ifp, "%d", &numWords);
printf("%d\n", numWords);
int i;
char** words = (char**)malloc(20 * sizeof(char*));
for(i = 0; i < numWords; i++) {
fscanf(ifp, "%s", words[i]);
printf("%s\n", words[i]);
}
}
Any help is appreciated. I've read around on many posts but haven't figured it out.
In your second version, you allocate space for 20 pointers, but you leave those pointers uninitialized and without anything to point to. I'm sure you can imagine how that presents a problem when you then try to read from your dictionary into the memory designated by one of those pointers.
It looks like you want to allocate space for numwords pointers
char** words = malloc(numwords * sizeof(*words));
, and for each of them, to allocate space for a word.
for(i = 0; i < numWords; i++) {
words[i] = malloc(20); // by definition, sizeof(char) == 1
// ...
Additionally, do check the return value of malloc(), which will be NULL in the event of allocation failure.
The first problem is you only allocated space for a list of words (ie. character pointers) but you didn't allocate space for the words themselves.
char** words = (char**)malloc(20 * sizeof(char*));
This allocates space for 20 character pointers and assigns it to words. Now words[i] has space for a character pointer but not for the characters.
words[i] contains garbage, because malloc does not initialize memory. When you pass it into fscanf, fscanf tries to use the garbage in words[i] as a memory location to write characters to. That's either going to corrupt some memory in the program, or more likely it tries to read a memory location is isn't allowed to and crashes. Either way, it's not good.
You have to allocate memory for the string, pass that to fscanf, and finally put that string into words[i].
char** words = malloc(numWords * sizeof(char*));
for(i = 0; i < numWords; i++) {
char *word = malloc(40 * sizeof(char));
fscanf(ifp, "%39s", word);
words[i] = word;
printf("%s\n", words[i]);
}
Note that I didn't cast the result of malloc, that's generally considered unnecessary.
Also note that I allocated space for numWords in the list. Your original only allocates space for 20 words, once it goes over that it'll start overwriting allocated memory and probably crash. As a rule of thumb, avoid constant memory allocations. Get used to dynamic memory allocation as quickly as you can.
Also note that I limited how many characters fscanf is allowed to read to the size of my buffer (minus one because of the null byte at the end of strings). Otherwise if your word list contained "Pneumonoultramicroscopicsilicovolcanoconiosis", 45 characters, it would overrun the word buffer and start scribbling on adjacent elements and that would be bad.
This leads to a new problem that are common to fscanf and scanf: partial reads. When the code above encounters "Pneumonoultramicroscopicsilicovolcanoconiosis" fscanf(ifp, "%39s", word); will read in the first 39 characters, "Pneumonoultramicroscopicsilicovolcanoco" and stop. The next call to fscanf will read "niosis". You'll store and print them as if they were two words. That's no good.
You could solve this by making the word buffer bigger, but now most words will be wasting a lot of memory.
scanf and fscanf have a whole lot of problems and are best avoided. Instead, it's best to read entire lines and parse them with sscanf. In this case you don't need to do any parsing, they're just strings, so getting the line will suffice.
fgets is the usual way to read a line, but that also requires that you try and guess how much memory you'll need to read in the line. To mitigate that, have a large line buffer, and copy the words out of it.
void strip_newline( char* string ) {
size_t len = strlen(string);
if( string[len-1] == '\n' ) {
string[len-1] = '\0';
}
}
...
int i;
/* The word list */
char** words = malloc(numWords * sizeof(char*));
/* The line buffer */
char *line = malloc(1024 * sizeof(char*));
for(i = 0; i < numWords; i++) {
/* Read into the line buffer */
fgets(line, 1024, ifp);
/* Strip the newline off, fgets() doesn't do that */
strip_newline(line);
/* Copy the line into words */
words[i] = strdup(line);
printf("%s\n", words[i]);
}
strdup won't copy all 1024 bytes, just enough for the word. This will result in using only the memory you need.
Making assumptions about files, like that they'll have a certain number of lines, is a recipe for problems. Even if the file says it contains a certain number of lines you should still verify that. Otherwise you'll get bizarre errors as you try to read past the end of the file. In this case, if the file has less than numWords it'll try to read garbage and probably crash. Instead, you should read the file until there's no more lines.
Normally this is done by checking the return value of fgets in a while loop.
int i;
for( i = 0; fgets(line, 1024, ifp) != NULL; i++ ) {
strip_newline(line);
words[i] = strdup(line);
printf("%s\n", words[i]);
}
This brings up a new problem, how do we know how big to make words? You don't. This brings us to growing and reallocating memory. This answer is getting very long, so I'll just sketch it.
char **readDictionary(FILE *ifp) {
/* Allocate a decent initial size for the list */
size_t list_size = 256;
char** words = malloc(list_size * sizeof(char*));
char *line = malloc(1024 * sizeof(char*));
size_t i;
for( i = 0; fgets(line, 1024, ifp) != NULL; i++ ) {
strip_newline(line);
/* If we're about to overflow the list, double its size */
if( i > list_size - 1 ) {
list_size *= 2;
words = realloc( words, list_size * sizeof(char*));
}
words[i] = strdup(line);
}
/* Null terminate the list so readers know when to stop */
words[i] = NULL;
return words;
}
int main() {
FILE *fp = fopen("/usr/share/dict/words", "r");
char **words = readDictionary(fp);
for( int i = 0; words[i] != NULL; i++ ) {
printf("%s\n", words[i]);
}
}
Now the list will start at size 256 and grow as needed. Doubling grows pretty fast without wasting too much memory. My /usr/share/dict/words has 235886 lines in it. That can be stored in 218 or 262144. 256 is 28 so it only requires 10 expensive calls to realloc to grow to the necessary size.
I've changed it to return the list, because there isn't much good in building the list if you're just going to use it immediately. This allows me to demonstrate another technique in working with dynamically sized lists, null termination. The last element in the list is set to NULL so anyone reading the list knows when to stop. This is safer and simpler than trying to pass the length around with the list.
That was a lot, but that's all the basic stuff you need to do when working with files in C. It's good to do it manually, but fortunately there are libraries out there which make doing this sort of thing a lot easier. For example, Gnome Lib provides a lot of basic functionality including arrays of pointers that automatically grow as needed.

Access value of a pointer in dynamically allocated memory

My assignment is to read words from a text file and store them in character arrays which are stored in an array of char*. All memory in these arrays needs to be dynamically allocated.
What I am doing is reading in each word with fscanf() and storing it into the variable str. I am then calculating the length of the word in str and dynamically allocating memory to store the value of str in the character array new_word. new_word is then inserted into the array of char* named words. When words runs out of space, I double its size and continue.
My problem lies in the commented code starting on line 62. I'm going to need to read these words later from words, so I'm testing my ability to access the pointers and their values. I can index new_word fine (in the lines above), but when I then store new_word in words and try to read from words, I get the following error:
hw1.c:63:25: error: subscripted value is not an array, pointer, or vector
while (*(words[count])[k] != '\0'){
on lines 63 and 64. I know it has something to do with dereferencing the pointer, but I have tried a bunch of variations with no success. How can I fix this?
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[]){
if (argc != 3){
fprintf(stderr, "Incorrect number of arguments\n");
exit(1);
}
char* infile = argv[1];
FILE* finp = fopen(infile, "r");
if (finp == NULL){
fprintf(stderr, "Unable to open input file\n");
exit(1);
}
char* prefix = argv[2];
int count = 0;
int size = 20;
char* words = calloc(size, sizeof(char));
printf("Allocated initial array of 20 character pointers.\n");
char* str = malloc(30*sizeof(char));
while (fscanf(finp, "%s", str) == 1){
if (count == size){
words = realloc(words, 2 * size);
size *= 2;
printf("Reallocated array of %d character pointers.\n", size);
}
int i = 0;
while (str[i] != '\0'){
i++;
}
char* new_word = malloc((i+1)*sizeof(char));
int j = 0;
while (str[j] != '\0'){
new_word[j] = str[j];
j++;
}
new_word[j] = '\0';
int k = 0;
while (new_word[k] != '\0'){
printf("%c", new_word[k]);
k++;
}
printf("\n");
words[count] = *new_word;
/*k = 0;
while (*(words[count])[k] != '\0'){
printf("%c", *(words[count])[k]);
k++;
}
printf("\n");*/
count++;
}
}
Ok, dissecting that a bit:
char* words = calloc(size, sizeof(char));
this should probably read:
char **words = calloc(size, sizeof(char *));
Why? What you want here is a pointer to an array of pointers to char ... words points to the first char *, which points to your first "string".
char* str = malloc(30*sizeof(char));
while (fscanf(finp, "%s", str) == 1){
Buffer overflow here. Make sure to read at maximum 30 characters if you define your buffer not to hold more. Btw, just for convention, call your buffer buffer or buf (not str) and there's really no need to dynamically allocate it. Hint: Use a field size for fscanf() or, even better, some other function like fgets().
if (count == size){
words = realloc(words, 2 * size);
size *= 2;
printf("Reallocated array of %d character pointers.\n", size);
}
The realloc here will not work, should read
words = realloc(words, 2 * size * sizeof(char *));
You need to multiply the size of a single element, which, in this case, is a pointer to char.
No guarantee this will be all errors, but probably the most important ones. On a sidenote, strlen() and strncpy() will help you stop writing unnecessary code.
A pointer to "A [dynamically-allocated] array of char*" would need to be recorded in a variable of type char **. That is, a pointer to the first element of the array, which element is of type char *. Thus ...
char **words;
If you want to have sufficient space for size words, then you could allocate it as ...
words = calloc(size, sizeof(char *));
(note the difference from your code), though it's harder to make a mistake with this form:
words = calloc(size, sizeof(*words));
Note in that case that the sizeof operator does not evaluate its operand, so it does not matter that words is not yet allocated.
Most importantly, be aware that the elements of array words are themselves pointers, not the ultimately pointed-to strings. Thus you assign a new word to the array by
words[count] = new_word;
(Again, note the difference from your version.) Other adjustments are needed as well.
The problematic while loop, though, is not fixed even then. Remember that the expression pointer[index] is equivalent to *((pointer) + (index)), so the expression *(words[count])[k] attempts to triply derference words. Even with the type correction, you want only to doubly dereference it: words[count][k].
But why re-invent the wheel? As Olaf observed with respect to strlen() and some of your earlier code, C already has perfectly good functions in its standard library for dealing with strings. In this case ...
printf("%s", words[count]);
... would be so much simpler than that while loop.

reading a file of strings to a multidimensional array to access later

I am really having a problem understanding dynamically allocated arrays.
I am attempting to read a text file of strings to a 2d array so I can sort them out later. right now as my code stands it throws seg faults every once in a while. Which means I'm doing something wrong. I've been surfing around trying to get a better understanding of what malloc actually does but I want to test and check if my array is being filled.
my program is pulling from a text file with nothing but strings and I am attempting to put that data into a 2d array.
for(index = 0; index < lines_allocated; index++){
//for loop to fill array 128 lines at a time(arbitrary number)
words[index] = malloc(sizeof(char));
if(words[index] == NULL){
perror("too many characters");
exit(2);
}
//check for end of file
while(!feof(txt_file)) {
words = fgets(words, 64, txt_file);
puts(words);
//realloc if nessesary
if (lines_allocated == (index - 1)){
realloc(words, lines_allocated + lines_allocated);
}
}
}
//get 3rd value placed
printf("%s", words[3]);
since this just a gist, below here ive closed and free'd the memory, The output is being displayed using puts, but not from the printf from the bottom. an ELI5 version of reading files to an array would be amazing.
Thank you in advance
void *malloc(size_t n) will allocate a region of n bytes and return a pointer to the first byte of that region, or NULL if it could not allocate enough space. So when you do malloc(sizeof(char)), you're only allocating enough space for one byte (sizeof(char) is always 1 by definition).
Here's an annotated example that shows the correct use of malloc, realloc, and free. It reads in between 0 and 8 lines from a file, each of which contains a string of unknown length. It then prints each line and frees all the memory.
#include <stdio.h>
#include <stdlib.h>
/* An issue with reading strings from a file is that we don't know how long
they're going to be. fgets lets us set a maximum length and discard the
rest if we choose, but since malloc is what you're interested in, I'm
going to do the more complicated version in which we grow the string as
needed to store the whole thing. */
char *read_line(void) {
size_t maxlen = 16, i = 0;
int c;
/* sizeof(char) is defined to be 1, so we don't need to include it.
the + 1 is for the null terminator */
char *s = malloc(maxlen + 1);
if (!s) {
fprintf(stderr, "ERROR: Failed to allocate %zu bytes\n", maxlen + 1);
exit(EXIT_FAILURE);
}
/* feof only returns 1 after a read has *failed*. It's generally
easier to just use the return value of the read function directly.
Here we'll keep reading until we hit end of file or a newline. */
while ('\n' != (c = getchar())) {
if (EOF == c) {
/* We return NULL to indicate that we hit the end of file
before reading any characters, but if we've read anything,
we still want to return the string */
if (0 == i) return NULL;
break;
}
if (i == maxlen) {
/* Allocations are expensive, so we don't want to do one each
iteration. As such, we're always going to allocate more than
we need. Exactly how much extra we allocate depends on the
program's needs. Here, we just add a constant amount. */
maxlen += 16;
/* realloc will attempt to resize the memory pointed to by s,
or copy it to a newly allocated region of size maxlen. If it
makes a copy, it will free the old version. */
char *p = realloc(s, maxlen + 1);
if (!p) {
/* If the realloc fails, it does not free the old version, so we do it here. */
free(s);
fprintf(stderr, "ERROR: Failed to allocate %zu bytes\n", maxlen + 1);
exit(EXIT_FAILURE);
}
s = p;//set the pointer to the newly allocated memory
}
s[i++] = c;
}
s[i] = '\0';
return s;
}
int main(void) {
/* If we wanted to, we could grow the array of strings just like we do the strings
themselves, but for brevity's sake, we're just going to stop reading once we've
read 8 of them. */
size_t i, nstrings = 0, max_strings = 8;
/* Each string is an array of characters, so we allocate an array of char*;
each char* will point to the first element of a null-terminated character array */
char **strings = malloc(sizeof(char*) * max_strings);
if (!strings) {
fprintf(stderr, "ERROR: Failed to allocate %zu bytes\n", sizeof(char*) * max_strings);
return 1;
}
for (nstrings = 0; nstrings < max_strings; nstrings++) {
strings[nstrings] = read_line();
if (!strings[nstrings]) {//no more strings in file
break;
}
}
for (i = 0; i < nstrings; i++) {
printf("%s\n", strings[i]);
}
/* Free each individual string, then the array of strings */
for (i = 0; i < nstrings; i++) {
free(strings[i]);
}
free(strings);
return 0;
}
I haven't looked too closely so I could be offering an incomplete solution.
That being said, the error is probably here:
realloc(words, lines_allocated + lines_allocated);
realloc if succesful returns the new pointer, if you're lucky it can allocate the adjacent space (which wouldn't cause a segfault).
words = realloc(words, lines_allocated + lines_allocated);
would solve it, although you probably need to check for errors.

C - list of char*'s - Memory Allocation

I am confused about how to allocate memory correctly. I am trying to make a list of char*'s from a text file. Every time I make a char* do I have to allocate memory for it? When and where are the exceptions?
#define BUFF 1000
int main(int argc, char** argv)
{
FILE* file;
file = fopen(argv[1], "r");
char* word = calloc(BUFF, sizeof(char));
char* sentence = calloc(BUFF, sizeof(char));
char** list = calloc(BUFF, sizeof(char*));
int i = 0;
while((fgets(sentence, BUFF, file)) != NULL)
{
word = strtok(sentence, " ,/.");
while(word != NULL)
{
printf("%s\n", word);
strcpy(list[i], word);
i++;
word = strtok(NULL, " ,/.");
}
}
int k;
for(k = 0; k < i; k++)
{
puts("segging here");
printf("%s\n", list[i]);
}
The rule is: you have to allocate any memory that you use.
Your problem comes in:
strcpy(list[i], word);
list[i] is currently not pointing to any allocated storage (it's probably a null pointer). You have to make it point somewhere before you can copy characters into it.
One way would be:
list[i] = strdup(word);
strdup is not an ISO C standard function, but it is equivalent to doing malloc then strcpy. You will need to free afterwards.
Also, the i++ line needs to stop when i == BUFF, and it'd be useful to add \n to the list of strtok separators .
In addition to Matt McNabb's answer, there's also a more subtle problem with your usage of strtok. That function doesn't require an output buffer; it just returns a pointer to somewhere inside the input buffer.
When you call char* word = calloc(BUFF, sizeof(char));, you allocate memory and assign word to point to the allocated memory. Then, when you call word = strtok(sentence, " ,/.");, you overwrite the value of word. That means that no pointer in your control points to the memory you've allocated. That memory is no longer useful to your code, and you can't deallocate it; it has been leaked.
You can fix this issue by writing char* word = strtok(sentence, " ,/."); Then, since you didn't allocate the memory that word points to, remember not to free it either.
your list is a char* list, with the size of BUFF, but the list[i] is what?
you do not allocate memory to it.
you need to allocate the memory for list[i] in a loop

Trying to load text file into an array, getting a seg fault. Any ideas why?

The task of this function is fairly straightforward. Given an array of char*, a pointer to a file, and a maximum word size, it reads through the file and copies each word one by one into the char* array. Since there's one word per line in the file, it makes sense to use \n as the break between words. So with that in mind, the code should be fairly simple to interpret:
void loadDictionary(char* strDictionary[], FILE* filePointer, int nMaxLetters)
{
int nNameCount= 0, nCursor = 0;
char* strCurrent;
char cCurrent;
//allocate space for a word
strCurrent = malloc(nMaxLetters * sizeof(char));
while ((cCurrent = fgetc(filePointer)) != EOF) {
if(cCurrent != '\n')
{
strCurrent[nCursor] = cCurrent;
nCursor++;
} else { //then we've reached the end of the line (word)
//add null termination to string
strCurrent[nCursor] = '\0'; //SEG FAULT
//copy string to dictionary
memcpy(strDictionary[nNameCount], strCurrent, strlen(strCurrent)+1);
//increment count
nNameCount++;
//reset the cursor
nCursor = 0;
}
}
}
This code generates a segmentation fault at the line where I call strCurrent[nCursor] = '\0';. I'm not sure why, because on the face of it, it seems like this operation should be no different from the operation in the other block, where I call strCurrent[nCursor] = cCurrent;. strCurrent should have allocated more than enough space to store all necessary characters. So, I'm somewhat at a loss. Help me figure this one out, guys.
Note: I think I would probably have an easier time using fgets instead of fgetc to accomplish this task. I might well switch to that; however, since I have encountered an error I don't understand, I don't want to leave it alone until I've understood it.
EDIT:
Someone pointed out that the error might occur in the memcpy operation, possibly due to strDictionary being improperly allocated. Here's the main block where strDictionary gets allocated. Perhaps I have made an error:
int main(int argc, char* argv[])
{
char** strDictionary;
FILE* filePointer;
int nResults = 0, nLines = 0, nNumLines, nMaxChars, i;
filePointer = fopen("dictionary.txt", "r");
//obtain the number of lines and the maximum word size of the dictionary
countLines(filePointer, &nNumLines, &nMaxChars);
//allocate memory for strDictionary
strDictionary = malloc(nNumLines * nMaxChars * sizeof(char));
printf("%d words in dictionary. Longest word is %d letters\n",
nNumLines, nMaxChars);
//Output here correctly prints: 1000 and 21
//reset the file pointer (not sure if this is a necessary step, but oh well)
filePointer = fopen("dictionary.txt", "r");
//load dictionary into memory
loadDictionary(strDictionary, filePointer, nMaxChars);
for (i=0; i<10; i++)
printf("%dth element of dictionary: %s\n", i, strDictionary[i]);
return 0;
}
EDIT 2:
OK, I decided to use fgets() instead of fgetc() to greatly simplify my function. I've also done what I thought was a correct malloc() operation for strDictionary. However, I'm still getting a seg fault. Here's the updated code:
void loadDictionary(char* strDictionary[], FILE* filePointer, int nMaxLetters)
{
printf("Call to loadDictionary. nMaxLetters = %d\n", nMaxLetters);
int nWordCount= 0, nCursor = 0;
char* strCurrent;
char cCurrent;
strCurrent = malloc(nMaxLetters); //allocate space for a word
while (fgets(strCurrent, nMaxLetters, filePointer) != NULL)
{
memcpy(strDictionary[nWordCount], strCurrent, strlen(strCurrent)+1);
nWordCount++;
}
}
int main(int argc, char* argv[])
{
char** strDictionary;
FILE* filePointer;
int nResults = 0, nLines = 0, nNumLines, nMaxChars, i;
filePointer = fopen("dictionary.txt", "r");
//count the lines in the file (works fine)
countLines(filePointer, &nNumLines, &nMaxChars);
//allocate space for the dictionary
strDictionary = malloc(nNumLines * sizeof(char*));
for (i = 0; i<nLines; i++)
strDictionary[i] = malloc(nMaxChars * sizeof(char));
printf("%d words in dictionary. Longest word is %d letters\n",
nNumLines, nMaxChars);
//load dictionary into array
filePointer = fopen("dictionary.txt", "r");
loadDictionary(strDictionary, filePointer, nMaxChars);
for (i=0; i<10; i++)
printf("%dth element of dictionary: %s\n", i, strDictionary[i]);
return 0;
}
Here:
char cCurrent;
...
while ((cCurrent = fgetc(filePointer)) != EOF) {
You are truncating the fgetc()'s value of type int to char. This may lead to the while condition not correctly recognizing EOF. cCurrent has to be int.
Here:
//allocate space for a word
strCurrent = malloc(nMaxLetters * sizeof(char));
nMaxLetters has to account for one extra character representing the string NUL terminator. Is it accounted for?
Btw, sizeof(char) is always 1.
Now, this parameter declaration:
char* strDictionary[]
is equivalent to this:
char** strDictionary
or, IOW, a pointer to a pointer to a char. That's because in C, arrays are never passed as parameters, only pointers to their first elements are, despite the deceptive syntax with the brackets suggesting something is an array.
This line:
memcpy(strDictionary[nNameCount], strCurrent, strlen(strCurrent)+1);
is going to take nNameCount'th pointer to a char and write character data where it points to.
But does the calling function allocate at least as many string buffers (of length nMaxLetters) as there are going to be lines in the file? Does it populate some array of pointers to char with the pointers to these buffers before passing this array into loadDictionary()? IOW, this code is expecting the caller to do something like this:
#define nMaxEntries 1000
char* dictionary[nMaxEntries];
int i;
FILE* f;
...
for (i = 0; i < nMaxEntries; i++)
dictionary[i] = malloc(nMaxLetters);
loadDictionary(dictionary, f, nMaxLetters);
Memory allocation failures must be checked in the above code. Also, I'd strongly suggest passing nMaxEntries into or using it in loadDictionary() so you don't overrun the array of pointers if the file has more lines than nMaxEntries. nNameCount should not grow beyond nMaxEntries.
UPDATE to the updated question...
Here:
char** strDictionary;
...
strDictionary = malloc(nNumLines * nMaxChars * sizeof(char));
You are not creating an array of pointers to char as loadDictionary() expects per the above analysis, you are creating a 2d array of char. And because of that the segfault most probably occurs not on this line:
strCurrent[nCursor] = '\0'; //SEG FAULT
but on the very next one, which may not be apparent in the debugger until you zoom in and look at the disassembly of the code:
//copy string to dictionary
memcpy(strDictionary[nNameCount], strCurrent, strlen(strCurrent)+1);
UPDATE2:
I don't understand why you now allocate space for nNumLines pointers:
strDictionary = malloc(nNumLines * sizeof(char*));
but of those nNumLines pointers you initialize nLines pointers (and nLines never becomes anything other than 0 if I'm reading your latest code correctly):
for (i = 0; i<nLines; i++)
strDictionary[i] = malloc(nMaxChars * sizeof(char));
What's the trick? Typo?

Resources