I wrote a program in C that tokenizes an input string, and when the user enters "exit", it exits the program.
It seems to tokenize the string correctly, however, when I exit the program, I get an error either about an "aborted (core dumped) error" about freeing memory, or a munmap_chunk error.
Here is the link to the picture of my output:
ErrorMessage
And here is my code for the program:
int main() {
/* Main Function Variables */
char *buf;
char *token;
size_t num_chars;
size_t bufsize = 2048;
int run = 1;
int tok_count = 0;
int cmp;
/* Allocate memory for the input buffer. */
buf = (char *) malloc(sizeof(char) * bufsize);
/*main run loop*/
while(run) {
/* Print >>> then get the input string */
printf(">>> ");
num_chars = getline(&buf, &bufsize, stdin);
cmp = strcmp(buf, "exit\n");
if (num_chars > 1) {
/* Tokenize the input string */
if (cmp != 0) {
/* Display each token */
while((token = strtok_r(buf, " ", &buf))) {
printf("T%d: %s\n", tok_count, token);
tok_count++;
}
}
/* If the user entered <exit> then exit the loop */
else {
run = 0;
break;
}
}
tok_count = 0;
}
/*Free the allocated memory*/
free(buf);
return 1;
}
What may be the problem here that is causing the free() errors and munmap_chunk errors?
Related
I'm trying to read in a text file, say input.txt, into an array of structs to then print out (and free memory of course). My C coding is a bit scratchy though, and I'm looking for help.
Input.txt contains lines of information about a single person. I want to read in the people, sort by name and print out in sorted order. Before I can do this, I'm just trying to create an array of people, allocate memory to each person, copy in the details from the text file, and then print them out finally. It's not even getting to the print out, as you can see it gives a segmentation fault:
I'm using the following:
gcc -Wall -O2 -o program filename.c
and getting this
Segmentation fault: 11
input.txt contents:
Joan 0212672938 joan#gmail.com
John 0365242939 john#yahoo.com
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person {
char *name;
char *phone;
char *email;
};
int main(void) {
int i;
int peopleSize = 0;
char * pch;
FILE *f = fopen("input.txt", "r");
if (f == NULL) return EXIT_FAILURE;
struct person** people = malloc(100 * (sizeof (people[0])));
/* Create 100 people */
char *nameTmp = malloc(30 * sizeof nameTmp[0]);
char *phoneTmp = malloc(30 * sizeof phoneTmp[0]);
char *emailTmp = malloc(30 * sizeof emailTmp[0]);
/* Open the file for reading */
char *line_buf = NULL;
size_t line_buf_size = 0;
int line_count = 0;
ssize_t line_size;
/* Get the first line of the file. */
line_size = getline(&line_buf, &line_buf_size, f);
while (line_size >= 1) {
line_count += 1;
people[line_count-1] = malloc(sizeof (people[line_count-1]));
/* if fgets returns an empty space or new line, no more people to add, break loop */
/* Within str, use strtok to divide strings up into name, phone and email */
strcpy(pch, line_buf);
pch = strtok (pch, " ");
strcpy(nameTmp, pch);
printf("%s\n", nameTmp);
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(phoneTmp, pch);
}
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(emailTmp, pch);
}
/* Allocate enough memory to person->name and person->phone and person->email as required */
people[line_count-1]->name = malloc((strlen(nameTmp) + 1) * sizeof (people[line_count-1]->name[0]));
people[line_count-1]->phone = malloc((strlen(phoneTmp) + 1) * sizeof (people[line_count-1]->phone[0]));
people[line_count-1]->email = malloc((strlen(emailTmp) + 1) * sizeof (people[line_count-1]->email[0]));
/* Now copy values from temporary variables into actual person */
strcpy(people[line_count-1]->name, nameTmp);
strcpy(people[line_count-1]->phone, phoneTmp);
strcpy(people[line_count-1]->email, emailTmp);
/* Get the next line */
line_size = getline(&line_buf, &line_buf_size, f);
}
peopleSize = line_count;
/* Printing all the people out */
for (i = 0; i < peopleSize; i++) {
printf("%s\t", people[i]->name);
printf("%s\t", people[i]->phone);
printf("%s", people[i]->email);
printf("\n");
}
/* Freeing all of the memory */
for (i = 0; i < peopleSize; i++) {
free(people[i]->email);
free(people[i]->phone);
free(people[i]->name);
free(people[i]);
}
free(people);
return EXIT_SUCCESS;
}
In general, when debugging, I would recommend compiling without optimizations and with the debug flag (-g). Then step through your program in GDB and see where it breaks.
Most of the fixes were already mentioned in the comments. See the code below for a line-by-line explanation of the fixes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { // now you can use "person" type rather than "struct person"
char *name;
char *phone;
char *email;
} person;
int main(void) {
int i;
int peopleSize = 0;
char * pch = malloc(30); // Must be initialized before use
FILE *f = fopen("input.txt", "r");
if (f == NULL) return EXIT_FAILURE;
person** people = malloc(100 * (sizeof(person*))); //This is an array of 100 pointers to person so you want sizeof(person*)
/* Create 100 people */
char *nameTmp = malloc(30); // These are char arrays. Each char occupys a byte and malloc allocates byte by default.
char *phoneTmp = malloc(30);
char *emailTmp = malloc(30);
/* Open the file for reading */
char *line_buf = malloc(30); // MUst be initialized before use;
size_t line_buf_size = 0;
int line_count = 0;
ssize_t line_size;
/* Get the first line of the file. */
line_size = getline(&line_buf, &line_buf_size, f);
while (line_size >= 1) {
line_count += 1;
people[line_count-1] = malloc(sizeof(person)); // You are allocating memory for a single person, so you want sizeof(person)
/* if fgets returns an empty space or new line, no more people to add, break loop */
/* Within str, use strtok to divide strings up into name, phone and email */
strcpy(pch, line_buf);
pch = strtok (pch, " ");
strcpy(nameTmp, pch);
printf("%s\n", nameTmp);
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(phoneTmp, pch);
}
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(emailTmp, pch);
}
/* Allocate enough memory to person->name and person->phone and person->email as required */
people[line_count-1]->name = malloc(strlen(nameTmp) + 1); // As above these are char arrays so there is no need for sizeof
people[line_count-1]->phone = malloc(strlen(phoneTmp) + 1);
people[line_count-1]->email = malloc(strlen(emailTmp) + 1);
/* Now copy values from temporary variables into actual person */
strcpy(people[line_count-1]->name, nameTmp);
strcpy(people[line_count-1]->phone, phoneTmp);
strcpy(people[line_count-1]->email, emailTmp);
/* Get the next line */
line_size = getline(&line_buf, &line_buf_size, f);
}
peopleSize = line_count;
/* Printing all the people out */
for (i = 0; i < peopleSize; i++) {
printf("%s\t", people[i]->name);
printf("%s\t", people[i]->phone);
printf("%s", people[i]->email);
printf("\n");
}
/* Freeing all of the memory */
for (i = 0; i < peopleSize; i++) {
free(people[i]->email);
free(people[i]->phone);
free(people[i]->name);
free(people[i]);
}
free(people);
return EXIT_SUCCESS;
}
I wrote a program in C that tokenizes an input string, and when the user enters "exit", it exits the program.
It tokenizes the string correctly, however, when I test my program with valgrind, I get some memory leaks. The only scenario when I don't get memory leaks is after compiling and then executing, I exit right away.
Here is the output with valgrind:
Valgrind Memory Leaks
And here is my code for the program:
int main() {
/* Main Function Variables */
char *buf;
char *savecpy = NULL;
char *token;
size_t num_chars;
size_t bufsize = 2048;
int run = 1;
int tok_count = 0;
int cmp;
/* Allocate memory for the input buffer. */
buf = (char *) malloc(sizeof(char) * bufsize);
/*main run loop*/
while(run) {
/* Print >>> then get the input string */
printf(">>> ");
num_chars = getline(&buf, &bufsize, stdin);
cmp = strcmp(buf, "exit\n");
if (num_chars > 1) {
/* Tokenize the input string */
if (cmp != 0) {
/* Display each token */
savecpy = strdup(buf);
while((token = strtok_r(savecpy, " ", &savecpy))) {
printf("T%d: %s\n", tok_count, token);
tok_count++;
}
}
/* If the user entered <exit> then exit the loop */
else {
run = 0;
break;
}
}
tok_count = 0;
}
/*Free the allocated memory*/
free(buf);
return 1;
}
What may be the problem here that is causing the memory leaks in valgrind? I am freeing my memory for my input string, but I still get memory leaks.
savecpy should be freed. As seen in the manual:
Memory for the new string is obtained
with malloc(3), and can be freed with free(3).
savecpy can not be freed after passing through strtok_r third argument, as this function modifies the pointer. Rather pass something like this
char* ptr;
strtok_r(..,.., &ptr);
Then you can free savecpy
I am dynamically allocating the 2D array like this:
char ** inputs;
inputs = (char **) malloc(4 * sizeof(char));
After doing this I started having the problem with the string. I printed the string before and after allocating the 2D-array:
printf("%s\n", str);
char ** inputs;
inputs = (char **) malloc(4 * sizeof(char));
printf("%s\n", str);
But I get strange output:
before: input aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa with len 34
after: input aaaaaaaaaaaaaaaaaaaaaaaaaaaa with len 29
Why the length is changed? I've searched through stackoverflow and other websites but couldn't find reasonable answer for that.
Here is my all function call:
int main(int argc, char const *argv[])
{
/* code */
mainProcess();
printf("\nEnd of the program\n");
return 0;
}
// Reading the input from the user
char * getInput(){
printf("Inside of the getInput\n");
char * result;
char * st;
char c;
result = malloc(4 * sizeof(char));
st = malloc(4 * sizeof(char));
// code goes here
printf("$ ");
while(3){
c = fgetc(stdin);
if(c == 10){
break;
}
printf("%c", c);
result[length] = c;
length++;
}
result[length] = '\0';
return result;
}
void mainProcess(){
char * input;
printf("Inside of Main process\n");
input = getInput();
printf("\nthis is input %s with len %d\n", input, strlen(input));
splitInput(input);
printf("\nthis is input %s with len %d\n", input, strlen(input));
}
char ** splitInput(const char * str){
char ** inputs;
inputs = NULL;
printf("inside split\n");
printf("%s\n", str);
inputs = (char **) malloc( sizeof(char));
// free(inputs);
printf("------\n"); // for testing
printf("%s\n", str);
if(!inputs){
printf("Error in initializing the 2D array!\n");
exit(EXIT_FAILURE);
}
return NULL;
}
It is not entirely clear what you are trying to accomplish, but it appears you are attempting to read a line of text with getInput and then you intend to separate the input into individual words in splitInput, but are not clear on how to go about doing it. The process of separating a line of text into words is called tokenizing a string. The standard library provide strtok (aptly named) and strsep (primarily useful if you have the possibility of an empty delimited field).
I have explained the difference between a 2D array and your use of a pointer-to-pointer-to-char in the comments above.
To begin, look at getInput. One issue that will give you no end of grief is c must be type int or you cannot detect EOF. In addition, you can simply pass a pointer (type size_t) as a parameter and keep count of the characters in result and avoid the need for strlen to get the length of the returned string. You MUST use a counter anyway to insure you do not write beyond the end of result to begin with, so you may as well make the count available back in the calling function e.g.
char *getInput (size_t *n)
{
printf ("Inside of the getInput\n");
char *result = NULL;
int c = 0; /* c must be type 'int' or you cannot detect EOF */
/* validate ALL allocations */
if ((result = malloc (MAXC * sizeof *result)) == NULL) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return result;
}
printf ("$ ");
fflush (stdout); /* output is buffered, flush buffer to show prompt */
while (*n + 1 < MAXC && (c = fgetc (stdin)) != '\n' && c != EOF) {
printf ("%c", c);
result[(*n)++] = c;
}
putchar ('\n'); /* tidy up with newline */
result[*n] = 0;
return result;
}
Next, as indicated above, it appears you want to take the line of text in result and use splitInput to fill a pointer-to-pointer-to-char with the individual words (which you are confusing to be a 2D array). To do that, you must keep in mind that strtok will modify the string it operates on so you must make a copy of str which you pass as const char * to avoid attempting to modify a constant string (and the segfault).
You are confused in how to allocate the pointer-to-pointer-to-char object. First you must allocate space for a sufficient number of pointers, e.g. (with #define MAXW 32) you would need something like:
/* allocate MAXW pointers */
if ((inputs = malloc (MAXW * sizeof *inputs)) == NULL) {
fprintf (stderr, "error: memory exhausted - inputs.\n");
return inputs;
}
Then as you tokenize the input string, you must allocate for each individual word (each themselves an individual string), e.g.
if ((inputs[*n] = malloc ((len + 1) * sizeof *inputs[*n])) == NULL) {
fprintf (stderr, "error: memory exhausted - word %zu.\n", *n);
break;
}
strcpy (inputs[*n], p);
(*n)++;
note: 'n' is a pointer to size_t to make the word count available back in the caller.
To tokenize the input string you can wrap the allocation above in:
for (char *p = strtok (cpy, delim); p; p = strtok (NULL, delim))
{
size_t len = strlen (p);
...
if (*n == MAXW) /* check if limit reached */
break;
}
Throughout your code you should also validate all memory allocations and provide effective returns for each function that allocates to allow the caller to validate whether the called function succeeded or failed.
Putting all the pieces together, you could do something like the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 256 /* constant for maximum characters of user input */
#define MAXW 32 /* constant for maximum words in line */
void mainProcess();
int main (void)
{
mainProcess();
printf ("End of the program\n");
return 0;
}
char *getInput (size_t *n)
{
printf ("Inside of the getInput\n");
char *result = NULL;
int c = 0; /* c must be type 'int' or you cannot detect EOF */
/* validate ALL allocations */
if ((result = malloc (MAXC * sizeof *result)) == NULL) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return result;
}
printf ("$ ");
fflush (stdout); /* output is buffered, flush buffer to show prompt */
while (*n + 1 < MAXC && (c = fgetc (stdin)) != '\n' && c != EOF) {
printf ("%c", c);
result[(*n)++] = c;
}
putchar ('\n'); /* tidy up with newline */
result[*n] = 0;
return result;
}
/* split str into tokens, return pointer to array of char *
* update pointer 'n' to contain number of words
*/
char **splitInput (const char *str, size_t *n)
{
char **inputs = NULL,
*delim = " \t\n", /* split on 'space', 'tab' or 'newline' */
*cpy = strdup (str);
printf ("inside split\n");
printf ("%s\n", str);
/* allocate MAXW pointers */
if ((inputs = malloc (MAXW * sizeof *inputs)) == NULL) {
fprintf (stderr, "error: memory exhausted - inputs.\n");
return inputs;
}
/* split cpy into tokens (words) max of MAXW words allowed */
for (char *p = strtok (cpy, delim); p; p = strtok (NULL, delim))
{
size_t len = strlen (p);
if ((inputs[*n] = malloc ((len + 1) * sizeof *inputs[*n])) == NULL) {
fprintf (stderr, "error: memory exhausted - word %zu.\n", *n);
break;
}
strcpy (inputs[*n], p);
(*n)++;
if (*n == MAXW) /* check if limit reached */
break;
}
free (cpy); /* free copy */
return inputs;
}
void mainProcess()
{
char *input = NULL,
**words = NULL;
size_t len = 0, nwords = 0;
printf ("Inside of Main process\n\n");
input = getInput (&len);
if (!input || !*input) {
fprintf (stderr, "error: input is empty or NULL.\n");
return;
}
printf ("this is input '%s' with len: %zu (before split)\n", input, len);
words = splitInput (input, &nwords);
printf ("this is input '%s' with len: %zu (after split)\n", input, len);
free (input); /* done with input, free it! */
printf ("the words in input are:\n");
for (size_t i = 0; i < nwords; i++) {
printf (" word[%2zu]: '%s'\n", i, words[i]);
free (words[i]); /* free each word */
}
free (words); /* free pointers */
putchar ('\n'); /* tidy up with newline */
}
Example Use/Output
$ ./bin/mainprocess
Inside of Main process
Inside of the getInput
$ my dog has fleas
my dog has fleas
this is input 'my dog has fleas' with len: 16 (before split)
inside split
my dog has fleas
this is input 'my dog has fleas' with len: 16 (after split)
the words in input are:
word[ 0]: 'my'
word[ 1]: 'dog'
word[ 2]: 'has'
word[ 3]: 'fleas'
End of the program
Memory Error Check
In any code you write that dynamically allocates memory, you need to run your code though a memory/error checking program. On Linux, valgrind is the normal choice. Simply run your code through it, e.g.
$ valgrind ./bin/mainprocess
==15900== Memcheck, a memory error detector
==15900== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==15900== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==15900== Command: ./bin/mainprocess
==15900==
Inside of Main process
Inside of the getInput
$ my dog has fleas
my dog has fleas
this is input 'my dog has fleas' with len: 16 (before split)
inside split
my dog has fleas
this is input 'my dog has fleas' with len: 16 (after split)
the words in input are:
word[ 0]: 'my'
word[ 1]: 'dog'
word[ 2]: 'has'
word[ 3]: 'fleas'
End of the program
==15900==
==15900== HEAP SUMMARY:
==15900== in use at exit: 0 bytes in 0 blocks
==15900== total heap usage: 7 allocs, 7 frees, 546 bytes allocated
==15900==
==15900== All heap blocks were freed -- no leaks are possible
==15900==
==15900== For counts of detected and suppressed errors, rerun with: -v
==15900== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always verify you have freed any memory you allocate, and that there are no memory errors.
Look things over and let me know if you have any questions. If I guess wrong about what you intended, well that's where an MCVE helps :)
This code compiles (gcc -Wall) without warnings and does not change the size.
It also tries to stress the need for allocating enough space and/or not to write beyond allocated memory.
Note for example the
malloc((MaxInputLength+1) * sizeof(char))
while(length<MaxInputLength)
inputs[i]=malloc((MaxLengthOfSplitString+1) * sizeof(char));
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// the length which was used in your MCVE, probably accidentally
#define MaxInputLength 3 // you will probably want to increase this
#define MaxLengthOfSplitString 1 // and this
#define MaxNumberOfSplitStrings 3 // and this
// Reading the input from the user
char * getInput(){
printf("Inside of the getInput\n");
char * result;
char c;
int length=0;
result = malloc((MaxInputLength+1) * sizeof(char));
// code goes here
printf("$ ");
while(length<MaxInputLength){
c = fgetc(stdin);
if(c == 10){
break;
}
printf("%c", c);
result[length] = c;
length++;
}
result[length] = '\0';
return result;
}
char ** splitInput(const char * str){
char ** inputs;
inputs = NULL;
printf("inside split\n");
printf("%s\n", str);
inputs = (char **) malloc(MaxNumberOfSplitStrings * sizeof(char*));
{
int i;
for (i=0; i< MaxNumberOfSplitStrings; i++)
{
inputs[i]=malloc((MaxLengthOfSplitString+1) * sizeof(char));
}
// Now you have an array of MaxNumberOfSplitStrings char*.
// Each of them points to a buffer which can hold a ero- terminated string
// with at most MaxLengthOfSplitString chars, ot counting the '\0'.
}
// free(inputs);
printf("------\n"); // for testing
printf("%s\n", str);
if(!inputs){
printf("Error in initializing the 2D array!\n");
exit(EXIT_FAILURE);
}
return NULL;
}
void mainProcess(){
char * input;
printf("Inside of Main process\n");
input = getInput();
printf("\nthis is input %s with len %d\n", input, strlen(input));
splitInput(input);
printf("\nthis is input %s with len %d\n", input, strlen(input));
}
int main(int argc, char const *argv[])
{
/* code */
mainProcess();
printf("\nEnd of the program\n");
return 0;
}
So i am attempting to pass a string array (char** arguments) to a function, fill the array with values and then print those values after returning from the function. The problem occurs when I try to print the first value of "arguments" which gives me a segmentation fault. Why is this? when I print the values in the "getArguments" function all goes as expected. I am new to C and yes this is an assignment. I am not looking for you to write this code for me however I would like an explanation of this behaviour as I try to understand this concept.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define BUFFERSIZE 81
int getArguments(char** arguments, char* argument);
void getPath(char* pathBuffer);
int checkForDirectoryChange(char **arguments, int num_args);
int main(int argc, char *argv[]){
char * command;
char ** arguments = NULL;
char * cd_path;
int len, pid, ret_code, cd_requested = 1;
char buffer[BUFFERSIZE];
/* Get user input and the first token */
printf("Enter a command: > ");
command = fgets(buffer,BUFFERSIZE,stdin);
printf("The command entered was %s",buffer);
len = strlen(buffer);
if(buffer[len-1] == '\n')
buffer[len-1]='\0';
cd_requested = getArguments(arguments, command);
printf("The argument passed is now: %s\n", arguments[0]);
if(cd_requested == 0){
fprintf(stdout,"Change directory requested.\n");
}
/*
char * pathBuf;
getPath(pathBuf);
free the memory allocated */
/*
pid = fork();
if(pid){
wait(NULL);
}else{
ret_code = execvp(*arguments, arguments);
if(ret_code){
printf("The fork failed, exiting.");
exit(0);
}
}*/
}
int getArguments(char** arguments, char* command){
int n_spaces = 0,i;
char *token;
token = strtok(command, " ");
/* Loop until we have gotten all of the tokens */
while (token) {
arguments = realloc (arguments, sizeof (char*) * ++n_spaces);
if (arguments == NULL){
printf("Memory allocation failed: token - %d\n", n_spaces);
exit (-1); /* memory allocation failed */
}
arguments[n_spaces-1] = token;
token = strtok (NULL, " ");
}
/* realloc one extra element for the last NULL */
arguments = realloc (arguments, sizeof (char*) * (n_spaces+1));
arguments[n_spaces] = 0;
/* print the result */
for (i = 0; i < (n_spaces+1); ++i)
printf ("arguments[%d] = %s\n", i, arguments[i]);
return strcmp("cd",arguments[0]);
}
int checkForDirectoryChange(char** arguments, int num_args){
return 0;
}
void getPath(char* pathBuffer){
size_t n;
n = confstr(_CS_PATH, NULL, (size_t) 0);
pathBuffer = malloc(n);
if (pathBuffer == NULL)
abort();
confstr(_CS_PATH, pathBuffer, n);
}
It is because getArguments() only reassigned the copy of pointer to pointer of characters inside itself. arguments in main() was not updated.
You should define getArguments() as
int getArguments(char*** arguments, char* command) {
/* ... */
while (token) {
*arguments = realloc (*arguments, sizeof (char*) * ++n_spaces);
if (*arguments == NULL){
printf("Memory allocation failed: token - %d\n", n_spaces);
exit (-1); /* memory allocation failed */
}
(*arguments)[n_spaces-1] = token;
token = strtok (NULL, " ");
}
/* ... */
}
And call it as the following inside main().
cd_requested = getArguments(&arguments, command);
In a separate .txt file, I have: de4 dw9 ds8 g8,7 m3,4 p2,2
The function below cuts the string up into an array.
The output of the array is this:
de4 / w9 / s8 / g8,7 / m3,4 / p2,2 / (null)
As you can see, the "w9" and "s8" are missing the 'd'. I cannot seem to figure out why. Here is my function:
void parseFile(char ** argv)
{
FILE * textFile;
char * string;
char ** lineToken;
int i;
textFile = fopen(argv[1], "r");
lineToken = malloc(sizeof(char *) + 1);
string = malloc(sizeof(char *) + MAX_CHAR);
while(fgets(string, MAX_CHAR, textFile) != NULL)
{
lineToken[0] = strtok(string, " "); /* Put first element in lineToken[0] */
for(i = 1; string != NULL; i++)
{
lineToken = realloc(lineToken, (sizeof(char *) * (i + 1))); /* Realloc since total number of elements is unknown */
if(lineToken == NULL) /* Check to see if reallocing caused an error */
{
move(0,0);
printw("Error reallocing. Press any key to close program.");
refresh();
getch();
exit(0);
endwin();
}
lineToken[i] = strtok(NULL, " "); /* Put new strtok'd string into lineToken[i] */
system("clear");
move(0,0);
printw("%s", lineToken[i]);
refresh();
getch();
}
}
for(i = 0; lineToken[i] != NULL; i++)
{
system("clear");
move(0,0);
printw("%s", lineToken[i]);
refresh();
getch();
}
fclose(textFile);
free(string);
free(lineToken);
}
There are two pretty obvious problems:
The first is the condition for the inner loop when reading from the file, string != NULL. unless the allocation of string failed initially this condition will always be true. You need to check the return of strtok instead: lineToken[i - 1] != NULL.
The second problem is that you only have a single "array" for all lines you read. So if you have more than a single line in the file you overwrite all tokens you read from the first line.
A third problem: If the reallocation fails, you exit the program. However, you have code after that exit call, and the exit function does not return so the call to endwin will not happen in that case.