I want to find how many names in names array. I know sizeof(names)/sizeof(names[0]) gives the right answer. But the problem is I can't just declare char *names[];. Because compiler gives me an error like this "Storage of names is unknown". To avoid this error, I must declare like this char *names[] = {"somename", "somename2"};. But the thing is I cannot assign the strings right after deceleration. I assign strings after some conditions and my problem is how many strings i have after that conditions.
My example.
char *names[];
char word[10];
int i = 0;
while (fscanf(word, sizeof(word), fp)>0) {
// Think hello increase every time loop returns.
// such as "hello1", and the 2nd time "hello2"
if(strcmp(word, "hello1") == 0)
names[i] = word;
}
printf("size: %d\n", sizeof(names)/sizeof(names[0]));
An array size is fixed once the array is created. It cannot change.
If fp can be read twice, read the file once for the word count.
size_t word_count = 0;
int word_length_max = 0;
long pos = ftell(fp); // remember file location
int n = 0;
while (fscanf(fp, "%*s%n", &n) != EOF && n > 0) { // Use %n to record character count
word_count++;
if (n > word_length_max) {
word_length_max = n;
}
n = 0;
}
Now code knows the word[] array size needed and the maximum length.
char *words[word_count];
char word[word_length_max + 1u]; // buffer size needed to read in the words
fseek(fp, pos, SEEK_SET); // go back
for (size_t i=0; i<word_count; i++) {
if (fscanf(fp, "%s", word) != 1) {
Handle_UnexpectedError(); // 2nd pass should have same acceptable results
}
words[i] = strdup(word); // allocate a duplicate
}
When done with words[], be sure to free the allocated memory.
....
for (size_t i=0; i<word_count; i++) {
free(words[i]);
}
Better code would also check the return value of ftell(), fseek(), malloc() for errors and limit fscanf(fp, "%s", word).
Related
I have an assignment where we take in the contents from an input file and put it into arrys
the numbers on the first line represent the dimensions for the array. the first 6 regards the first 6 rows/lines on the text file, which i have put in a one dimensional ray but the characters after that i have to put them in a 5x6 2d array in the form of a solved crossword (with the spaces included and making sure to have a n extra column for '\0'so 5x7) I have to use malloc or calloc to make the array and my issue is making the matrix as it doesnt get the spaces or i get a segmentation dump. Im trying to make the arrays first(two arrays - one dimensional array of W strings and a 2d array of characters NxM) and make sure the elements are in the matrix but like i said i keep getting a segmentation dump. Im at a loss as to how to do this.
txt file:
6 5 6
nail
taco
name
men
next
can
next
namect
e aa
n nc
nail
here's my code so far:
void freeMatrix(char **matrix, int r, int c);
int main(int argc, char **argv)
{
int W, N, M;
char inBuf[SIZE], words[SIZE], crosswords[SIZE];
char *word;
char *outp;
FILE *input;
// FILE *output;
if (argc != 2)
{
printf("Error, please input the filenames\n");
exit(-1);
}
if ((input = fopen(argv[1], "r")) == NULL)
{
printf("Error, the file %s cannot be opened\n", argv[1]);
}
fgets(inBuf, SIZE, input);
sscanf(inBuf, "%i%i%i", &W, &N, &M);
word = (char *)malloc(sizeof(char) * W);
char *crossword[N];
char *ptr = word;
char token[N][M];
for (int x = 0; x < W; x++)
{
fgets(inBuf, SIZE, input);
sscanf(inBuf, "%s", &words);
printf("%s\n", words);
*ptr = *words;
}
for (int f = 0; f < N; f++)
{
crossword[f] = (char *)malloc(N * sizeof(char));
}
for (int y = 0; y < N; y++)
{
for (int z = 0; z < M; z++)
{
fscanf(input, "%c", &token[y][z]);
crossword[y][z] = token[y][z];
printf("%s", crossword[y][z]);
}
printf("\n");
}
fclose(input);
free(word);
freeMatrix(crossword, N, M);
return 0;
}
void freeMatrix(char **matric, int r, int c)
{
for (int i = 0; i < r; i++)
{
free(matric[i]);
}
free(matric);
}
I expected a crossword to be printed with the individual characters in the matrix the same way the text file has it set up. A segmentation error resulted. It prints the first 6 words fine as an array of strings but the 2d array of characters is where i fall short.
nail
taco
name
men
next
can
Segmentation fault (core dumped)
A lot of things wrong here. My first suggestion is just to get the easy bit working first. Read in the 6 words into an array and then print them out. Get that working first. (that isnt working in your code at the moment, you do not save the words then get entered anywhere). Here is whats wrong at the moment
fgets(inBuf, SIZE, input); // ok
sscanf(inBuf, "%i%i%i", &W, &N, &M); //ok
what is the purpose of word below? It is an array of 6 characters. There seems no point to it since 6 is the number of words, not the length of them
word = (char *)malloc(sizeof(char) * W);
char *crossword[N];
char *ptr = word;
// char token[N][M]; <<<< dont need this yet
// ok this loop read W words from the input file.
for (int x = 0; x < W; x++)
{
fgets(inBuf, SIZE, input); // good
sscanf(inBuf, "%s", &words); // you could have fscanf directly but ok
printf("%s\n", words); // print it
*ptr = *words; // meaningless line
}
I think that last line is somehow trying to copy the word you just read into the buffer 'word' given that you did *ptr = word earlier
First note the odd names, I would expect 'words' to be the array or wards and 'word' to be the one you just read.
More importantly thats not how you copy strings
So lets fix this
First we need an array of pointers to words
char *words[N];
I am reluctant to type that because its not standard c but you use it every where (Variable length arrays, my compiler does not allow it at all, even if I ask really nicely). But I will do it.
now we need a char buffer to read the current word into
char word[SIZE]; // get rid of old word and words
now lets do some reading
// get rid of old word and words
char word[SIZE];
char *words[N];
for (int x = 0; x < W; x++)
{
fgets(inBuf, SIZE, input);
sscanf(inBuf, "%s", &word);
words[x] = strdup(word);
}
now
for (int x = 0; x < W; x++)
{
printf("%s\n", words[x];
}
to prove we actually have the data
get all that workinig before moving on to the next section
PS, strdup is a wonderful function that mallocs the correct size for the string and then copies the string to the malloced buffer, returnig a pointer to the newly mallocd memory
There are several common mistakes present in this program.
If fopen fails, you print a warning but continue with the program anyway. You should exit here, or otherwise handle the event to prevent future reads from failing.
It would also be prudent to print errors to the standard error stream.
if ((input = fopen(argv[1], "r")) == NULL)
{
/* printf("Error, the file %s cannot be opened\n", argv[1]); */
fprintf(sterr, "Failed to open [%s].\n", argv[1]);
return EXIT_FAILURE;
}
Casting the result of malloc (or calloc, etc.) is not necessary in C. A void * can be safely and implicitly promoted to any other pointer type.
In addition to this, sizeof (char) is guaranteed to be 1.
/* word = (char *)malloc(sizeof(char) * W); */
word = malloc(W);
In sscanf(inBuf, "%s", &words), &words is a char (*)[SIZE], which is the wrong type for %s.
The & is not needed. words is of type char [SIZE], which will decay to the appropriate char * type when passed to a function.
fgets, fscanf, and sscanf can all fail. You should guard against this to prevent the rest of your program working with incorrect data.
fgets returns NULL on failure. *scanf functions return the number of successful conversions performed ("%s" is one conversion, "%i%i%i" is three).
if (NULL == fgets(inBuf, SIZE, input))
/* handle this event */;
if (1 != sscanf(inBuf, "%s", words))
/* handle this event */;
*ptr = *words; does not perform a string copy. Actually, it copies the first element of words to the first element of ptr.
ptr = words would assign the pointer value.
= is never used for string copying, and instead, copying is done with the strcpy function:
char one[64];
char two[] = "hello world."
strcpy(one, two);
Care must be taken to ensure that the destination buffer has enough space for the to-be-copied string (including its null terminating byte).
crossword[y][z] is a char. Use %c not %s to print single characters.
printf(/* "%s" */ "%c", crossword[y][z]);
The scanf specifier %s skips leading whitespace, begins reading characters into its buffer, and stops when it encounters more whitespace.
The result of sscanf(" e aa", "%s", buffer) would have buffer be equivalent to "e". You will not be able to parse the lines with spaces in them this way.
The character set conversion specifier (%[]) can be used to overcome this limitation, as it allows reading whitespace. %[^\n] will read all characters until it encounters a newline.
Note that using either %s or %[] without a limiting field width specifier is unsafe as gets, as you can overflow the buffer.
char buffer[16];
if (1 == sscanf(" e aa\n", "%15[^\n]", buffer))
printf("[%s]", buffer); /* => [ e aa] */
With that said, the simple solution is to just remove the newline from the input buffer (replace it with the null terminating byte), if it exists, and use that buffer directly.
char input[] = " e aa\n";
input[strcspn(input, "\n")] = 0;
The elements of crossword are initialized as
crossword[f] = (char *)malloc(N * sizeof(char));
with N as the length of the second dimension. They are then accessed as
for (int z = 0; z < M; z++) {
/* ... */
crossword[y][z] = token[y][z];
where z relies on a different bound (M instead of N). If N is 5, and M is 6, this will access memory out of bounds.
In general, there is no need for all these different, intermediate buffers (and pointers to buffers). This can be done with a single buffer for reading each line.
Here is a working example with some helper functions to reduce code repetition. The bulk of the program is in the run function. It should be relatively straightforward to follow along:
read the header information
allocate enough space for our word_count pointers to strings.
read word_count lines, for each:
allocate enough memory for it
copy the string to this allocated memory
allocate enough memory for a rows * cols matrix
read rows lines, for each:
copy each byte from the string (excluding the null byte) to the correct row and column in the matrix
use the data (display it)
free all allocations
Note that the input file must contain trailing whitespace on lines that require padding up to the specified cols length (truncation occurs if oversized).
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* output formatted message to stderr and exit program unsuccessfully */
static void panic(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
fputc('\n', stderr);
va_end(args);
exit(EXIT_FAILURE);
}
/* read a line of input into a size limited buffer; removes newline character */
static size_t read_file_line(char *buffer, int size, FILE *file) {
if (!fgets(buffer, size, file))
panic("Could not read user input.");
size_t length = strcspn(buffer, "\n");
buffer[length] = 0;
return length;
}
/* panic unless memory allocation successful */
static void *palloc(size_t bytes) {
void *p = malloc(bytes);
if (!p)
panic("Could not allocate %zu bytes.", bytes);
return p;
}
static void print_matrix(size_t r, size_t c, char (*m)[r][c]) {
putchar('+');
for (size_t i = 0; i < c; i++)
putchar('-');
puts("+");
for (size_t i = 0; i < r; i++) {
putchar('|');
for (size_t j = 0; j < c; j++)
putchar((*m)[i][j]);
puts("|");
}
putchar('+');
for (size_t i = 0; i < c; i++)
putchar('-');
puts("+");
}
static void run(FILE *file) {
size_t word_count;
size_t rows;
size_t cols;
char input[128];
/* read our header information */
read_file_line(input, sizeof input, file);
if (3 != sscanf(input, "%zu%zu%zu", &word_count, &rows, &cols))
panic("Could not read file header.");
/* allocate the word list, read and allocate each word */
char **words = palloc(sizeof *words * word_count);
for (size_t i = 0; i < word_count; i++) {
size_t len = read_file_line(input, sizeof input, file);
words[i] = palloc(len + 1);
strcpy(words[i], input);
}
/* allocate and read our matrix */
char (*matrix)[rows][cols] = palloc(sizeof *matrix);
for (size_t i = 0; i < rows; i++) {
size_t len = read_file_line(input, sizeof input, file);
if (len < cols)
panic("Insufficient column data: Required %zu, Read %zu", cols, len);
for (size_t j = 0; j < cols; j++)
(*matrix)[i][j] = input[j];
}
/* display our input */
for (size_t i = 0; i < word_count; i++)
printf("WORD: %s\n", words[i]);
print_matrix(rows, cols, matrix);
/* free the memory */
for (size_t i = 0; i < word_count; i++)
free(words[i]);
free(words);
free(matrix);
}
int main(int argc, char **argv) {
if (argc != 2)
panic("usage: %s FILENAME", argv[0]);
FILE *file = fopen(argv[1], "r");
if (!file)
panic("Could not open file [%s].", argv[1]);
run(file);
fclose(file);
}
stdout:
WORD: nail
WORD: taco
WORD: name
WORD: men
WORD: next
WORD: can
+------+
| next |
|namect|
| e aa|
| n nc|
| nail |
+------+
I seem to be losing the reference to my pointers here. I dont know why but I suspect its the pointer returned by fgets that messes this up.
I was told a good way to read words from a file was to get the line then separate the words with strok, but how can I do this if my pointers inside words[i] keep dissapearing.
text
Natural Reader is
john make tame
Result Im getting.
array[0] = john
array[1] = e
array[2] =
array[3] = john
array[4] = make
array[5] = tame
int main(int argc, char *argv[]) {
FILE *file = fopen(argv[1], "r");
int ch;
int count = 0;
while ((ch = fgetc(file)) != EOF){
if (ch == '\n' || ch == ' ')
count++;
}
fseek(file, 0, SEEK_END);
size_t size = ftell(file);
fseek(file, 0, SEEK_SET);
char** words = calloc(count, size * sizeof(char*) +1 );
int i = 0;
int x = 0;
char ligne [250];
while (fgets(ligne, 80, file)) {
char* word;
word = strtok(ligne, " ,.-\n");
while (word != NULL) {
for (i = 0; i < 3; i++) {
words[x] = word;
word = strtok(NULL, " ,.-\n");
x++;
}
}
}
for (i = 0; i < count; ++i)
if (words[i] != 0){
printf("array[%d] = %s\n", i, words[i]);
}
free(words);
fclose(file);
return 0;
}
strtok does not allocate any memory, it returns a pointer to a delimited string in the buffer.
therefore you need to allocate memory for the result if you want to keep the word between loop iterations
e.g.
word = strdup(strtok(ligne, " ,.-\n"));
You could also hanle this by using a unique ligne for each line read, so make it an array of strings like so:
char ligne[20][80]; // no need to make the string 250 since fgets limits it to 80
Then your while loop changes to:
int lno = 0;
while (fgets(ligne[lno], 80, file)) {
char *word;
word = strtok(ligne[lno], " ,.-\n");
while (word != NULL) {
words[x++] = word;
word = strtok(NULL, " ,.-\n");
}
lno++;
}
Adjust the first subscript as needed for the maximum size of the file, or dynamically allocate the line buffer during each iteration if you don't want such a low limit. You could also use getline instead of fgets, if your implementation supports it; it can handle the allocation for, though you then need to free the blocks when you are done.
If you are processing real-world prose, you might want to include other delimiters in your list, like colon, semicolon, exclamation point, and question mark.
I want to create a program in C that takes an arbitrary number of lines of arbitrary length as input and then prints to console the last line that was inputted. For example:
input:
hi
my name is
david
output: david
I figured the best way to do this would be to have a loop that takes each line as input and stores it in a char array, so at the end of the loop the last line ends up being what is stored in the char array and we can just print that.
I have only had one lecture in C so far so I think I just keep setting things up wrong with my Java/C++ mindset since I have more experience in those languages.
Here is what I have so far but I know that it's nowhere near correct:
#include <stdio.h>
int main()
{
printf("Enter some lines of strings: \n");
char line[50];
for(int i = 0; i < 10; i++){
line = getline(); //I know this is inproper syntax but I want to do something like this
}
printf("%s",line);
}
I also have i < 10 in the loop because I don't know how to find the total number of lines in the input which, would be the proper amount of times to loop this. Also, the input is being put in all at once from the
./program < test.txt
command in Unix shell, where test.txt has the input.
Use fgets():
while (fgets(line, sizeof line, stdin)) {
// don't need to do anything here
}
printf("%s", line);
You don't need a limit on the number of iterations. At the end of the file, fgets() returns NULL and doesn't modify the buffer, so line will still hold the last line that was read.
I'm assuming you know the maximum length of the input line.
This one here will surely do the job for you
static char *getLine( char * const b , size_t bsz ) {
return fgets(b, bsz, stdin) );
}
But remember fgets also puts a '\n' character at the end of buffer so perhaps something like this
static char *getLine( char * const b , size_t bsz ) {
if( fgets(b, bsz, stdin) ){
/* Optional code to strip NextLine */
size_t size = strlen(b);
if( size > 0 && b[size-1] == '\n' ) {
b[--size] = '\0';
}
/* End of Optional Code */
return b;
}
return NULL;
}
and your code needs to be altered a bit while calling the getline
#define BUF_SIZE 256
char line[BUF_SIZE];
for(int i = 0; i < 10; i++){
if( getLine(line, BUF_SIZE ) ) {
fprintf(stdout, "line : '%s'\n", line);
}
}
Now it is how ever quite possible to create function like
char *getLine();
but then one needs to define the behavior of that function for instance if the function getLine() allocates memory dynamically then you probably need use a free to de-allocate the pointer returned by getLine()
in which case the function may look like
char *getLine( size_t bsz ) {
char *b = malloc( bsz );
if( b && fgets(b, bsz, stdin) ){
return b;
}
return NULL;
}
depending on how small your function is you can entertain thoughts about making it inline perhaps that's a little off topic for now.
In order to have dynamic number of input of dynamic length, you have to keep on reallocating your buffer when the input is of greater length. In order to store the last line, you have to take another pointer to keep track of it and to stop the input from the terminal you have to press EOF key(ctrl+k). This should do your job.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *get_last_line(FILE* fp, size_t size){
//The size is extended by the input with the value of the provisional
char *str, *last_str = NULL;
int ch;
size_t len = 0, last_len = 0;
str = realloc(NULL, sizeof(char)*size);//size is start size
if(!str)return str;
while(ch=fgetc(fp)){
if(ch == EOF){
break;
}
if(ch == '\n'){
str[len]='\0';
last_len = len;
last_str = realloc(last_str,sizeof(char)*last_len);
last_str[last_len]='\0';
//storing the last line
memcpy(last_str,str,sizeof(char)*last_len);
str = realloc(NULL, sizeof(char)*size);//size is start size
len = 0;
}
else {
str[len++]=ch;
if(len==size){
str = realloc(str, sizeof(char)*(size+=16));
if(!str)return str;
}
}
}
free(str);
return last_str;
}
int main(void){
char *m;
printf("input strings : ");
m = get_last_line(stdin, 10);
printf("last string :");
printf("%s\n", m);
free(m);
return 0;
}
I'm trying to work on an assignment. The idea is to get an array of strings, and a file stream. I need to look for those strings in the file, and count the occurrence of these strings.
I think I've got the basic loop down. The only problem is that, when I find a string in the line, I want to search for that string again (in case of more than one occurrence) by starting from 1 + the position where the found string starts.
#define LINE_MAX_CHARS 1000
// n = number of strings to be found
// **strings = array of strings to look for in file
void count_occurrences (int n, FILE *file, char **strings) {
char str[LINE_MAX_CHARS]; // buffer
int count = 0;
while (fgets(str, LINE_MAX_CHARS, file) != NULL){ // for each line
for (int i = 0; i < n; i++){ // for each word in line
char *found;
found = (strstr(str, (*(strings + i)))); // search line
if (found != NULL){ // if word found in line
// here, I want str (the buffer) to have its 0-th element to be the element at (found + 1),
// and the 1-st element to be (found + 2) and so on...
i--; // to look for same word in the rest of the line
count = count + 1;
}
}
}
}
Another problem is that I have no way of testing my code. I'm just given a test program that runs and tells me whether or not my code is producing the correct output.
I am REQUIRED to use fgets and strstr.
Suggestions?
strstr(str, strings[i]) Returns a pointer to a position in the string. You should be able to increment that pointer (str++) and pass it straight back into strstr() in a loop, incrementing count each time, finishing the loop if strstr() returns NULL or str hits the null character.
It should look something like this. I've not tested this; but since this is your homework, if it doesn't work/compile quite right, I'm going to leave it to you to debug. That means I won't have done all the work for you...
;-)
void count_occurrences (int n, FILE *file, char **strings) {
char str[LINE_MAX_CHARS];
int count = 0;
while (fgets(str, LINE_MAX_CHARS, file) != NULL){
for (int i = 0; i < n; i++){
char *pos = str;
while(((pos = strstr(pos, strings[i]) != NULL) && *pos != '\n') {
count++;
pos++;
}
}
}
}
To count every occurrence of strings[i] in the current line, you have to use a loop and you have to let strstr start at least one position after the last occurrence. See the following code:
#define LINE_MAX_CHARS 1000
// n = number of strings to be found
// **strings = array of strings to look for in file
void count_occurrences (int n, FILE *file, char **strings) {
char str[LINE_MAX_CHARS]; // buffer
int count = 0;
while (fgets(str, LINE_MAX_CHARS, file) != NULL){ // for each line
for (int i = 0; i < n; i++){ // for each word in line
char *found = str;
do {
found = strstr(found, strings[i]); // search line
if (found != NULL){ // if word found in line
count = count + 1;
found++;
}
}
while (found)
}
}
}
Is there a way to read a text file into a one dimensional array in plain C? Here's what I tried (I am writing hangman):
int main() {
printf("Welcome to hangman!");
char buffer[81];
FILE *dictionary;
int random_num;
int i;
char word_array[80368];
srand ( time(NULL) );
random_num = rand() % 80368 + 1;
dictionary = fopen("dictionary.txt", "r");
while (fgets(buffer, 80, dictionary) != NULL){
printf(buffer); //just to make sure the code worked;
for (i = 1; i < 80368; i++) {
word_array[i] = *buffer;
}
}
printf("%s, \n", word_array[random_num]);
return 0;
}
What's wrong here?
Try changing a couple of things;
First; you're storing a single char. word_array[i] = *buffer; means to copy a single character (the first one on the line/in the buffer) into each (and every) single-char slot in word_array.
Secondly, your array will hold 80K characters, not 80K words. Assuming that that's the length of your dictionary file, you can't fit it all in there using that loop.
I'm assuming you have 80,368 words in your dictionary file. That's about 400,000 words less than /usr/share/dict/words on my workstation, though, but sounds like a reasonable size for hangman…
If you want a one-dimensional array intentionally, for some reason, you'll have to do one of three things:
pretend you're on a mainframe, and use 80 chars for every word:
char word_array[80368 * 80];
memcpy (&(word_array[80 * i]), buffer, 80);
create a parallel array with indices to the start of each line in a huge buffer
int last_char = 0;
char* word_start[80368];
char word_array[80368 * 80];
for ( … i++ ) {
memcpy (&word_array[last_char], buffer, strlen(buffer));
word_start[i] = last_char;
last_char += strlen(buffer);
}
switch to using an array of pointers to char, one word per slot.
char* word_array[80368];
for (int i = 0; i < 80368, i++) {
fgets (buffer, 80, dictionary);
word_array[i] = strdup (buffer);
}
I'd recommend the latter, as otherwise you have to guess at the max size or waste a lot of RAM while reading. (If your average word length is around 4-5 chars, as in English, you're on average wasting 75 bytes per word.)
I'd also recommend dynamically allocating the word_array:
int max_word = 80368;
char** word_array = malloc (max_word * sizeof (char*));
… which can lead you to a safer read, if your dictionary size ever were to change:
int i = 0;
while (1) {
/* If we've exceeded the preset word list size, increase it. */
if ( i > max_word ) {
max_word *= 1.2; /* tunable arbitrary value */
word_array = realloc (word_array, max_word * sizeof(char*));
}
/* Try to read a line, and… */
char* e = fgets (buffer, 80, dictionary);
if (NULL == e) { /* end of file */
/* free any unused space */
word_array = realloc (word_array, i * sizeof(char*));
/* exit the otherwise-infinite loop */
break;
} else {
/* remove any \r and/or \n end-of-line chars */
for (char *s = &(buffer[0]); s < &(buffer[80]); ++s) {
if ('\r' == *s || '\n' == *s || '\0' == *s) {
*s = '\0'; break;
}
}
/* store a copy of the word, only, and increment the counter.
* Note that `strdup` will only copy up to the end-of-string \0,
* so you will only allocate enough memory for actual word
* lengths, terminal \0's, and the array of pointers itself. */
*(word_array + i++) = strdup (buffer);
}
}
/* when we reach here, word_array is guaranteed to be the right size */
random = rand () % max_word;
printf ("random word #%d: %s\n", random, *(word_array + random));
Sorry, this is posted in an hurry, so I haven't tested the above. Caveat emptor.
This part is wrong:
while (fgets(buffer, 80, dictionary) != NULL){
printf(buffer); //just to make sure the code worked;
for (i = 1; i < 80368; i++) {
word_array[i] = *buffer;
}
}
You are copying 80368 chars from buffer which has size 81. Change it to:
i = 0;
while (fgets(buffer, 80, dictionary) != NULL){
printf(buffer); //just to make sure the code worked;
for (j = 0; j < 80; j++) {
word_array[i++] = buffer[j];
}
}