I'm new to the C language, and I'm trying to make a calendar using SDL2, but for some reason my code just skips storing the first data. When I try to return with the "head" of my linked list (which stores structures), some of the data is saved, but some is not. I have a function called linecutter. It should work fine according to my tests. The structure of the file is something like
for some reason the comment part returns correctly. If I printf the location data, it returns correctly, but otherwise it doesn't work as intended.
An examle of a file used:
Prog spec;2020/10/05;2020/11/01;00/00;23/59;Infoc;shouldnt forget it and leave to the last min
something;2020/10/05;2020/11/01;00/00;23/59;location;just a comment
asd asd;2020/2/02;2020/9/01;00/00;23/59;Infoc;lkasjd laksdj
This code should print the event names twice. Once when reading the file, once when checking in the main. But it only prints when reading.
#include <stdio.h>
#include <stdlib.h>
typedef struct Date{
int y;
int m;
int d;
} Date;
typedef struct Time{
int h;
int m;
} Time;
typedef struct Event{
char* name;
Date startdate;
Date enddate;
Time starttime;
Time endtime;
char* location;
char* comment;
} Event;
typedef struct Lista{
Event event;
struct Lista * next;
} Lista;
Date datecreate(char*todate)
{
Date *tmp = (Date *)malloc(sizeof(Date)*1);
int len = strlen(todate);
char date[len];
strcpy(date,todate);
char y[5];
char m[5];
char d[4];
int i =0;
for(; i<4; i++)
y[i] = date[i];
i++;
for(int var = 0; i<7; var++, i++)
{
m[var] = date[i];
}
i++;
for(int var = 0; i<10; var++, i++)
{
d[var] = date[i];
}
tmp->d = atoi(d);
tmp->m = atoi(m);
tmp->y = atoi(y);
return *tmp;
}
Time timecreator(char*totime)
{
Time tmp;
char h[3];
char m[3];
for(int i = 0; i<2; i++)
h[i] = totime[i];
for(int i = 4; i<6; i++)
m[i-4] = totime[i];
h[3] = '\0';
m[3] = '\0';
tmp.h = atoi(h);
tmp.m = atoi(m);
return tmp;
}
Event linecutter(char* line)
{
int i = -1;
int loc = 0;
char name[256], startdate[12],enddate[12],starttime[7],endtime[7],location[256],comment[512];
do{
i++;
name[i] = line[loc];
loc++;
}
while(name[i] !=';');
name[i] = '\0';
i=-1;
do{
i++;
startdate[i] = line[loc];
loc++;
}
while(startdate[i] !=';');
startdate[i] = '\0';
i=-1;
do{
i++;
enddate[i] = line[loc];
loc++;
}
while(enddate[i] !=';');
enddate[i] = '\0';
i=-1;
do{
i++;
starttime[i] = line[loc];
loc++;
}
while(starttime[i] !=';');
starttime[i] = '\0';
i=-1;
do{
i++;
endtime[i] = line[loc];
loc++;
}
while(endtime[i] !=';');
endtime[i] = '\0';
i=-1;
do{
i++;
location[i] = line[loc];
loc++;
}
while(location[i] !=';');
location[i] = '\0';
i=-1;
do{
i++;
comment[i] = line[loc];
loc++;
}
while(comment[i] !='\0');
comment[i] = '\0';
Event tmp;
tmp.name = name;
tmp.location = location;
tmp.comment = comment;
tmp.starttime = timecreator(starttime);
tmp.startdate = datecreate(startdate);
tmp.enddate = datecreate(enddate);
tmp.endtime = timecreator(endtime);
return tmp;
}
Lista * read(void)
{
FILE *fp;
char line[5000];
fp = fopen("esemenyek.txt" , "rw+");
if(fp == NULL) {
perror("error opening");
return NULL;
}
char buf[3];
fscanf(fp, "%3c", buf);
if (memcmp(buf, "\xEF\xBB\xBF", 3) != 0) //this is just for the encoding stuff
fseek(fp, 0, SEEK_SET);
/* ... handling the file ... */
Lista * head= NULL;
Lista * current = NULL;
while(fgets(line, sizeof(line), fp)!=NULL){
Lista *node = (Lista*)malloc(sizeof(Lista));
if(node == NULL)
{
perror("error");
return NULL;
}
node->event = linecutter(line);
node->next =NULL;
if(head== NULL){
current = head = node;
} else {
current = current->next= node;
}
for(int i = 0; i<500; i++)
line[i] ='\0';
printf("%s\n", current->event.name);
}
fclose(fp);
return head;
}
int main(void){
Lista * lst = read();
Lista *move;
for (move= lst; move!= NULL; move= move->next)
printf("%s\n", move->event.name);
return 0;
}
What am I doing wrong, or why is this not working? If someone could help me, I'd really appreciate it. I found another post here, it helped me to get here, but I don't know how to proceed from here.
Related
In my problem, I need to read lines from a txt file.
Each line contains student_id, name, birthdate, gender, department, and grade(class).
e.g ( 155898933;Nuh Kaplan;26/01/1998;M;ME;2 )
Then I need to store them in a Linked List.
I declared my structure as follows:
struct Node{
int id;
char name[100];
int date; //YYYYMMDD (String date will be converted to integer. I created dateStrInt function for this conversion.)
char gender[2];
char departmentCode[6];
int classGrade;
struct Node *next;
};
Then I read lines and store in an character array with this part of code:
if (fptr != NULL) {
while (fgets (buff, 100, fptr)) {
char* split = strtok(buff, ";");
while( split != NULL ) {
strcpy(arr[i][j], split);
j++;
split = strtok(NULL, ";");
}
i++;
j = 0;
}
}
After I stored lines into character array, I need to store them in a linked list. I tried to do it as follows:
for(int i = 0; i < len; i++) {
p = (struct Node*) malloc(sizeof(struct Node));
j = 0;
p->id = (int)arr[i][j];
strcpy(p->name, arr[i][j+1]);
p->date = dateStrInt(arr[i][j+2]);
strcpy(p->gender,arr[i][j+3]);
strcpy(p->departmentCode, arr[i][j+4]);
p->classGrade = (int)arr[i][j+5];
j = 0;
if(list == NULL){
list = p;
p -> next = NULL;
last = p;
}
else {
last -> next = p;
p -> next = NULL;
last = p;
}
}
However when I run my code, I get garbage values for student id and classGrade.
Can you help me to solve this problem?
My hole code:
#include <stdio.h>
#include<string.h>
#include <stdlib.h>
#include <ctype.h>
struct Node {
int id;
char name[100];
int date; //YYYYMMDD
char gender[2];
char departmentCode[6];
int classGrade;
struct Node *next;
};
int dateStrInt(char str[]) {
int d, m, y;
sscanf(str, "%d/%d/%d", &d, &m, &y);
return (y * 10000 + m * 100 + d);
}
int countLines(char* filename) {
int count = 0;
FILE *fptr;
fptr = fopen(filename, "r");
if(fptr == NULL){
printf("File does not exist.");
exit(1);
}
else {
for(char ch = getc(fptr); ch != EOF; ch = getc(fptr)) {
if(ch == '\n'){
count++;
}
}
}
return count + 1;
}
struct Node* createList(struct Node* list, int len, char filename[]){
struct Node* last;
struct Node* p;
char buff[100];
char arr[len][6][100];
int i = 0, j = 0;
FILE* fptr = fopen(filename,"r");
if (fptr != NULL) {
while (fgets (buff, 100, fptr)) {
char* split = strtok(buff, ";");
while( split != NULL ) {
strcpy(arr[i][j], split);
j++;
split = strtok(NULL, ";");
}
i++;
j = 0;
}
}
int o = 0;
for(int k = 0; k < len; k++){
printf("\nID = %s", arr[k][o]);
printf("\nName = %s", arr[k][o+1]);
printf("\nBirth Date = %s", arr[k][o+2]);
printf("\nGender = %s", arr[k][o+3]);
printf("\nDepartment = %s", arr[k][o+4]);
printf("\nGrade = %s", arr[k][o+5]);
o = 0;
}
for(int i = 0; i < len; i++){
p = (struct Node*) malloc(sizeof(struct Node));
j = 0;
p->id = (int)arr[i][j];
strcpy(p->name, arr[i][j+1]);
p->date = dateStrInt(arr[i][j+2]);
strcpy(p->gender,arr[i][j+3]);
strcpy(p->departmentCode, arr[i][j+4]);
p->classGrade = (int)arr[i][j+5];
j = 0;
if(list == NULL){
list = p;
p -> next = NULL;
last = p;
}
else {
last -> next = p;
p -> next = NULL;
last = p;
}
}
return list;
}
void printList(struct Node *list, int len){
struct Node *p;
p = list;
int cnt = 0;
printf("\nThe list = ");
while(p != NULL) {
if(cnt != len - 1) {
printf("\n{%d, %s, %d, %s, %s, %d} ---->",p->id, p->name, p->date,
p->gender, p->departmentCode, p->classGrade);
cnt++;
}
else
printf("\n{%d, %s, %d, %s, %s, %d} ",p->id, p->name, p->date,
p->gender, p->departmentCode, p->classGrade);
p = p->next;
}
}
int main(void) {
struct Node *head = NULL;
char filename[10];
printf("Enter file name: ");
scanf("%s", filename);
int len = countLines(filename);
struct Node* list = createList(head, len, filename);
printList(list, len);
}
test.txt file :
149875280;Burcu Aksu;04/04/1994;F;CS;3
180201201;Mustafa Kursat Yavuz Tur;12/06/1996;M;CS;3
Output:
Enter file name: test.txt
ID = 149875280
Name = Burcu Aksu
Birth Date = 04/04/1994
Gender = F
Department = CS
Grade = 3
ID = 180201201
Name = Mustafa Kursat Yavuz Tur
Birth Date = 12/06/1996
Gender = M
Department = CS
Grade = 3
The list =
{-1883589280, Burcu Aksu, 19940404, F, CS, -1883588780} ---->
{-1883588680, Mustafa Kursat Yavuz Tur, 19960612, M, CS, -1883588180}
Why are you declaring char array, instead you should be creating array of Node type. Just typecasting the string value to int will not convert the 2 integer fields correctly. Use the conversion function like atoi().
Change this line,
p->id = (int)arr[i][j];
to
p->id = atoi(arr[i][j]);
I have a problem and I really dont know what to do.
I'am trying to insert "new students" to an student-array. The array contains pointers to the created structs. Can somebody find the error? It adds the student-structs to the array but especially the printing doesnt work.
It would be really helpful, if somebody could help me. :) PS: You can just copy the code.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_HASH 10
typedef struct student
{
unsigned int matnr;
char *name;
struct student *next_student;
} Student;
Student **hash_tabelle[MAX_HASH];
void insert_student (unsigned int matnr, char *name)
{
Student *neuer_student = malloc(sizeof(Student));
neuer_student->name = malloc(sizeof(*name)+1);
neuer_student->matnr = matnr;
strcpy(neuer_student->name, name);
neuer_student->next_student = NULL;
// Index im Hash-Array ermitteln
int hash_index = matnr % 10;
if(hash_tabelle[hash_index] == NULL)
{
neuer_student->next_student = hash_tabelle[hash_index];
hash_tabelle[hash_index] = neuer_student;
}
else
{
while(*hash_tabelle[hash_index] != NULL && (((*hash_tabelle[hash_index])->matnr - neuer_student->matnr) <= 0))
hash_tabelle[hash_index] = &(*hash_tabelle[hash_index])->next_student;
neuer_student->next_student = *hash_tabelle[hash_index];
*hash_tabelle[hash_index] = neuer_student;
}
}
void print_hash_tabelle()
{
for(int i = 0; i != MAX_HASH - 1; i++){
printf("%d)\t", i);
hash_tabelle[i] = &(*hash_tabelle[i])->next_student;
for(; hash_tabelle[i] != NULL; hash_tabelle[i] = &(*hash_tabelle[i])->next_student){
printf("%s (%d)", (&(*hash_tabelle[i])->name), (&(*hash_tabelle[i])->matnr));
}
printf("\t");
}
}
int main()
{
unsigned int matnr;
char name[100];
do
{
printf("Matrikelnummer:\t");
scanf("%d", &matnr);
fflush(stdin);
getchar(); // um das \n aus dem Puffer zu kriegen und rauszuschmeiĆen
printf("Name:\t\t");
fgets(name, 30, stdin);
insert_student(matnr, name);
}
while (matnr != 0);
print_hash_tabelle();
return 0;
}
Using a hash table is so simple... No need to use dereferencing for a fixed-size array of linked-list pointers.
Step 1 - a hash table is a array of linked-list pointers.
As #BLUEPIXY suggests:
Student *hash_tabelle[MAX_HASH];
Step 2 - to allocate and free each linked-list, initialize each item to NULL.
Otherwise, if(hash_tabelle[hash_index] == NULL) is Undefined
behavior in the function insert_student().
void hash_init()
{
for(int i=0;i<MAX_HASH;i++) {
hash_tabelle[MAX_HASH]=NULL;
}
}
Step 3 - allocate enough char to store the char *name to insert_student().
As # WhozCraig suggests, use strlen().
void insert_student (unsigned int matnr, char *name)
{
Student *neuer_student = malloc(sizeof(Student));
neuer_student->name = malloc(strlen(name)+1);
neuer_student->matnr = matnr;
strcpy(neuer_student->name, name);
neuer_student->next_student = NULL;
Step 4 - add the neuer_student in the hash_tabelle[] (function insert_student())
Warning: the index shall be included in the size of the array
[0..MAX_HASH[. (using 10 instead of MAX_HASH could become a bug).
int hash_index = matnr % MAX_HASH;
When the hash_tabelle[hash_index] is NULL, simple store the
neuer_student. No need to modify neuer_student->next_student.
if(hash_tabelle[hash_index] == NULL)
{
hash_tabelle[hash_index] = neuer_student;
}
Else explore the linked-list of hash_tabelle[hash_index] to store
the neuer_student at the end.
else
{
Student *tmp;
tmp = hash_tabelle[hash_index];
while (tmp->next_student!=NULL) {
tmp = tmp->next_student;
}
tmp->next_student = neuer_student;
}
Step 5 - to print the all items of the hash table (function print_hash_tabelle())
Reuse the same method to explore each linked-list pointer.
Warning: explore all item from 0 to MAX_HASH-1
void print_hash_tabelle()
{
for(int i = 0; i < MAX_HASH; i++){ // ERR != MAX_HASH - 1; i++){
printf("%d)\t", i);
Student *tmp = hash_tabelle[i];
while (tmp!=NULL) {
printf("%s (%d)", tmp->name, tmp->matnr);
tmp = tmp->next_student;
}
printf("\n");
}
}
Step 6 - free the memory of each item of the hash_tabelle[].
Free the allocated string free(tmp->name);.
Remove the current student hash_tabelle[i] = tmp->next_student;
Free the allocated student free(tmp);
Repeat until the end of the linked-list
That's all (no change in the main() except adding a call to hash_free() at the end).
void hash_free()
{
for(int i=0;i<MAX_HASH;i++) {
Student *tmp = hash_tabelle[i];
while (tmp!=NULL) {
free(tmp->name);
hash_tabelle[i] = tmp->next_student;
free(tmp);
tmp = hash_tabelle[i];
}
}
}
like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_HASH 10
typedef struct student {
unsigned int matnr;
char *name;
struct student *next_student;
} Student;
Student *hash_tabelle[MAX_HASH];
void insert_student (unsigned int matnr, char *name){
Student *neuer_student = malloc(sizeof(Student));
neuer_student->name = malloc(strlen(name)+1);
strcpy(neuer_student->name, name);
neuer_student->matnr = matnr;
//neuer_student->next_student = NULL;
int hash_index = matnr % MAX_HASH;
Student head = { .next_student = hash_tabelle[hash_index] };
Student *prev = &head, *curr = head.next_student;
while(curr != NULL && curr->matnr <= neuer_student->matnr){
prev = curr;
curr = curr->next_student;
}
neuer_student->next_student = curr;
prev->next_student = neuer_student;
hash_tabelle[hash_index] = head.next_student;
}
void print_hash_tabelle(void){
for(int i = 0; i < MAX_HASH; i++){
printf("%d)\t", i);
for(Student *p = hash_tabelle[i]; p; p = p->next_student){
printf("%s (%d)\t", p->name, p->matnr);
}
printf("\n");
}
}
void free_hash_tabelle(void){
for(int i = 0; i < MAX_HASH; i++){
Student *p = hash_tabelle[i];
while(p){
Student *temp = p->next_student;
free(p->name);
free(p);
p = temp;
}
}
}
int main(void){
int matnr = -1;//for %d of scanf
char name[100];
while(1){
printf("Matrikelnummer(-1 for end input): ");fflush(stdout);
scanf("%d", &matnr);
if(matnr < 0)
break;
while(getchar() != '\n');
printf("Name: ");fflush(stdout);
fgets(name, sizeof name, stdin);
name[strcspn(name, "\n")] = 0;
insert_student(matnr, name);
}
print_hash_tabelle();
free_hash_tabelle();
return 0;
}
My assignment is to make a program in C to remove null production from a CFG. Ans I can only use Linked List. Note that the Linked List value part points to an Array. I've given the output in the Code. My Null production removal is not working properly. Please run the code and tell me what you think and how can i improve it.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdbool.h>
/*the CFG
S>ABAC
A>aA|$
B>bB|$
C>c
*/
/*List produced
SABAC
AaA
A$
BbB
B$
Cc*/
/*Desired Result
SABAC
SABC
SBAC
SBC
AaA
BbB
Bb
Cc*/
typedef struct node {
struct node * next;
//struct node * prev;
char arr[7];//the array to save CFG per line
}node_t;
char print_list(node_t * root);
//char first_set(node_t * root,char c);
char traversal(node_t * root);//To see which nodes have null productions
char rightTraversal(node_t * root,char);//Passing the nodes which have null production then removing them from list.
char c, temp, nonTerminal; int i=0; bool flag = true;
char null_list[7];
int null_counter = 0;
int main() {
node_t * head = malloc(sizeof(node_t));
node_t * current = malloc(sizeof(node_t));
node_t * root = malloc(sizeof(node_t));
head = current;
for(int j=0; j<7; j++){
null_list[j] = '#';
}
FILE *fp;
//char c, temp; int i=0; bool flag = true;
fp = fopen("cfg.txt", "r");
while((c = fgetc(fp)) != EOF) {
if(c == '\n') {
current->next = malloc(sizeof(node_t));
//current->next->next = NULL;
current = current->next;
current->next = NULL;
flag = true; i=0;
}else if(c == '>' || c == ' '){continue;}
else if(c == '|'){
current->next = malloc(sizeof(node_t));
current = current->next;
i = 0;
current->arr[i] = temp;
i++;
continue;
}
else {
current->arr[i] = c;
i++;
current->next = NULL;
//current->prev = NULL;
if(flag){
temp = c;
flag = false;
}
// continue;
}
}
fclose(fp);
root = head;
traversal(root);
/*for(int j=0; j<7; j++){
if(null_list[j] != '#'){
printf("%c\n",null_list[j]);
}
}*/
rightTraversal(root, null_list[0]);
rightTraversal(root, null_list[1]);
}
char print_list(node_t * root) {
while(root->next != NULL){
for(i=0; i<7; i++) {
printf("%c", root->arr[i]);
}
printf("\n");
root = root->next;
}
return 0;
}
char traversal(node_t * root) {
while(root->next != NULL){
for(i=0; i<7; i++) {
if(root->arr[i] == '$'){
null_list[null_counter] = root->arr[0];
null_counter++;
}
}
root = root->next;
}
return 0;
}
char rightTraversal(node_t * root, char c){
node_t * shoot = root;
while(shoot->next != NULL){
for(int i=1; i<7; i++){
if(shoot->arr[i] == c){
node_t * temp_node = malloc(sizeof(node_t));
/*printf("%c\n", shoot->arr[0]);*/
for(int i=0; i<7; i++){
temp_node->arr[i] = shoot->arr[i];
}
for(int k=1; k<7; k++){
if(temp_node->arr[k]==c){
temp_node->arr[k] = ' ';
break;
}
}
temp_node->next = shoot->next;
shoot->next = temp_node;
break;
//shoot->next = malloc(sizeof(node_t));
//shoot = shoot->next;
}
}
shoot = shoot->next;
}
print_list(root);
}
fgetc() returns an int. You assign the result to a char.
So this condition
(c = fgetc(fp)) != EOF)
will never detect EOF.
To fix this defined c to be an int or introduce an intermediate int like this:
int ci;
while (ci = fgetc(fp)) != EOF)
{
c = ci;
If you'd pushed up the compiler's warning level to the maximum (-Wall -Wextra -Wconversion -pedantic for GCC) it mostly like had warned you on this!
I am working on a project in C and it is working great except for one function which seems to be overwriting my array and writing weird numbers such as 1970802352 which keeps count of word occurrences in a file
this is my header file:
#ifndef LIST_H
#define LIST_H
struct Node_{
char* word;
//array holding names of files word occurs in
char **filesIn;
int numFilesIn;
//array holding count of how many times word occured in file
int* occursIn;
struct Node_ *next;
int isHead;
};
typedef struct Node_ Node;
int insert(char *wordToAdd, char *File);
int addOccur(Node *addedTo, char *File);
Node *createNode(char *wordToAdd, char *File);
void destroyNodes();
#endif
and this is the function that keeps overwriting the array:
Node *head;
int insert(char *wordToAdd, char *File){
if(head == NULL){
Node *new;
new = createNode(wordToAdd, File);
new->isHead = 1;
head = new;
return 0;
}
else{
Node *trace;
trace = head;
char *traceWord;
int wordSize;
wordSize = strlen(trace->word);
traceWord = (char*) malloc(wordSize + 1);
strcpy(traceWord, trace->word);
int a =strcmp(wordToAdd, traceWord);
free(traceWord);
if(a == 0){
int b = addOccur(trace, File);
//printf("addOccur returned %d\n", b);
return 0;
}
if(a < 0){
Node *Insert = createNode(wordToAdd, File);
trace->isHead = 0;
Insert->isHead = 1;
Insert->next = trace;
head = Insert;
return 0;
}
else{
Node *backTrace;
backTrace = head;
while(trace->next != NULL){
trace = trace->next;
traceWord = trace->word;
a = strcmp(wordToAdd, traceWord);
if(a < 0){
Node* Insert = createNode(wordToAdd, File);
Insert->next = trace;
backTrace->next = Insert;
return 0;
}
if(a == 0){
addOccur(trace, File);
//free(wordToAdd);
return 0;
}
if(a > 0){
backTrace = trace;
continue;
}
}
Node *Insert = createNode(wordToAdd, File);
trace->next = Insert;
return 0;
}
}
return 1;
}
and the other functions are:
Node* createNode(char *wordToAdd, char *File){
Node *new;
new = (Node*)malloc(sizeof(Node));
memset(new, 0, sizeof(Node));
new->word = wordToAdd;
char **newArray;
newArray = (char**)malloc(sizeof(char*));
newArray[0] = File;
new->filesIn = newArray;
int a[1];
a[0] = 1;
new->occursIn = a;
//new->occursIn[0] = 1;
new->numFilesIn = 1;
return new;
}
int addOccur(Node *addedTo, char *File){
char **fileList = addedTo->filesIn;
char *fileCheck;
int i = 0;
int fileNums = addedTo->numFilesIn;
for(i = 0; i < fileNums; i++){
fileCheck = fileList[i];
if(strcmp(fileCheck, File) == 0){
int *add1;
add1 = addedTo->occursIn;
int j = add1[i];
j++;
add1[i] = j;
return 0;
}
}
int numberOfFilesIn;
numberOfFilesIn = addedTo->numFilesIn;
char **newList = (char**)malloc(sizeof(char*) * numberOfFilesIn + sizeof(char*));
i = 0;
char *dest;
char *src;
for(i = 0; i < numberOfFilesIn; i++){
src = fileList[i];
int len;
len = strlen(src);
dest = (char*)malloc(sizeof(char) * (len + 1));
strcpy(dest, src);
newList[i] = dest;
}
int len2;
len2 = strlen(File);
newList[i] = File;
free(fileList);
int r = addedTo->numFilesIn;
r++;
addedTo->numFilesIn = r;
addedTo->filesIn = newList;
i = 0;
int *g;
g = addedTo->occursIn;
int count2;
count2 = addedTo->numFilesIn;
count2++;
int a[count2];
for(i = 0; i < count2 -1; i++){
a[i] = g[i];
}
a[count2 - 1] = 1;
return 0;
}
When going to gdb i notice that the value of
head->occursIn[0]
changes after the line
wordSize = strlen(trace->word);
and I have no clue why.
In your CreateNode() function, you are not allocating storage for the occursIn array. You are simply declaring a local array within the function and then assigning the occursIn pointer:
int a[1];
a[0] = 1;
new->occursIn = a;
The array a[1] goes away when the createNode function returns, so at that point your occursIn pointer is pointing to a value that is subject to being overwritten.
And even if the storage was allocated correctly in createNode, you've set a fixed size for the array but your whole strategy depends on that array having an element for each file; and in addOccurs you don't do anything to allocate a new larger array for a new file.
You may want to re-evaluate your strategy and switch to using lists instead of arrays.
I'm having a bit of trouble thinking of an idea to solve my problem.
I have a word counting program, which uses a hashtable to count
all of the words in any number of files, and print only the words
that are in all files, and their counts. I also store all of my used
hash indexs in a linked list.
Solved my own problem, I knew the answer would be simple. I just figured out the one with the lowest count and if my new value was greater than than that, but it at the index of the one of the lowest count in the array of the twenty word structs.
Thanks for all of your help everyone!
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
/*Structures*///////////////////////////////////////////
//A struct to hold the words in the hash tables and their
//counts
struct counter{
int count;
int printed;
char word[51];
int allfiles[101];
struct counter * next;
};
//A struct to hold the hash indexes of the already visited
//index, for easy printing
struct index{
int used;
struct index * next;
};
//A simple struct to pass arguments to the work function for
//threading
struct arguments{
void * id;
int fileid;
};
////////////////////////////////////////////////////////
/*Functions*////////////////////////////////////////////
static int hash(char * word);
static void inHash(struct counter * newWord, int hash, int FILEID);
static void indexchain(int hash);
//static void hashprint(int NUMFILES);
static void * work(struct arguments *);
static void toptwenty(int NUMFILES);
static void print();
////////////////////////////////////////////////////////
/*Global Variables*/////////////////////////////////////
struct counter * top[20] = {0};
struct counter * hashtable[6222] = {0};
struct index * head;
////////////////////////////////////////////////////////
int main(int argc, char * argv[])
{
//check for valid number of arguments
if(argc < 2)
{
fprintf(stderr, "invalid number of arguments");
return 1;
}
//set up index chain starts with a null node
head = malloc(sizeof(struct index));
head->next = NULL;
head->used = -1;
//loop through any number of files
int arg;
for(arg = 1; arg < argc; arg++)
{
struct arguments * argum = malloc(sizeof(struct arguments));
argum->fileid = arg;
argum->id = ((void*)argv[arg]);
work(argum);
}
//hashprint(argc);
toptwenty(argc);
print();
return 0;
}
/*Function Definitions*/
//this function takes a file name and counts
//the words in the file
static void * work(struct arguments * argum)
{
int FILEID = argum->fileid;
void * in = argum->id;
int fd = open((char*)in, O_RDONLY);
if (fd == -1)
{
fprintf(stderr, "can't open %s for reading!\n", (char*)in);
exit(-1);
}
int BUFLEN = (int) lseek(fd, 0, SEEK_END);
lseek(fd, 0, 0);
//A few variable
char buf[BUFLEN + 1];
int lastRead;
lastRead = read(fd, buf, BUFLEN);
if (lastRead == -1)
{
fprintf(stderr, "error reading file %s!\n", (char*)in);
exit(-1);
}
//Parse the filebuffer for words.
char newword[51];
int c;
int curindex = 0;
buf[BUFLEN + 1] = ' ';
//not doing the last space because it is eof
for(c = 0; c < BUFLEN + 1; c++)
{
if((buf[c] >= 'A' && buf[c] <= 'Z'))
{
buf[c] += 32;
}
if(buf[c] >= 'a' && buf[c] <= 'z')
{
//add the next char to the string.
newword[curindex] = buf[c];
curindex++;
}
else
{
//make a new struct for the entry, and add it to the hashtable
//add its hash to the
if(strlen(newword) >= 6)
{
struct counter * temp = malloc(sizeof(struct counter));
strcpy(temp->word,newword);
int thishash = hash(temp->word);
//Only save hash indexes if they are in the first files
if(FILEID == 1)
{
indexchain(thishash);
}
inHash(temp, thishash, FILEID);
}
int wordlength = strlen(newword);
int i;
for(i = 0;i < wordlength; i++)
{
newword[i] = 0;
}
curindex = 0;
}
}
close(fd);
return in;
}
//Bad hash function by just adding ascii values of the
//characters
static int hash(char * word)
{
int loop = strlen(word);
int i;
int hashval = 0;
for(i = 0; i < loop; i++)
hashval += word[i];
return hashval;
}
//add a new word to the hash table
static void inHash(struct counter * newWord, int hash, int FILEID)
{
int eflag = 0;
if(hashtable[hash] == NULL)
{
//if the entry isnt in the table
if(FILEID == 1)
{
newWord->allfiles[FILEID] = 1; /*FILEID ARRAY TEST*/
newWord->count = 1;
newWord->next = NULL;
hashtable[hash] = newWord;
}
}
else
{
//if its not, but what if it is?
struct counter * cur = hashtable[hash];
if(strcmp(cur->word, newWord->word) == 0)
{
//is the word in the first slot?
cur->count += 1;
cur->allfiles[FILEID] = 1; /*FILEID ARRAY TEST*/
eflag = 1;
}
else
{
while(cur->next != NULL)
{
cur = cur->next;
if(strcmp(cur->word, newWord->word) == 0)
{
//if the word already exsists, update the count
cur->allfiles[FILEID] = 1; /*FILEID ARRAY TEST*/
cur->count += 1;
eflag = 1;
break;
}
}
}
//if its not in any bucket, make a new bucket
if(eflag == 0)
{
//Else add the new entry to the end of that list
if(FILEID == 1)
{
newWord->allfiles[FILEID] = 1; /*FILEID ARRAY TEST*/
newWord->count = 1;
newWord->next = NULL;
cur->next = newWord;
}
}
}
}
//adding a value to the linked list for printing
static void indexchain(int hash)
{
struct index * p = head;
int eflag = 0;
while(p->next != NULL)
{
if(p->used != hash)
p = p->next;
else
{
eflag = 1;
break;
}
}
if(eflag == 0)
{
struct index * newValue = malloc(sizeof(struct index));
newValue->used = hash;
newValue->next = NULL;
p->next = newValue;
}
}
/*
//This function will print the values in the hash tables and their counts
//Prints based on number of files to check if words are in all files
static void hashprint(int NUMFILES)
{
struct index * p;
p = head->next;
int hash;
int i;
int printbool = 1;
while(p != NULL)
{
hash = p->used;
struct counter * ptr = hashtable[hash];
while(ptr != NULL)
{
if(ptr->printed == 0)
{
for(i = 1; i < NUMFILES; i++)
{
if(ptr->allfiles[i] == 0)
{
printbool = 0;
break;
}
else
printbool = 1;
}
if(printbool == 1)
{
ptr->printed = 1;
printf("%s %d\n", ptr->word, ptr->count);
}
}
ptr = ptr->next;
}
p = p->next;
}
}
*/
//A function to see which numbers have the top twenty highest count
static void toptwenty(int NUMFILES)
{
struct index * p;
p = head->next;
int hash;
int i;
int printbool = 1;
while(p != NULL)
{
hash = p->used;
struct counter * ptr = hashtable[hash];
while(ptr != NULL)
{
if(ptr->printed == 0)
{
for(i = 1; i < NUMFILES; i++)
{
if(ptr->allfiles[i] == 0)
{
printbool = 0;
break;
}
else
printbool = 1;
}
if(printbool == 1)
{
for(i = 0; i < 20; i++)
{
if(top[i] == NULL)
{
top[i] = ptr;
break;
}
else if(ptr->count > top[i]->count)
{
top[i] = ptr;
break;
}
}
}
}
ptr = ptr->next;
}
p = p->next;
}
}
//print the top 20 count
static void print()
{
int i;
for(i = 0; i < 20; i++)
{
if(top[i] != NULL)
{
if(top[i]->printed == 0)
{
//printf("%s\n", top[i]->word);
printf("%s %d\n", top[i]->word, top[i]->count);
top[i]->printed = 1;
}
}
else
break;
}
}
Create an priority Queue that holds the 20 hash indexes that have the top counts and their corresponding counts.
When you are counting the lowest value is at the top of the queue if your new word beats it remove it from the queue O(1) and add your new one to the queue O(log(n)) which is only O(log(20)).