Why this #define processor act strange when it meets an #include? - c

I wrote a simple version of #define processor for the exercise in K&R's C Book.(Exercise 6.3). It is very simple and works fine for simple inputs.
But If it meets an #include line it breaks. It doesn't replace any name with the replacement text. It just prints the exact input.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define MAXWORD 100
#define SUCCESS 0
struct nlist {
struct nlist *next;
char *name;
char *defn;
};
struct nlist *lookup(char *);
struct nlist *install(char *, char *);
int getword(char *, int);
int gettoken(char *, int);
int nl = 0;
int main()
{
char word[MAXWORD], key[MAXWORD], value[MAXWORD], token[MAXWORD];
struct nlist *res, *rres;
FILE *fp = fopen("out", "w");
res = NULL;
while (getword(word, MAXWORD) != EOF) {
fprintf(fp, "%s_", word);
if (strcmp(word, "#define") == 0) {
getword(key, MAXWORD);
getword(value, MAXWORD);
install(key, value);
printf("%s %s %s\n", word, key, value);
} else if (strcmp(word, "#include") == 0) {
printf("%s ", word);
gettoken(word, MAXWORD);
printf("%s\n", word);
} else if ((res = lookup(word)) != NULL) {
printf("%s ", res->defn);
} else {
printf("%s ", word);
if (!strcmp(word, ";")) printf("\n");
else if (!strcmp(word, "{")) printf("\n");
else if (!strcmp(word, "}")) printf("\n");
}
}
return SUCCESS;
}
#define HASHSIZE 101
struct nlist *hashtab[HASHSIZE];
unsigned hash(char *s)
{
unsigned hashval;
for (hashval = 0; *s != '\0'; s++)
hashval = *s + 31 * hashval;
return hashval % HASHSIZE;
}
struct nlist *lookup(char *s)
{
struct nlist *np;
for (np = hashtab[hash(s)]; np != NULL; np = np->next)
if (strcmp(s, np->name) == 0)
return np;
return NULL;
}
struct nlist *install(char *name, char *defn)
{
struct nlist *np;
unsigned hashval;
char *mstrdup(char *);
if ((np = lookup(name)) == NULL) {
np = (struct nlist *) malloc(sizeof (*np));
if (np == NULL || (np->name = mstrdup(name)) == NULL)
return NULL;
hashval = hash(name);
np->next = hashtab[hashval];
hashtab[hashval] = np;
} else
free((void *) np->defn);
if ((np->defn = mstrdup(defn)) == NULL)
return NULL;
return np;
}
char *mstrdup(char *s)
{
char *p = malloc(strlen(s) + 1);
if (p != NULL)
strcpy(p, s);
return p;
}
int getch(void);
void ungetch(int);
int getword(char *word, int lim)
{
int c;
char *w = word;
while (isspace(c = getch()))
;
if (c != EOF)
*w++ = c;
if (!isalnum(c) && c != '#') {
*w = '\0';
return c;
}
for ( ; --lim > 0; w++) {
*w = getch();
if (!isalnum(*w) && *w != '_') {
if (*w != '\n')
ungetch(*w);
break;
}
}
if (*w == '\n')
nl = 1;
*w = '\0';
return word[0];
}
int gettoken(char *token, int lim)
{
int c;
char *t = token;
while (isspace(c = getch()))
;
if (c == '<') {
*t++ = c;
for ( ; --lim > 0 && *t != '>'; )
*t++ = getch();
*t = '\0';
return token[0];
} else if (c == '\"') {
*t++ = c;
for ( ; --lim > 0 && *t != '\"'; )
*t++ = getch();
*t = '\0';
return token[0];
} else {
strcpy(t, "Invalid token.");
return 0;
}
}
#define BUFF 100
char buff[BUFF];
char *bufp = buff;
int getch(void)
{
return (bufp > buff) ? *--bufp : getchar();
}
void ungetch(int c)
{
if (bufp < buff + BUFF)
*bufp++ = c;
else
bufp = buff;
}
I'm going to input this file: d.txt
#define MAX 100
#define MIN 0
int main() {
int i = MAX;
printf("%d %d", i, MIN);
return MIN;
}
and the output is :
$ ./defp < d.txt
#define MAX 100
#define MIN 0
int main ( ) {
int i = 100 ;
printf ( " % d % d " , i , 0 ) ; // notice the space between % and d It means that those characters was processed.
return 0 ;
}
but when input contains an #include <stdio.h> output is:
$ ./defp < d.txt
#define MAX 100
#define MIN 0
#include <stdio.h>
int main() {
int i = MAX;
printf("%d %d", i, MIN); // notice that there are no spaces just the exact input means that the line wasn't proccessed.
return MIN;
}
Why is It acting like this, I don't have any idea, Please give me an explanation?

As said in the comments, your next task is to learn how to use a debugger.
Hint: the error is in:
*t++ = getch();

Related

Get_next_line : Abort when BUFFER_SIZE between 8 and 15 on Mac

I am currently completing my "Get_next_line" project. It is a function that reads a file and allows you to read a line ending with a newline character from a file descriptor. When you call the function again on the same file, it grabs the next line. This project deals with memory allocation and when to free and allocate memory to prevent leaks. The value (-1) is returned if an error occurred, (0) is returned if the file is finished reading, and (1) is returned if a line is read.
However, while testing my final code I encounter an abort when BUFFER_SIZE is between 8 and 15. This error only appears on Mac. Does anyone have an idea of what might be the issue?
Compile with :
gcc -Wall -Wextra -Werror -D BUFFER_SIZE=32 get_next_line.c get_next_line_utils.c
The get_next_line() function and some support code;
#include "get_next_line.h"
int ft_backslash(const char *s)
{
int i;
i = -1;
while (s[++i])
if (s[i] == '\n')
return (1);
if (s[i] == '\n')
return (1);
return (0);
}
int ft_read_buffer(int fd, char *buf)
{
int ret;
ret = 0;
ret = read(fd, buf, BUFFER_SIZE);
if (ret < 0)
return (-1);
buf[ret] = '\0';
return (ret);
}
char *ft_treat_save(char *save, char *buf)
{
char *tmp;
if (save == NULL)
save = ft_strdup(buf);
else
{
tmp = ft_strdup(save);
free (save);
save = ft_strjoin(tmp, buf);
free (tmp);
}
return (save);
}
char *ft_treat_tmp(char *save)
{
char *tmp;
tmp = ft_strdup(save);
free (save);
return (tmp);
}
int get_next_line(int fd, char **line)
{
int ret;
char buf[BUFFER_SIZE];
char *tmp;
static char *save;
ret = 1;
if (fd < 0 || fd > 255 || BUFFER_SIZE <= 0 || line == NULL)
return (-1);
*line = NULL;
tmp = NULL;
while (ret > 0)
{
if ((ret = ft_read_buffer(fd, buf)) < 0)
return (-1);
save = ft_treat_save(save, buf);
if (ft_backslash(save) == 1)
{
tmp = ft_treat_tmp(save);
*line = ft_strcut_front(tmp);
save = ft_strcut_back(tmp);
return (1);
}
}
tmp = ft_treat_tmp(save);
save = NULL;
*line = ft_strdup(tmp);
free (tmp);
return (0);
}
Other support code:
size_t ft_strlen(char *str)
{
size_t i;
i = 0;
if (str)
while (str[i])
i++;
return (i);
}
char *ft_strdup(char *str)
{
int i;
char *dst;
dst = malloc(sizeof(char) * ((ft_strlen(str) + 1)));
if (!(dst))
{
free (dst);
return (NULL);
}
i = -1;
while (str[++i])
dst[i] = str[i];
dst[i] = '\0';
return (dst);
}
char *ft_strjoin(char *s1, char *s2)
{
int i;
int j;
char *join;
i = -1;
j = 0;
if (!s1 && !s2)
return (NULL);
join = malloc(sizeof(char) * (ft_strlen(s1) + ft_strlen(s2) + 2));
if (!(join))
return (NULL);
if (BUFFER_SIZE == 1)
while (s1[++i + 1] != '\0')
join[i] = s1[i];
else
while (s1[++i] != '\0')
join[i] = s1[i];
while (s2[j])
join[i++] = s2[j++];
join[i] = '\0';
return (join);
}
char *ft_strcut_front(char *str)
{
int i;
char *front;
i = 0;
while (str[i] != '\n')
i++;
front = malloc(sizeof(char) * (i + 1));
if (!(front))
return (NULL);
i = 0;
while (str[i] != '\n')
{
front[i] = str[i];
i++;
}
front[i] = '\0';
return (front);
}
char *ft_strcut_back(char *str)
{
int i;
int j;
char *back;
i = 0;
while (str[i] != '\n')
i++;
i++;
back = malloc(sizeof(char) * ((ft_strlen(str) - i) + 1));
if (!(back))
return (NULL);
j = 0;
while (str[i] != '\0')
back[j++] = str[i++];
back[j] = '\0';
free (str);
return (back);
}
The main() function:
int main(void)
{
int fd, ret, line_count;
char *line;
line_count = 1;
ret = 0;
line = NULL;
fd = open("baudelaire.txt", O_RDONLY);
while ((ret = get_next_line(fd, &line)) > 0)
{
printf(" \n [ Return: %d ] | A line has been read #%d => |%s|\n", ret, line_count, line);
line_count++;
}
printf(" \n [ Return: %d ] A line has been read #%d: |%s\n", ret, line_count++, line);
printf("\n");
if (ret == -1)
printf("-----------\n An error happened\n");
else if (ret == 0)
{
printf("-----------\n EOF has been reached\n");
}
close(fd);
}
Problem solved. I forgot to add + 1 to my buf size... stupid error ! Thank you

program that reads a text file and stores in each line in into a char*[] [duplicate]

This question already has answers here:
C read file line by line
(17 answers)
Closed 5 years ago.
I am new to c programming. I'm writing a program that reads a text file and stores in each line in into a char*[] data structures. I know how to this with characters, but I don't know how to store each line? does it require a 2D array? thats the code I have but I get segmentation error. I'm just trying to print out I and j to check if it works.
Thank you
#include <stdio.h>
#define NUMBER_LINES 400
int main()
{
char lines[NUMBER_LINES][255];
FILE *fp = fopen("input.txt", "r");
if (fp == 0)
{
return 1;
}
char c;
int i ;
while (fscanf (fp, "%c", &c) == 1)
{
i = 0;
int j;
for (j=0; !(c=='\n'); j++){
lines[i][j] = c;
}
if (c == '\n'){
printf("%s%s\n", lines[i][j]);
i++;
}
}
return 0;
}
You could use a matrix:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMBER_LINES 100
int main(void)
{
int i = 0;
char lines[NUMBER_LINES][255];
FILE *fp = fopen("file.txt", "r");
if (fp == 0)
{
fprintf(stderr, "failed to open input.txt\n");
exit(1);
}
while (i < NUMBER_LINES && fgets(lines[i], sizeof(lines[0]), fp))
{
lines[i][strlen(lines[i])-1] = '\0';
printf("\n%s", lines[i]);
i = i + 1;
}
fclose(fp);
return 0;
}
The code :
#include "get_next_line.h"
int check_n(char *str)
{
int i;
i = 0;
while (str && str[i])
{
if (str[i] == '\n')
return (i);
i++;
}
return (-1);
}
char *my_strdup_gnl(char *src)
{
int i;
char *str;
int ret;
i = 0;
if ((ret = check_n(src)) == -1)
return (NULL);
if ((str = malloc(sizeof(char) * ret + 1)) == NULL)
return (NULL);
while (i < ret)
{
str[i] = src[i];
i++;
}
str[i] = '\0';
return (str);
}
char *boucle_gnl(char *line, char *buff, int ret, int i)
{
strcat(line, buff);
i = 0;
while (buff[ret + 1] != '\0')
{
buff[i] = buff[ret + 1];
i++;
ret++;
}
buff[ret] = 0;
while (i < READ_SIZE + 1)
{
buff[i] = '\0';
i++;
}
return (line);
}
char *boucle_else_gnl(char *line, char *buff, int ret, int fd)
{
int i;
i = 0;
line = =strcpy(line, buff);
while (i < READ_SIZE + 1)
{
buff[i] = '\0';
i++;
}
if ((ret = read(fd, buff, READ_SIZE)) <= 0)
return (NULL);
return (line);
}
char *get_next_line(const int fd)
{
static char buff[READ_SIZE + 1] = {'\0'};
char *line;
int ret;
int i;
int tmp;
i = 0;
tmp = 0;
line = NULL;
if (!buff[0] && (ret = read(fd, buff, READ_SIZE)) <= 0)
return (NULL);
while (tmp++ != -1)
{
if ((line = my_realloc(line, (tmp * READ_SIZE))) == NULL)
return (NULL);
if ((ret = check_n(buff)) != -1)
return (line = boucle_gnl(line, buff, ret, i), line);
else
{
if ((line = boucle_else_gnl(line, buff, ret, fd)) == NULL)
return (NULL);
}
}
return (NULL);
}
The "my_realloc function" :
char *my_realloc(char *buff, int nb)
{
char *buf2;
int i;
i = 0;
if ((buf2 = malloc(sizeof(char) * (strlen(buff) + nb + 1))) == NULL)
return (NULL);
if (buff == NULL)
{
buf2[0] = '\0';
return (buf2);
}
while (buff[i])
{
buf2[i] = buff[i];
i++;
}
buf2[i] = '\0';
return (buf2);
}
The "get_next_line.h" :
#ifndef GET_NEXT_LINE_H_
# define GET_NEXT_LINE_H_
#ifndef READ_SIZE
# define READ_SIZE 10000
#include <unistd.h>
#include <stdlib.h>
#endif /* !READ_SIZE */
#endif /* !GET_NEXT_LINE_H_ */

Segmentation Fault issue in binary search tree

I have to create a binary search tree for an assignment that sorts strings. I ran debug mode and found where the issue for the segmentation fault is but I have no idea what the issue is or how to fix it. I get
#0 0x0000000000400969 in Insert (node=0x7fffffffe008, data=0x7fffffffe010 "run\n", c_flag=0) at testbst.c:38
#1 0x0000000000400df8 in main (argc=1, argv=0x7fffffffe188) at testbst.c:156"
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
typedef struct treeNode
{
char *data;
int count;
struct treeNode *left;
struct treeNode *right;
} treeNode;
void Insert(treeNode** node,char* data,int c_flag)
{
if(node==NULL)
{
treeNode *temp;
temp = (treeNode *)malloc(sizeof(treeNode));
temp -> data = data;
printf("%sdata", data);
printf("\n%stemp", temp -> data);
temp -> left = NULL;
temp -> right = NULL;
*node = temp;
return;
}
if(c_flag == 1)
{
if(caseCompare((*node)->data, data) == 1)
Insert(&(*node)->left, data, c_flag);
if(caseCompare((*node)->data, data) == -1)
Insert(&(*node)->right, data, c_flag);
else
(*node)->count++;
}
else if(compare((*node)->data, data) == 1)
Insert(&(*node)->left, data, c_flag);
if(compare((*node)->data, data) == -1)
Insert(&(*node)->right, data, c_flag);
else
(*node)->count++;
}
void PrintInorder(treeNode *node)
{
if(node==NULL)
{
return;
}
PrintInorder(node->left);
printf("%d ",node->data);
PrintInorder(node->right);
}
void DeletePostorder(treeNode *node)
{
if(node != NULL)
{
DeletePostorder(node->left);
DeletePostorder(node->right);
if(node->left!=NULL)
free(node->left);
if(node->right != NULL)
free(node->right);
free(node);
}
}
int compare(char* string1, char* string2)
{
int str1 = strlen(string1);
int str2 = strlen(string2);
int bigger;
int i = 0;
if(str1 > str2)
bigger = str1;
if(str1 < str2)
bigger = str2;
for(i = 0; i < bigger; i++)
{
if(tolower(string1[i]) > tolower(string1[i]))
return 1; //returns 1 if string 1 is farther letter
if(tolower(string1[i]) < tolower(string2[i]))
return -1; //returns -1 if string 1 letter is behind
}
return 0; //returns 0 if same words
}
int caseCompare(char* string1, char* string2)
{
int str1 = strlen(string1);
int str2 = strlen(string2);
int bigger;
int i = 0;
if(str1 > str2)
bigger = str1;
if(str1 < str2)
bigger = str2;
for(i = 0; i < bigger; i++)
{
if(string1[i] > string1[i])
return 1; //returns 1 if string 1 is farther letter
if(string1[i] < string2[i])
return -1; //returns -1 if string 1 letter is behind
}
return 0; //returns 0 if same words
}
int main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
FILE* infile = stdin;
FILE* outfile = stdout;
char string[100];
treeNode* tree = NULL;
int cflag = 0, oflag = 0, c, err;
static char usage[] = "usage: %s [-c] [-o output_file_name] [input_file_filename]\n";
while ((c = getopt(argc, argv, "co:")) != -1)
switch (c)
{
case 'c':
cflag = 1;
break;
case 'o':
oflag = 1;
outfile = fopen(optarg, "w");
break;
case '?':
err = 1;
printf("%s\n", usage);
break;
}
if((argc - optind) > 1)
{
printf("Input Incorrect \n%s\n", usage);
exit(0);
}
if(argv[optind] != NULL)
if((infile = fopen(argv[optind], "r")) == NULL)
{
printf("File \"%s\" does not exist\nType in your sentences\n", argv[optind]);
infile = stdin;
}
while(fgets(string, sizeof(string), infile) != NULL && string[0] != '\n')
{
printf("%s", string);
Insert(&tree, string, cflag);
}
PrintInorder(tree);
DeletePostOrder(tree);
}

Segmentation fault loading dictionary into trie tree

I'm making a program that reads a given dictionary into a trie tree, and then
performs auto complete on a string inputted by the user. When I use the dictionary file that I am required to use (~100,000 words) I get a segmentation fault. I can't seem to figure out what is causing the segmentation fault. Any help would be appreciated.
typedef struct trieTree {
int data;
struct trieTree *array[26];
}trieTree;
insert function:
trieTree* insert_tree(trieTree *t, char *s, int val)
{
int i;
trieTree *p;
if (strlen(s) == 0)
return t;
if (t == NULL)
t = new_tree(t);
p = t;
for (i = 0; i < strlen(s); ++i) {
if (p->array[s[i] - 'a'] == NULL)
p->array[s[i] - 'a'] = malloc(sizeof (trieTree));
p = p->array[s[i] - 'a'];
}
p->data = val;
return t;
}
Filling the tree:
trieTree* load_tree(trieTree *t, char *file)
{
char s[MAX];
FILE *f = fopen(file, "r");
if (f == NULL)
printf("Error! File not found.");
else
while (feof(f) == 0) {
fscanf(f, "%s", s);
t = insert_tree(t, s, 1);
}
return t;
}
Main function
int main()
{
trieTree t;
new_tree(&t);
load_tree(&t, "dict.txt");
char word[100];
printf("Enter word: ");
scanf("%s", word);
char dat[100] = "";
search_tree(&t, word, dat);
return 0;
}
trieTree* new_tree(trieTree *t)
{
int i;
t = malloc(sizeof (trieTree));
for (i = 0; i < 24; ++i)
t->array[i] = 0;
return t;
}
Your function new_tree() returns a pointer to allocated memory but the returned value is ignored. That's a memory leak, and your code continues to use an uninitialized variable. That's a problem!
int main()
{
trieTree t;
new_tree(&t);
load_tree(&t, "dict.txt");
…
trieTree* new_tree(trieTree *t)
{
int i;
t = malloc(sizeof(trieTree));
for (i = 0; i < 24; ++i)
t->array[i] = 0;
return t;
}
The 24 in the function should be 26, of course. But the function allocates memory and assigns it to the local pointer (original set to point to t in main(), but the malloc() zaps that value). That pointer is returned, but the return is ignored. The variable t in main() is still uninitialized, but it is passed to the load_tree() function.
Frankly, you need:
int main()
{
trieTree *tp = new_tree();
load_tree(&t, "dict.txt");
…
trieTree* new_tree(void)
{
int i;
trieTree *t = malloc(sizeof(trieTree));
if (t == 0)
{
fprintf(stderr, "memory allocation failure\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 26; ++i)
t->array[i] = 0;
return t;
}
Note that errors should be reported on the standard error channel; that is what it's for. And that every memory allocation should be checked, because if you don't check, it will fail and your program will crash.
There are probably a lot of other problems; I've not investigated them all. This should get you further before crashing.
This seems to work for me, though admittedly I only tested it on a 'dictionary' of 257 words.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAX = 1024 };
typedef struct trieTree
{
int data;
struct trieTree *array[26];
} trieTree;
static trieTree *new_tree(void)
{
int i;
trieTree *t = malloc(sizeof(trieTree));
if (t == 0)
{
fprintf(stderr, "malloc for %zu bytes failed\n", sizeof(trieTree));
exit(EXIT_FAILURE);
}
t->data = 0;
for (i = 0; i < 26; ++i)
t->array[i] = 0;
return t;
}
static trieTree *insert_tree(trieTree *t, char *s, int val)
{
int i;
trieTree *p;
if (strlen(s) == 0)
return t;
if (t == NULL)
t = new_tree();
p = t;
int len = strlen(s);
for (i = 0; i < len; ++i)
{
if (p->array[s[i] - 'a'] == NULL)
p->array[s[i] - 'a'] = new_tree();
p = p->array[s[i] - 'a'];
}
p->data = val;
return t;
}
static trieTree *load_tree(trieTree *t, char *file)
{
char s[MAX];
FILE *f = fopen(file, "r");
if (f == NULL)
{
fprintf(stderr, "Error! File not found.");
exit(EXIT_FAILURE);
}
else
{
while (fscanf(f, "%s", s) == 1)
t = insert_tree(t, s, 1);
fclose(f);
}
return t;
}
static void print_trie(trieTree *t, char *pad)
{
int len = strlen(pad);
char space[len + 3];
memset(space, ' ', len + 2);
space[len + 2] = '\0';
for (int i = 0; i < 26; i++)
{
if (t->array[i] != 0)
{
printf("%s%c\n", pad, i + 'a');
print_trie(t->array[i], space);
}
}
}
static void free_trie(trieTree *t)
{
if (t != 0)
{
for (int i = 0; i < 26; i++)
free_trie(t->array[i]);
free(t);
}
}
int main(void)
{
trieTree *tp = new_tree();
if (tp != 0)
{
tp = load_tree(tp, "dict.txt");
print_trie(tp, "");
free_trie(tp);
}
return 0;
}
I believe it is leak free, too.
Note that this code will crash and burn if any of the input words contains any upper-case letters, or digits, or punctuation. It only handles lower-case and white space; anything else is an unchecked disaster waiting to devastate your program. That's because I've not done any substantive work in the insert_tree() function. You need to worry about 'invalid' characters in that function, probably by case-converting upper-case letters to lower-case and ignoring anything that's not a letter.

Trying to parse document and store node info, do not know why its segfaulting

When I gdb the program, it says something is wrong with strcpy, but I do not know why.
Thanks.
The program requires me to read an input file, find the course abbreviation, the course description, the number of credit hours, and the professor name.
Also, I am trying to read the credit hours from the file, which are on the same line as the course. I am trying to only get the credit hours that are on the same line as the course, but it instead prints every number as a credit hour.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 20
typedef struct courses{
char *abbr;
char *name;
int credits;
char *prof;
struct courses *next;
}courses;
int isAbbr(char *string);
int isName(char *string);
int isCredit(char *string);
int isProf(char *string);
courses *readfile(FILE *);
courses *create_course(char *abbr, char *name, int credits, char *prof);
courses *create_list(courses *, courses *);
int main(int argc, char **argv)
{
if (argc != 2)
{
printf("Inadequate amount of arguments.\n");
return 0;
}
FILE *fp = fopen(argv[1], "r");
if (fp == NULL)
{
printf("File cannot be opened.\n");
return 0;
}
courses* head = NULL;
head = readfile(fp);
int choice = 0;
while (choice != 3)
{
printf("\nSelect your option below:\n1-Register for a Course\n2-See my total\n3-Exit\nChoice: ");
scanf("%d",&choice);
}
return 0;
}
courses *readfile(FILE *fp)
{
courses *head, *entry;
head = entry = NULL;
char *abbr = malloc(MAX);
char *namep = malloc(MAX);
namep = "hello";
char *prof = malloc(MAX);
int credit;
int credflag = 0;
int nameFlag = 0;
int profFlag = 0;
int credits = 0;
char line[MAX];
while (fgets(line, MAX - 1, fp) != NULL)
{
if (line[strlen(line) - 1] == '\n')
{
line[strlen(line) - 1] = '\0';
}
char* token = strtok(line," ,\t");
while (token != NULL)
{
if (isAbbr(token) == 1)
{
abbr = token;
credflag = 1;
}
if (isName(token) == 1)
{
credflag = 1;
}
if (isCredit(token) == 1)
{
if(credflag == 1)
{
credits = atoi(token);
credflag = 0;
}
}
if (isProf(token)== 1)
{
if(nameFlag == 1) //print names, reset name flag = 0
{
entry = create_course(abbr, namep, credits, token);
head = create_list(entry,head);
nameFlag = 0;
}
else
{
namep = malloc(sizeof(char));
strcpy(namep, token);
nameFlag = 1;
}
}
else
{
nameFlag = 0;
}
token = strtok(NULL," ,\t");
}
}
}
courses *create_course(char *abbr, char *name, int credits, char *prof)
{
courses *entry = malloc(sizeof(courses));
entry->abbr=(char*)malloc(sizeof(char)*256);
strcpy(entry->abbr, abbr);
entry->name=(char*)malloc(sizeof(char)*256);
strcpy(entry->name, name);
entry->abbr=(char*)malloc(sizeof(char)*256);
strcpy(entry->prof, prof);
entry->credits = credits;
entry->next = NULL;
return entry;
}
courses *create_list(courses *head, courses *entry)
{
if (head == NULL)
{
return entry;
}
courses* curr = head;
while (curr->next != NULL)
{
curr = curr->next;
}
curr->next = entry;
return head;
}
int isProf(char *string)
{
int length = strlen(string);
int i;
if (isupper(string[0]))
{
for (i=1; i<length; i++)
{
if (islower(string[i]))
{
continue;
}
else
{
return 0;
}
}
return 1;
}
}
int isCredit(char *string)
{
int n;
int nfields = sscanf(string, "%d", &n);
if (nfields == 1 && n > 0)
{
return 1;
}
return 0;
}
int isName(char *string)
{
return 1;
}
int isAbbr(char *string)
{
int length = strlen(string);
if (length == 8 && string[4] == '-')
{
printf(" %s\n",string);
return 1;
}
return 1;
}
Just focus on strcpy:
char *namep = malloc(MAX);
namep = "hello";
here you just lose what you malloc for namep, use strcpy or something you want.
namep = malloc(sizeof(char));
strcpy(namep, token);
here you just malloc 1 char for namep, but strcpy auto add NULL terminator, so unless token is "", you overflow namep.
And every strcpy in create_course(), you just malloc 256 and strcpy, what if size of abbr, name, prof > 255? check size or use strncpy().

Resources