I appear to be getting a segmentation fault, but I can't figure out where or why it occurs. Any input would be helpful.
I'm basically trying to read an input as chars, store them into word until I hit a space, and when I hit a space, store that word into a wordList.
All this has to be done without ever storing in memory (must use dynamic allocation).
The relevant code is:
char* word;
int WFactor = 30;
int WLFactor = 30;
char** wordList;
int wordCount = 0;
int letterCount = 0;
word = (char*)malloc(sizeof(char) * WFactor);
wordList = (char**)malloc(sizeof(char*) * WLFactor);
if( word == NULL ){
free(word);
free(wordList);
fprintf(stderr, "Memory Allocation Failure");
exit(1);
}
if(wordList == NULL){
fprintf(stderr, "Memory Allocation Failure");
exit(1);
}
char cur = '*';
while(cur!=EOF){
if(letterCount == WFactor){
WFactor = WFactor * 2;
word = realloc(word, sizeof(char)*WFactor);
if(word == NULL){
free(word);
free(wordList);
fprintf(stderr, "Memory Re-Allocation Failure");
exit(1);
}
}
cur = getchar();
if(cur!=EOF && cur!= ' '){
putchar(cur);
word[letterCount] = cur;
letterCount++;
}
if(cur == ' '){
if(wordCount == WLFactor){
WLFactor = WLFactor*2;
wordList = realloc(wordList, sizeof(char*)*WLFactor);
if(wordList == NULL){
free(word);
free(wordList);
fprintf(stderr, "Memory Re-Allocation Failure");
exit(1);
}
}
printf("%s", "e");
wordList[wordCount] = word;
wordCount++;
letterCount =0;
word = NULL;
WFactor = 19;
printf("HERE");
word = malloc(sizeof(char)*WFactor);
if(word == NULL){
free(wordList);
fprintf(stderr, "Memory Allocation Failure");
exit(1);
}
}
}
getchar() returns int not char.
If you assign its result to char it is not possible to safely detect ^EOF`.
To fix this change
char cur = '*';
to be
int cur = '*';
Related
I'm currently programming a shell in C and I am stuck on the parsing function.
At the moment I have a 'shell_readLine ()' function and a 'shell_split_line ()' function.
I would like to improve the splitLine function so that it takes into account redirects such as: '|', '<' or '>'. Currently, only spaces serve as delimiters. I do not know where to start.
shell_readLine fonction :
char *shell_readLine(void)
{
int buffsize = SHELL_RL_BUFFSIZE;
int position = 0;
char *buffer = malloc(sizeof(char) * buffsize);
int c;
if(!buffer) {
fprintf(stderr, "shell: allocation error\n");
exit(EXIT_FAILURE);
}
while(1) {
// Read a character
c = getchar();
// If EOF, replace with null and return
if(c == EOF || c == '\n') {
buffer[position] = '\0';
return buffer;
} else {
buffer[position] = c;
}
position++;
// Check if we have exceeded the buffer and reallocate if necessary
if(position >= buffsize) {
buffsize += SHELL_RL_BUFFSIZE;
buffer = realloc(buffer, buffsize);
if(!buffer) {
fprintf(stderr, "shell: allocation error\n");
exit(EXIT_FAILURE);
}
}
}
}
And my shell_split_line fonction :
/*
* Does not allow quoting or backslash escaping in command line args
*/
char **shell_split_line(char *line) {
int buffsize = SHELL_TOK_BUFFSIZE, position = 0;
char **tokens = malloc(buffsize * sizeof(char *));
char *token;
if(!tokens) {
fprintf(stderr, "shell: allocation error\n");
exit(EXIT_FAILURE);
}
token = strtok(line, SHELL_TOK_DELIM);
while(token != NULL) {
tokens[position] = token;
position++;
if(position >= buffsize) {
buffsize += SHELL_TOK_BUFFSIZE;
tokens = realloc(tokens, buffsize * sizeof(char *));
if(!tokens) {
fprintf(stderr, "shell: allocation error\n");
exit(EXIT_FAILURE);
}
}
token = strtok(NULL, SHELL_TOK_DELIM);
}
tokens[position] = NULL;
return tokens;
}
Thanks in advance for your advices and ideas. I do not really know where to start and even how to make this. It's my first shell ever and i'm not a pro of C language.
I am novice to C programming and I have written a code to a requirement specification but I am consistently getting Segmentation Fault and unable to proceed ahead.
If the file name is 'code.c' and it runs with an error of not passing the argument (filename). But if the filename is passed, we land in Segmentation Fault.
Any help/suggestions will be appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
struct _data
{
char *firstName;
char *lastName;
long number;
};
// SCAN FILE
int SCAN(FILE *(*stream))
{
*stream = fopen("inputFile.data", "r");
int ch = 0, lines = 0;
while (!feof(*stream))
{
ch = fgetc(*stream);
if (ch == '\n')
{
lines++;
}
}
return lines;
}
// LOAD FILE
struct _data *LOAD(FILE *stream, int size)
{
int i;
size_t chrCount;
char *text, *number, *firstName, *lastName;
struct _data *BlackBox;
if ((BlackBox = (struct _data*)calloc(size, sizeof(struct _data))) == NULL)
{
printf("ERROR - Could not allocate memory.\n");
exit(0);
}
rewind(stream);
for (i = 0; i < size; i++)
{
getline(&text, &chrCount, stream);
firstName = strtok(text, " ");
lastName = strtok(text, " ");
number = strtok(NULL, "\n");
// Allocate memory for name part of struct.
if ((BlackBox[i].firstName = (char*)calloc(strlen(firstName), sizeof(char))) == NULL)
{
printf("ERROR - Could not allocate memory.\n");
exit(0);
}
if ((BlackBox[i].lastName = (char*)calloc(strlen(lastName), sizeof(char))) == NULL)
{
printf("ERROR - Could not allocate memory.\n");
exit(0);
}
strcpy(BlackBox[i].firstName, firstName);
strcpy(BlackBox[i].lastName, lastName);
BlackBox[i].number = atol(number);
}
fclose(stream);
return BlackBox;
}
void SEARCH(struct _data *BlackBox, char *name, int size, int inputs)
{
int i;
int found = 0;
char *search = " ";
char *firstName;
char *lastName;
if (inputs == 2)
{
firstName = strtok(name, search);
lastName = strtok(NULL, search);
}
printf("*******************************************\n");
if (inputs == 2)
{
for (i = 0; i < size; i++)
{
if (!strcasecmp(firstName, BlackBox[i].firstName) && !strcasecmp(firstName, BlackBox[i].firstName))
{
printf("The name was found at the %d entry.\n", i);
found = 1;
break;
}
}
}
else
{
for (i = 0; i < size; i++)
{
if (!strcasecmp(firstName, BlackBox[i].firstName) || !strcasecmp(firstName, BlackBox[i].firstName))
{
printf("The name was found at the %d entry.\n", i);
found = 1;
break;
}
}
}
if (found == 0)
{
printf("The name was NOT found.\n");
}
printf("*******************************************\n");
}
// FREE MEMORY
void FREE(struct _data *BlackBox, int size)
{
int i;
for (i = 0; i < size; i++)
{
free(BlackBox[i].firstName);
free(BlackBox[i].lastName);
}
free(BlackBox);
BlackBox = NULL;
}
// MAIN
int main(int argv, char **argc)
{
int size;
FILE *stream;
struct _data *BlackBox;
// argv == 1 WORKS, Below message is printed.
if (argv == 1)
{
printf("*******************************************\n");
printf("* You must include a name to search for. *\n");
printf("*******************************************\n");
}
// argv == 2 DOES NOT WORK, Segmentation Fault.
if (argv == 2)
{
size = SCAN (&stream);
BlackBox = LOAD(stream, size);
SEARCH(BlackBox, argc[1], size, 1);
}
if (argv == 3)
{
size = SCAN(&stream);
BlackBox = LOAD(stream, size);
SEARCH(BlackBox, argc[2], size, 2);
}
return 0;
}
You have a problem in this code:
firstName = strtok(text, " ");
lastName = strtok(text, " ");
number = strtok(NULL, "\n");
...
BlackBox[i].number = atol(number);
The second strtok() call should pass NULL as its first argument. As it is, the third strtok() call is certain to return NULL because the first call modifies text in such a way that the second consumes the whole thing (when tokenizing again from the beginning, as it erroneously does). You do not test for that, however, and as a result, atol() attempts to dereference a null pointer.
Update:
Additionally, as #chqrlie and later #JamesWilkins observed, you do not allocate sufficient space for BlackBox[i].firstName and BlackBox[i].lastName, as you need room for the string terminators as well. This is an entirely separate problem that could also produce a segfault. I like #chqrlie's suggestion to switch to strdup(), but it would be sufficient to just increase each allocation by one unit.
Update 2:
Furthermore, you have an issue with this line:
getline(&text, &chrCount, stream);
You do not initialize variable text before the first call, so it contains a junk value. The function allocates a buffer only when its first argument points to a NULL pointer; otherwise it writes the line to the buffer pointed to by the pointer obtained by dereferencing the first argument. Writing to a random location in memory certainly produces undefined behavior, which in practice often manifests as a segfault.
Moreover, unless you can rely on no line of the file being longer than the first, you also need to free the text pointer at the end of each loop iteration AND reset its value to NULL, so that getline() allocates a fresh buffer on the next iteration. If you do not free it on each iteration, then you need instead to free it after the end of the loop; else you will leak memory.
Try this (though I'm using Visual Studio on Windows). I added code to check for a missing '\n' on the last line, and also allowed for a variable number of search terms. I also increased the memory allocation for strings by 1 to account for the null terminating character. I noticed you are using getline(const char*..., which I think is GNU (Linux?), so I change that to fgets() just so I could compile and test it in VS (so you can change it back if you like). I put in various null checks as well, to be safer.
#include <iostream>
using namespace std;
struct _data
{
char *firstName;
char *lastName;
long number;
};
// SCAN FILE
int SCAN(FILE *(*stream))
{
*stream = fopen("inputFile.data", "r");
if (*stream == NULL)
{
perror("Error opening file");
return 0;
}
char ch = 0, lines = 0, linesize = 0;
while ((ch = fgetc(*stream)) != EOF)
{
if (ch == '\n')
{
lines++;
linesize = 0;
}
else linesize++;
}
if (linesize > 0)
lines++; // (last line doesn't have '\n')
return lines;
}
// LOAD FILE
struct _data *LOAD(FILE *stream, int lineCount)
{
int i;
size_t chrCount = 256;
char text[256], *result, *number, *firstName, *lastName;
struct _data *BlackBox;
if ((BlackBox = (struct _data*)calloc(lineCount, sizeof(struct _data))) == NULL)
{
printf("ERROR - Could not allocate memory.\n");
exit(0);
}
else memset(BlackBox, 0, sizeof(struct _data) * lineCount); // (make sure all data members are null to begin)
rewind(stream);
for (i = 0; i < lineCount; i++)
{
result = fgets(text, chrCount, stream);
if (result == NULL)
break; // (EOF)
firstName = strtok(text, " ");
lastName = strtok(NULL, " ");
number = strtok(NULL, "\n");
// Allocate memory for name part of struct.
if ((BlackBox[i].firstName = (char*)calloc(strlen(firstName) + 1, sizeof(char))) == NULL)
{
printf("ERROR - Could not allocate memory.\n");
exit(0);
}
if ((BlackBox[i].lastName = (char*)calloc(strlen(lastName) + 1, sizeof(char))) == NULL)
{
printf("ERROR - Could not allocate memory.\n");
exit(0);
}
strcpy(BlackBox[i].firstName, firstName);
strcpy(BlackBox[i].lastName, lastName);
BlackBox[i].number = atol(number);
}
fclose(stream);
return BlackBox;
}
void SEARCH(struct _data *BlackBox, char **names, int lineCount, int inputs)
{
int i, l;
int found = 0;
printf("*******************************************\n");
for (i = 0; i < inputs; ++i)
{
for (l = 0; l < lineCount; ++l)
{
if (BlackBox[l].firstName != NULL && !_stricmp(names[i], BlackBox[l].firstName)
|| BlackBox[l].lastName != NULL && !_stricmp(names[i], BlackBox[l].lastName))
{
printf("The name was found on line %d.\n", 1 + l);
found = 1;
break;
}
}
if (found) break;
}
if (!found)
printf("The name was NOT found.\n");
printf("*******************************************\n");
}
// FREE MEMORY
void FREE(struct _data *BlackBox, int lineCount)
{
int i;
for (i = 0; i < lineCount; i++)
{
if (BlackBox[i].firstName != NULL)
free(BlackBox[i].firstName);
if (BlackBox[i].lastName != NULL)
free(BlackBox[i].lastName);
}
free(BlackBox);
}
// MAIN
int main(int argc, char **argv)
{
int lineCount;
FILE *stream;
struct _data *BlackBox;
// argc == 1 WORKS, Below message is printed.
if (argc == 1)
{
printf("*******************************************\n");
printf("* You must include a name to search for. *\n");
printf("*******************************************\n");
}
// argc == 2 DOES NOT WORK, Segmentation Fault.
if (argc > 1)
{
lineCount = SCAN(&stream);
if (lineCount > 0)
{
BlackBox = LOAD(stream, lineCount);
SEARCH(BlackBox, argv + 1, lineCount, argc - 1);
FREE(BlackBox, lineCount);
}
}
return 0;
}
Tested it on the command line, and it works.
The problem is the argv and argc. argc is supposed to be an int (think argument count), while argv is meant to be char**. You have them mixed up in your main.
I have a code that scans all the files in a directory for targeted words, and prints them out into a new file. The problem right now is after the while loop reads a file and stores a variable into the string (ex. customer), if the next file being read does not have the targeted word, it still displays the result stored in the string from the previous file. My goal is to make it display "N/A" if the current file does not have the target word.
I have tried a few ways to clear the string at the end or beginning of the while loop, but none of them work most of them just gives me a coredump error. Running out of ideas, any help would be much appreciated!
Code (shortened for easier reading):
int main(int argc, char** argv)
{
char directory[100];
char buff[100];
char delims[] = " :=";
char* result = NULL;
char* customer;
char* device;
char* buffer;
int i = 0;
DIR* FD;
struct dirent* in_file;
int c = 0;
printf("Enter directory:");
scanf("%s",directory);
FILE* ft = fopen("workorderlist.csv", "w"); /* Open file to write to*/
if (ft == NULL)
{
puts("Cannot open target file");
exit(1);
}
fprintf (ft, "Work Order,Customer,Device,Test_Prog,Software,DUT_board_id,Corl box\n");
/* Open Directory */
if (NULL == (FD = opendir(directory)))
{
puts("Cannot open directory");
return 1;
}
while ((in_file = readdir(FD)))
{
if (!strcmp (in_file->d_name, "."))
{
continue;
}
if (!strcmp (in_file->d_name, ".."))
{
continue;
}
/* Open files to read from */
buffer = (char*)malloc(100);
sprintf(buffer, "%s/%s", directory, in_file->d_name);
size_t len = strlen(buffer);
if (len >= 4 && memcmp(buffer + len - 4, ".wor", 4) == 0) /* checks if file ends with .wor */
{
FILE* fs = fopen(buffer, "r"); /* open file to read */
if (fs == NULL)
{
puts("Cannot open source file");
return 1;
}
/* Scanning each file for targeted words: */
while (fgets(buff, 100, fs) != NULL)
{
result = strtok( buff, delims );
while (result != NULL)
{
if ((strcmp(result, "Customer") == 0))
{
result = strtok(NULL,delims);
customer = (char*)malloc((strlen(result)+1)*sizeof(char));
strcpy(customer, result);
for (i = 0; i < strlen(customer) + 1; i++)
{
if (customer[i] == '\n')
{
break;
}
}
customer[i] = ' ';
}
if (strcmp(result, "device") == 0)
{
result = strtok(NULL, delims);
device = (char*)malloc((strlen(result) + 1) * sizeof(char));
strcpy(device, result);
for (i = 0; i < strlen(device) + 1; i++)
{
if(device[i] == '\n')
{
break;
}
}
device[i] = ' ';
}
result = strtok(NULL,delims);
}
}
if (customer == '\0')
{
customer = "N/A";
}
if (device == '\0')
{
device = "N/A";
}
fprintf(ft, "%s,%s,%s,%s,%s,%s,%s\n",
in_file->d_name, customer, device, testprog,
software, dutboardid, corlbox);
printf(in_file->d_name);
printf("\n");
fclose (fs) ;
c++;
}
}
printf("Total Workorders Found: %d (Info saved to workorderlist.csv)\n", c);
fclose(ft);
return 0;
}
First at all, customer/device are strings. You should not be doing == for it comparison. You can, for example, compare the first char of the string: device[0] == '\0';
You should do string initialization before the loop starts.
You can achieve this by using strcpy with a known value or any other string manipulation function. The value that you use to initialize the string before the loop is the one you gonna test with strcmp or similar later.
Is like with ints or any other C data type, but you need manipulation functions instead.
By the way, haven't you posted your read file loop in a question here too?
Hope this helps.
After a long time I'm playing with dynamic memory allocation in C and I'm encountering some issues with memory leaks ... I just can't see where the problem might be. Can Anyone help please?
EDIT2:
The program now works fine even with very large numbers and is quite quick :) I decided to change the program structure and used struct instead of just char string. There should not be any memory leaks (tested with valgrind).
Current code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct binary{
char * number;
size_t length;
}Tbinary;
//exterminate leading zeros
size_t exterminate(char * bin, size_t length){
char * pch = NULL;
long position = 0;
pch = strchr(bin, '1');
if(pch==NULL){
bin[1] = '\0';
length = 2;
}
else{
position = pch-bin;
strcpy(bin, pch);
}
return (length-position);
}
int binaryAdd(Tbinary first, Tbinary second){
int a=0, b=0, sum=0, carry=0;
size_t index = first.length;
first.number[first.length] = '\0';
while((first.length != 0) || (carry != 0)){
if(first.length>1) a= first.number[first.length-2]-'0';
else a = 0;
if(second.length>1) b= second.number[second.length-2]-'0';
else b = 0;
sum = (a+b+carry)%2;
first.number[first.length-1] = (sum)+'0';
carry = (a+b+carry)/2;
if(first.length >0)first.length--;
if(second.length >0)second.length--;
}
exterminate(first.number,index);
printf("Sum: %s\n", first.number);
return EXIT_SUCCESS;
}
int get_number(Tbinary *bin_addr){
char * tmp, * bin;
char ch=1;
int size = 1, index = 0;
bin = bin_addr->number;
while(ch){
ch = getc(stdin);
if((ch == '\n') || (ch == ' ')) ch = '\0';
if((ch-'0' != 0) && (ch-'0' != 1) && (ch != '\0')) return EXIT_FAILURE;
if (size-1 <=index){
size += 5;
tmp = (char *)realloc(bin, size*sizeof(char));
if(tmp == NULL){
return EXIT_FAILURE;
}
bin = tmp;
bin_addr->number = bin;
}
bin[index++] = ch;
}
bin_addr->length = index;
bin_addr->length = exterminate(bin_addr->number, bin_addr->length);
return EXIT_SUCCESS;
}
int main (void)
{
Tbinary bin1 = {bin1.number = NULL, bin1.length = 0};
Tbinary bin2 = {bin2.number = NULL, bin2.length = 0};
//allocate space for first number
bin1.number = (char *)malloc(sizeof(char));
if(bin1.number == NULL)
return EXIT_FAILURE;
//allocate space for second number
bin2.number = (char *)malloc(sizeof(char));
if(bin2.number == NULL){
free(bin1.number);
return EXIT_FAILURE;
}
printf("Enter two binary numbers:\n");
//number1 load
if(get_number(&bin1) != EXIT_SUCCESS){
free(bin1.number);
free(bin2.number);
printf("Invalid input.\n");
return EXIT_FAILURE;
}
//number2 load
if(get_number(&bin2) != EXIT_SUCCESS){
free(bin1.number);
free(bin2.number);
printf("Invalid input.\n");
return EXIT_FAILURE;
}
//add the two numbers
if(bin1.length >= bin2.length){
if(binaryAdd(bin1, bin2) != EXIT_SUCCESS){
free(bin1.number);
free(bin2.number);
printf("Invalid input.\n");
return EXIT_FAILURE;
}
}
else{
if(binaryAdd(bin2, bin1) != EXIT_SUCCESS){
free(bin1.number);
free(bin2.number);
printf("Invalid input.\n");
return EXIT_FAILURE;
}
}
free(bin1.number);
free(bin2.number);
return EXIT_SUCCESS;
}
In binaryAdd() you should free sum after realloc() in all cases, not just when realloc() returns null. Same thing in get_number().
About a = (int)strlen(first); why cast the return of strlen() into an int?
Also, don't cast the return of allocation functions.
You have an off-by-one error in your size and index relationship:
if (size <=index){
size += 5;
tmp = (char *)realloc(sum, size*sizeof(char));
if(tmp == NULL){
free(sum); // free memory to avoid leak
return EXIT_FAILURE;
}
sum = tmp;
}
for(int i=index; i>0; i--){
sum[i] = sum[i-1];
}
sum[0] = num%2+'0';
carry = num/2;
index++;
}
sum[index] = '\0';
If, on entering the last iteration, index == size-1, you are writing outside the allocated memory. Sometimes that can be harmless, for others you may overwrite some important data without causing an immediate crash, and sometimes it can cause an immediate crash (when the out-of-bounds access crosses a page boundary, usually). Change the test to size - 1 <= index.
In get_number, if you need to realloc, you only change the local copy of the char* to the input buffer, so if the location changes, the pointer in main points to invalid memory. It should be
int get_number(char **bin_addr){
char * tmp, bin = *bin_addr;
char ch=1;
size_t size = 1, index = 0;
while(ch){
ch = getc(stdin);
if((ch == '\n') || (ch == ' ')){
ch = '\0';
}
if((ch-'0' != 0) && (ch-'0' != 1) && (ch != '\0')){
return EXIT_FAILURE;
}
if (size-1 <=index){
size += 5;
tmp = (char *)realloc(bin, size*sizeof(char));
if(tmp == NULL){
return EXIT_FAILURE;
}
bin = tmp;
*bin_addr = bin; // let the pointer always point to the real block
}
bin[index++] = ch;
}
return EXIT_SUCCESS;
}
and be called get_number(&bin1); in main.
I need to write a program to read from a file, then save the words into a linked list for further use. I decided to read the text character by character using fgetc, then save all into the list each time a newline ('\n') or space (' ') is detected, indicating one word.
Sorry I'm a newbie in file pointers, this is what I've gotten so far:
struct list { //global
char string[30];
struct list *next;
};
int main(void) {
FILE *filePtr;
char file[] = "text.txt";
char tempStr[30];
list *curr, *header;
char c;
int i = 0;
curr = NULL;
header = NULL;
if((filePtr = fopen(file, "r")) == NULL) {
printf("\nError opening file!");
getchar();
exit(101);
}
printf("\nFile is opened for reading.\n");
while(!EOF) {
while((c = fgetc(filePtr) != ' ') && (c = fgetc(filePtr) != '\n')) {
curr = (list*)malloc(sizeof(list));
//c = fgetc(filePtr);
tempStr[i] = fgetc(filePtr);
i++;
}
tempStr[i] = '\0';
strcpy(curr->string, tempStr);
curr->next = header;
header = curr;
i = 0;
}
while(curr!=NULL) {
printf("%s - ", curr->string); //This will not print.
curr = curr->next;
}
if(fclose(filePtr) == EOF) {
printf("\nError closing file!");
getchar();
exit(102);
}
printf("\nFile is closed.\n");
getchar();
getchar();
}
If the text file:
have a nice day
Desired output:
have - a - nice - day
But, I could not print out anything except the file opened and closed.
Thanks.
Value of the macro EOF is -1, which is a system macro defined in stdio.h. File read APIs(fgetc, fread, fscanf) will return -1 once it reaches end of file. So in your program you have while(!EOF) this will be always false, because NOT of -1 is always 0. -1 will be represented in 2's complement so all bits of that variable will be 1. (If size of int is 2, -1 will be stored as 0xFFFF in int variable).
Use the below sample code.
while(EOF != (c = fgetc(filePtr)))
{
if ((c == ' ') || (c == '\n'))
{
if (i == 0)
{
continue;
}
tempStr[i] = '\0';
i = 0;
//here do your linklist node creation and insertion operation
continue;
}
tempStr[i] = c;
i++;
}
while(!EOF) {
This is a constant condition that is always false, so you never read anything.
Your code also has other problems, such as doing
curr = (list*)malloc(sizeof(list));
in a loop but using curr outside the loop.
You should replace the while condition with whatever function you're using to read the file - are you sure fgets isn't horrendously more efficient than this?
IE read the string into a much larger buffer than you expect, then copy it into an appropriately sized buffer and attach that to the node.
This is always false:
while(!EOF)
Review your memory allocation code.
curr = (list*)malloc(sizeof(list))
Files may not have newlines at the end of the file.
while((c = fgetc(filePtr) != ' ') && (c = fgetc(filePtr) != '\n'))
Spoiler:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct list {
struct list *next;
char string[30];
};
int main(void) {
FILE *fp;
char file[] = "llist4.c";
/* in C you CANNOT omit the "struct keyword" from a declaration or definition. */
struct list *head=NULL, **pp= &head;
int ch; /* getc() returns an int */
size_t len ;
char buff[30];
fp = fopen(file, "r");
if (!fp) {
fprintf(stderr, "\nError opening file!");
exit(EXIT_FAILURE);
}
printf("\nFile has been opened for reading.\n");
for (len=0; len < sizeof buff; ) {
ch = fgetc(fp);
if (ch == EOF && !len) break;
if (ch == ' ' || ch == '\n' || ch == EOF) {
if (!len) continue;
buff[len] = '\0';
*pp = malloc(sizeof **pp);
if (!*pp) break;
strcpy((*pp)->string, buff);
(*pp)->next = NULL;
pp = &(*pp)->next ;
len=0; continue;
}
buff[len++] = ch;
}
if (len) {
fprintf(stderr, "\nWord was too large, or out of memory\n");
}
for( ;head; head= head->next) {
printf("%s - ", head->string);
}
if (fclose(fp) == EOF) {
fprintf(stderr, "\nError closing file!\n");
exit(EXIT_FAILURE);
}
printf("\nFile has been closed.\n");
exit(EXIT_SUCCESS);
}