C Passing char array to function using structs - c

We have a small program where the input comes from a text file (see text sample below) and is used to scan and write certain student information to different struct variables. However, when the add_student() function is called it gives this bizzare output (see screenshot below).
struct student_list sl;
struct teacher_list tl;
struct data {
char *name;
int number;
char index;};
struct student {
struct data *d;
struct student *next;};
struct student_list{
int size;
struct student *front;
struct student *tail;};
struct teacher{
struct data *d;
struct teacher *next;};
struct teacher_list{
int size;
struct teacher *front;
struct teacher *tail;};
void main()
{
readAndLoad();
print_students();
}
void readAndLoad()
{
int c;
int i=0;
char line[200];
int number, semNum;
char name[100];
char index;
while ((c=getchar())!=EOF)
{
if(c != '\n')
{
line[i++] = c;
line[i] = '\0';
/*printf("%c ", c);
printf("%s \n", line);*/
}else
{
//printf("\n");
int j, b;
b = 0;
for (j = 0; j < sizeof(line); j++)
{
if (line[j] == ' ')
++b;
}
//printf("%s \n", line);
if (b == 2)
{
if (line[0] == 'S')
{
sscanf(line, "S %d %s", &number, name);
struct student *studentnode;
studentnode = malloc(sizeof(struct student));
add_student(&studentnode, number, &name);
} else if (line[0] == 'T')
{
sscanf(line, "T %d %s", &number, name);
struct teacher *teachernode;
teachernode = malloc(sizeof(struct teacher));
add_teacher(&teachernode, number, &name);
}
}
memset(&line[0], 0, sizeof(line));
i=0;
}
}
//printf(line);
}
void add_student(struct student *n, int student_number, char *student_name)
{
//---------------------------------------------------
printf("%s\n", student_name);
n->d->name = student_name;
n->d->number = student_number;
n->d->index = 'S';
n->next = 0;
printf("%s\n", n->d->name);
//---------------------------------------------------
if (sl.size == 0)
{
sl.front = n;
sl.tail = n;
printf("%s %d \n", n->d->name, n->d->number);
} else
{
sl.tail->next = n;
sl.tail = n;
printf("%s %d \n", n->d->name, n->d->number);
}
sl.size++;
printf("Student added\n");
}
void add_teacher(struct teacher *n, int number, char *name)
{
n->d->name = name;
n->d->number = number;
n->d->index = 'T';
n->next = 0;
if (tl.size == 0)
{
tl.front = n;
tl.tail = n;
} else
{
tl.tail->next = n;
tl.tail = n;
}
tl.size++;
printf("Teacher added\n");
}
void print_students()
{
int i;
struct student *s = sl.front;
for (i = 0; i < sl.size; i++)
//while (s->next != 0)
{
if (i == (sl.size - 2))
{
printf("%c %s %d", s->d->index, s->d->name, s->d->number);
} else
{
printf("%c %s %d \n", s->d->index, s->d->name, s->d->number);
s = s->next;
}
}
}
Input text file sample
here is the output
Between the highlighted part //-------------------
in the code we can see a correct output of the name from the first printf() but when we go to the second printf() it only prints the blank space... Do you know what could be the problem?
Input text file:
S 123456 Ivan
S 654321 Georgi
T 123456 Jesper
T 123457 Ole
T 123458 Lars
T 123459 Erland
C 31 CALI1 3
C 11 WDDI1 1
C 21 SDJI2 2
E 123456 31
E 123456 11
E 654321 21
A 123456 31
A 123457 11
Console output:
Ivan
123456
Student added
Georgi
,▒( 654321
Student added
Teacher added
Teacher added
Teacher added
Teacher added
E 0▒( 2673448E 0▒( 2673448

studentnode = malloc(sizeof(struct student));
only allocates memory for an instance of student. The memory for studentnode->d has not been allocated. Therefore any n->d->something in add_student() is invalid, thus invokes undefined behavior.

Related

Store list of courses input by user to an array in c

The program currently only asks the user to input courses, I want the list of courses the user entered to be stored in struct Students{ char courses[NUM_COURSES][100];. The list of courses the user entered should be able to be printed by using
printf("Courses %s\n",temp->courses);
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#define NUM_COURSES 5
int i = 0;
struct Students
{
char first_name[100];
char last_name[100];
int age;
char address[100];
char programme[100];
char courses[NUM_COURSES][100];
int num_selected_courses;
struct Students *next;
} * head;
void enter_student(char *first_name, char *last_name, int age, char *address, char *programme, char *courses, int num_selected_courses)
{
struct Students *student = (struct Students *)malloc(sizeof(struct Students));
strcpy(student->first_name, first_name);
strcpy(student->last_name, last_name);
student->age = age;
strcpy(student->address, address);
strcpy(student->programme, programme);
strcpy(student->courses[i], courses);
student->num_selected_courses = num_selected_courses;
student->next = NULL;
if (head == NULL)
{
// if head is NULL
// set student as the new head
head = student;
}
else
{
// if list is not empty
// insert student in beginning of head
student->next = head;
head = student;
}
}
void search_fname(char *first_name, char *last_name, int age, char *address, char *programme, char *courses, int num_selected_courses)
{
struct Students *temp = head;
char a[50];
int j;
printf("Enter First Name of Student to Search:\n");
scanf("%s", &a);
while (temp != NULL)
{
for (int j = 1; j <= i; j++)
{
if (!strcmp(first_name, a))
{
printf("The Students Details are:\n");
printf("First Name: %s\n", temp->first_name);
printf("Last Name: %s\n", temp->last_name);
printf("Age:%d\n", temp->age);
printf("Address: %s\n", temp->address);
printf("Programme: %s\n", temp->programme);
printf("Courses %s\n", temp->courses); /// list of courses for student name entered prints here
return;
}
}
temp = temp->next;
}
printf("Student name %s not found!!!\n\n\n", a);
}
int main()
{
struct Students stud;
head = NULL;
char first_name[100];
char last_name[100];
int age;
char address[100];
char programme[100];
int selected_courses[NUM_COURSES];
int num_selected_courses = 0;
int c;
const char *const list_courses[NUM_COURSES] = {
"CSE1100",
"CSE1101",
"CSE1102",
"ITE1100",
"ITE1101"};
do
{
int input_valid = 0;
int selected_course;
int d;
while (!input_valid)
{
char input[100];
// prompt user for input
printf(
"Courses available:\n"
" CSE1100\n"
" CSE1101\n"
" CSE1102\n"
" ITE1100\n"
" ITE1101\n"
"\n"
"Enter Course: ");
// attempt to read one word of user input
if (scanf("%99s", input) != 1)
{
fprintf(stderr, "unexpected input failure!\n");
exit(EXIT_FAILURE);
}
// discard remainder of input line
do
{
d = getchar();
} while (d != '\n' && d != EOF);
// determine whether course entered was valid or not
for (int i = 0; i < NUM_COURSES; i++)
{
if (strcmp(input, list_courses[i]) == 0)
{
input_valid = 1;
selected_course = i;
break;
}
}
// if invalid, print error message
if (!input_valid)
printf("Invalid choice! Try again.\n\n");
}
// input was valid, so add course
selected_courses[num_selected_courses] = selected_course;
num_selected_courses++;
// if we have already reached the maximum number of
// courses, then don't ask again
// ask user whether he wants to add another course
printf("Would you like to enter another course? (y or n)\n");
c = d = getchar();
// add spacing
printf("\n");
// discard remainder of input line
while (d != '\n' && d != EOF)
d = getchar();
} while (c == 'y');
for (int i = 0; i < num_selected_courses; i++)
{
// COPYING A SELECTED COURSE INTO STUDENT STRUCT
strcpy(stud.courses[i], list_courses[selected_courses[i]]);
}
// POPULATE NUMBER OF SELECTED COURSES IN STUDENT STRUCT
stud.num_selected_courses = num_selected_courses;
printf("You have selected the following courses:\n");
// PRINTING ALL COURSES IN THE STUDENT STRUCT
for (int i = 0; i < stud.num_selected_courses; i++)
// PRINTING A COURSE IN THE STUDENT STRUCT
printf("%s\n", stud.courses[i]);
}
If you want to be able to use the line
printf("Courses %s\n",temp->courses);
in order to print the courses member of struct Students, then you must make the courses member a null-terminated string. However, you are currently declaring that member as an array of strings.
Therefore, in order to do what you say you want, you would have to change the declaration
char courses[NUM_COURSES][100];
in struct Students to something like:
char courses[100];
You probably want the content of the string to be something like:
"CSE1100, CSE1102, ITE1101"
I have shown you in my answer to your previous question how to build such a string.

How can i automatically increase memory allocation for a struct in C?

I am building a small program that takes name and age as input (stored in a struct) and spits out the output. One of the problems that I am facing is I have to enter the number of people I am going to store, something that I am sure I can solve with realloc() it's just not working. Here is what I got so far.
#include <stdio.h>
#include<stdlib.h>
struct info
{
int age;
char name[30];
};
int main()
{
struct info *Ptr;
int i, num;
printf("Enter number of people");
scanf("%d", &num);
// Allocates the memory for num structures with pointer Ptr pointing to the base address.
Ptr = (struct info*)malloc(num * sizeof(struct info));
for(i = 0; i < num; ++i)
{
printf("Enter name and age:\n");
scanf("%s %d", &(Ptr+i)->name, &(Ptr+i)->age);
}
for(i = 0; i < num ; ++i)
printf("Name = %s, Age = %d\n", (Ptr+i)->name, (Ptr+i)->age);
return 0;
}
I have tried to realloc inside the first for loop, but it wasn't working even if it makes sense to have it there. Have also tried to convert the loop to a while loop like this:
while(input != "stop)
{
allocate more memory
}
How can I use realloc to in order to skip having to enter the persons number before entering them?
realloc is the correct way. Just start with Ptr = NULL and num = 0 and on each input increase the number of elements by one.
Remember to limit the number of characters scanf can read, otherwise you may buffer overrun.
Also I find Ptr[i] way easier then (Ptr+i)->.
Also compare strings with strcmp not using !=. The != will compare pointers to strings, not strings themselves.
As I like reading the whole line, then scanning the line, I would do it like this:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
struct info
{
int age;
char name[30];
};
int main()
{
struct info *ptr = 0;
size_t num = 0;
for (;;) {
printf("Enter name and age. If you want to stop, type only 'stop'.\n");
char line[256];
if (fgets(line, sizeof(line), stdin) == NULL) {
fprintf(stderr, "fgets error");
exit(-1);
}
if (!strcmp("stop\n", line)) {
break;
}
struct info tmp;
if (sscanf(line, "%29s %d\n", tmp.name, &tmp.age) != 2) {
fprintf(stderr, "error parsing line\n");
exit(-1);
}
ptr = realloc(ptr, (num + 1) * sizeof(*ptr));
if (ptr == NULL) {
fprintf(stderr, "error allocating memory!\n");
exit(-1);
}
ptr[num] = tmp;
++num;
}
for (size_t i = 0; i < num ; ++i) {
printf("Name = %s, Age = %d\n", ptr[i].name, ptr[i].age);
}
free(ptr);
return 0;
}
If you are not sure of the no.of.elements you want to allocate and do it based on the users choice, then you can follow the below approach.
It starts with one element and the memory is reallocated as when the user wants to add new element.
#include <stdio.h>
#include<stdlib.h>
struct info
{
int age;
char name[30];
};
int main()
{
struct info *Ptr=NULL;
int i=0, num;
char c='Y';
while(c=='Y'||c=='y') {
Ptr=realloc(Ptr,(i+1)*sizeof(struct info));
if(Ptr==NULL)
break;
printf("Enter name and age:\n");
scanf("%s %d",&Ptr[i].name,&Ptr[i].age);
printf("Do you want to cont?\n");
scanf(" %c",&c);
i++;
}
num=i;
for(i = 0; i < num ; ++i)
printf("Name = %s, Age = %d\n", (Ptr+i)->name, (Ptr+i)->age);
free(Ptr);
return 0;
}
To answer exactly, you can first read the input to temp variables and check if you need to stop: Break the loop if so. Or continue and reallocate the 'storage' array by increasing it's size by one and copying the values you just read to the 'storage' array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct info
{
int age;
char name[30];
};
int main()
{
struct info * infos = 0;
int num = 0;
char input_name[30];
int input_age;
while (1)
{
printf("Enter name and age:\n");
int r = scanf("%29s", input_name);
if (r == EOF || strcmp(input_name, "stop") == 0)
break;
scanf(" %d", &input_age);
infos = realloc(infos, sizeof(struct info) * (num + 1));
infos[num].age = input_age;
memcpy(infos[num].name, input_name, sizeof(char) * 30);
num++;
}
for(int i = 0; i < num ; ++i)
printf("Name = %s, Age = %d\n", infos[i].name, infos[i].age);
return 0;
}
You should use a data struct like vector.
vector_init init vector.
vector_push push val to vector, if necessary, will realloc memory.
vector_output output the vector.
The following code could work:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INIT_SIZE 1
struct info
{
int age;
char name[30];
};
struct vector {
struct info* p;
int n;
int index;
};
void vector_init(struct vector* ve) {
ve->n = INIT_SIZE;
ve->index = 0;
ve->p = malloc(sizeof(struct info) * ve->n);
}
void vector_push(struct vector* ve, struct info* tmp) {
if (ve->n == ve->index) {
ve->n *= 2;
ve->p = realloc(ve->p, sizeof(struct info) * ve->n);
}
ve->p[ve->index++] = *tmp;
}
void vector_output(const struct vector* ve) {
for (int i = 0; i < ve->index; ++i)
printf("Name = %s, Age = %d\n", ve->p[i].name, ve->p[i].age);
}
int main()
{
struct vector ve;
vector_init(&ve);
for (;;) {
struct info tmp;
printf("Enter name and age:\n");
scanf("%29s", tmp.name);
if (strcmp(tmp.name, "stop") == 0)
break;
scanf("%d", &tmp.age);
vector_push(&ve, &tmp);
}
vector_output(&ve);
return 0;
}

hashtable not working because of scanf()

I'm learning C data structures. I've the following code, which is resulting in a segmentation fault.
I've used the hash function from K&R C (2nd Ed.).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HASHSIZE 101
typedef struct Details
{
char *name;
float checkTotal;
float tipTotal;
int numReciepts;
struct Details *next;
struct Details *prev;
} det;
static det *hashtab[HASHSIZE];
char *str_dup(char *);
det *lookup(char *);
det *insert(char *, float, float);
unsigned hash(char *);
void printData(char *);
int main()
{
printf("1. Enter details.\n");
printf("2. Print List of employees.\n");
char *s;
float cT; //checkTotal
float tT; //tipTotal
while (1)
{
int command = 0;
printf("Enter option: ");
scanf("%d", &command);
if (command == 1)
{
printf("Enter name: ");
scanf("%s", s);
printf("Enter check total: ");
scanf("%f", &cT);
printf("Enter tip total: ");
scanf("%f", &tT);
insert(s, cT, tT);
}
else if (command == 2)
{
char *p;
printf("Enter name of employee: ");
scanf("%s", p); //including this line causes seg fault.
printData(p);
}
else
break;
}
return 0;
}
unsigned hash(char *s)
{
unsigned hashval;
for (hashval = 0; *s != '\0'; *s++)
hashval = *s + 31 * hashval;
return hashval % HASHSIZE;
}
det *lookup(char *name)
{
det *ptr;
for (ptr = hashtab[hash(name)]; ptr != NULL; ptr = ptr->next)
{
if (strcmp(name, ptr->name) == 0)
return ptr;
}
return NULL;
}
det *insert(char *name, float cT, float tT)
{
det *new;
unsigned hashval;
if ((new = lookup(name)) == NULL)
{
new = (det *)malloc(sizeof(new));
if (new == NULL || (new->name = str_dup(name)) == NULL)
return NULL;
hashval = hash(name);
new->next = hashtab[hashval];
hashtab[hashval] = new;
new->checkTotal += cT;
new->tipTotal += tT;
new->numReciepts++;
printf("Details of '%s' inserted.\n", name);
}
else
{
new->checkTotal += cT;
new->tipTotal += tT;
new->numReciepts++;
printf("Details of '%s' updated.\n", name);
}
}
char *str_dup(char *s)
{
char *p;
p = (char *)malloc(strlen(s) + 1);
if (p != NULL)
strcpy(p, s);
return p;
}
void printData(char *p)
{
det *ptr;
if ((ptr = lookup(p)) != NULL)
{
printf("Emplyee Name : %s\n", ptr->name);
printf("Total amount : %6.2f\n", ptr->checkTotal);
printf("Total tip : %6.2f\n", ptr->tipTotal);
printf("Total reciepts: %6.2d\n", ptr->numReciepts);
}
else
{
printf("Employee '%s' does not exist.\n", p);
return;
}
}
Without the inclusion of scanf() in else if:main, every thing works fine. Calling printData() with a hard coded string also works.
Inclusion of scanf() in else if:main results in segmentation fault after prompting for name.
I have tried and can not think of the reason. As far as I know:
my code in if:main is not accessing anything in else if:main.
if should not break because of something wrong in else if even if it is wrong. (at least in this scenario, or as far as my understanding goes)
Thanks and any tips for future from experts are appreciated!
P.S: scanf():if is working perfectly.

My code crashes after going into the insertHash function

My code below is taking a text file and hashing it, keys will be English words, values will be the Spanish translation.
My code crashes when it goes into the function insertHash, specifically the while loop below
while(hashTable[hashIndex].marker == 1)
{
printf("%d loop of hash index \n", i);
hashIndex = (hashIndex+1)%tableSize;
i++;
}
Please ignore the i++ and printf, those are for debugging purposes.
The function itself does not even go through one iteration, just crashes.
Any help is appreciated, code is below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int numofEle = 0;
const int STEPSIZE = 100;
//Hash table structure
struct node *hashTable;
struct node{
int marker;
char *key;
char *value;
};
//function declaration
char **loadfile(char *filename, int *len);
//Hash function for strings;
unsigned long hash(unsigned char *str)
{
unsigned long hash = 5381;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
//Function to insert elements in hash table
void insertHash(int len, char *words){
printf("Just entered insert hash function \n");
int hashKey, hashIndex;
int tableSize = len;
printf("before hashing\n");
hashKey = hash(words);
printf("after hashing\n");
hashIndex = hashKey % tableSize;
printf("After hash index \n");
if(numofEle == tableSize)
{
printf("The hash table is full\n.");
return;
}
printf("before checking for marker\n");
while(hashTable[hashIndex].marker == 1)
{
hashIndex = (hashIndex+1)%tableSize;
}
printf("After checking index \n");
strcpy(hashTable[hashIndex].key, strtok(words, "\t"));
strcpy(hashTable[hashIndex].value, strtok(NULL, "\t"));
hashTable[hashIndex].marker = 1;
printf("After assigning variables to table \n");
numofEle++;
return;
}
//Function to search for element
void searchElement(char *key, int len, int *totalProbe)
{
int count = 0;
int probe = 0;
int flag = 0;
char search;
int hashKey = hash(key);
int tableSize = len;
int hashIndex = hashKey % tableSize;
if(numofEle == 0)
{
printf("Hash Table is empty\n.");
return;
}
printf("Probes| keys\n");
printf(" %d| 0\n", probe);
while(hashTable[hashIndex].marker != 0 && count <= tableSize)
{
probe++;
if(hashTable[hashIndex].key == key)
{
printf("The word %s ", key);
printf("translate to %s.\n", hashTable[hashIndex].value);
flag = 1;
break;
}
else
{
printf(" %d| %d\n", probe, hashIndex);
}
hashIndex = (hashIndex+1) % tableSize;
}
if(!flag)
{
printf("Given data is not here\n.");
}
*totalProbe = probe;
return;
}
int main(int argc, char *argv[])
{
//Check for readable input
if(argc == 1)
{
fprintf(stderr, "Must supply a file name to read.\n");
exit(1);
}
int i, totalProbe;
int len = 0;
//Function to read text into array
char **words = loadfile(argv[1], &len);
printf("After loading files\n ");
//allocating memory for hash table and elements
struct node *hashTable = malloc(sizeof(struct node)* len);
printf("After struct allocation\n");
for(i = 0; i < len; i++)
{
hashTable[i].key = malloc(300 * sizeof(char));
hashTable[i].value = malloc(300 * sizeof(char));
hashTable[i].marker =(int*)malloc(sizeof(int));
}
for(i = 0; i < len; i++)
{
hashTable[i].marker = 0;
}
printf("After allocation for table elements\n");
//Loop to hash and insert elements
int totalHash = len;
for(i = 0; i < len; i++)
{
insertHash(len, words[i]);
totalHash--;
}
printf("After hashing words");
char input[100];
printf("Hash Table:\n");
printf("total NOT hashed: %d out of %d\n", totalHash, len);
printf("Please enter key: \n");
scanf("%s", input);
searchElement(input, len, &totalProbe);
printf("max_run of probes = %d\n", totalProbe);
return (EXIT_SUCCESS);
}
//Reads large files into array
char **loadfile(char *filename, int *len)
{
FILE *fp = fopen(filename, "r");
if(!fp)
{
fprintf(stderr, "Can't open %s for reading.\n", filename);
return NULL;
}
int arrlen = STEPSIZE;
//Allocate space for 100 char pointers.
char **lines = (char**)malloc(arrlen*sizeof(char*));
char buff[10000];
int i = 0;
while(fgets(buff, 10000, fp))
{
//Check for full array, if so, extend the array
if(i == arrlen)
{
arrlen += STEPSIZE;
char **newlines = realloc(lines, arrlen*sizeof(char*));
if(!newlines)
{
fprintf(stderr, "Can't reallocate\n");
exit(1);
}
lines = newlines;
}
// trim off \0 at the end
buff[strlen(buff)-1] = '\0';
//get length of buffer
int blen = strlen(buff);
char *str = (char*)malloc((blen+1)*sizeof(char));
//copy string from buff to structure
strcpy(str, buff);
lines[i] = str;
i++;
}
*len = i; //Set length of char pointers
return lines;
}
Two things :
1.You need to declare struct node *hashTable below the structure definition,
//Hash table structure
//struct node *hashTable; <--- incorrect
struct node{
int marker;
char *key;
char *value;
};
struct node *hashTable;
2.You are re-declaring struct node *hashTable in main().
struct node *hashTable = malloc(sizeof(struct node)* len);
The scope of this pointer will be local.
You have already declared struct node *hashTable globally.
Use :
hashTable = (struct node *)malloc(sizeof(struct node)* len);
3.why are you dynamically allocating memory for marker? It is an int member of struct node. It has sizeof(int) bytes of memory.
hashTable[i].marker =(int*)malloc(sizeof(int)); ---> Not needed. You can comment it.

C: Segmentation fault with printing Link List

I'm pretty new to C, but I wanted to build a program that could allows users store ip addresses obtained from a traceroute/tracert that is first stored into a text file. It then allows them to print the next/previous hop. I used a linked list, but the printing gives me a segmentation error.
I tried looking through it but I can't find any error, would someone point out my error and guide me? Thanks in advance!!
(Sorry for the poor indentation!!)
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
int id = 0;
int list = 0;
int nodes = 0;
FILE *readFile(char *fileName)
{
FILE *rawdata = fopen(fileName, "r");
return rawdata;
}
void printMenu()
{
printf(" ========== MENU =============\n\n");
printf("1. Report ID of Previous Hops of a network node\n");
printf("2. Identify the next hops of a network node\n");
printf("3. Quit\n");
}
int getInput()
{
int choice;
printf("Please select your choice (1 to 3) =>: ");
scanf("%d", &choice);
return choice;
}
struct NodeInfo {
int ID;
int IP1;
int IP2;
int IP3;
int IP4;
struct NodeInfo *next;
struct NodeInfo *prev;
};
typedef struct NodeInfo Node;
Node *Topology;
Node *createNode(int ip1, int ip2, int ip3, int ip4)
{
Node *newNode = malloc(sizeof(Node));
newNode->IP1 = ip1;
newNode->IP2 = ip2;
newNode->IP3 = ip3;
newNode->IP4 = ip4;
newNode->next = 0; // NULL Pointer
newNode->prev = 0; // NULL Pointer
return newNode;
}
void addToBack(Node * tempnode)
{
Node *n = Topology;
Node *tail = 0;
while (n != NULL) {
tail = n;
n = n->next;
}
tail->next = tempnode;
tempnode->prev = tail;
}
void printFile(FILE * newFile)
{
char data[256], nth1[50], nth2[50], nth3[50], nth4[50], nth5[50],
nth6[50], nth7[50], ip[50], ip2[15], ip2new[14];
int linecount = -1, strlength;
int ip1, ip2x, ip3, ip4;
int ip11, ip21, ip31, ip41;
if (newFile == NULL) {
printf("There is an error with opening this file\n");
} else {
while (fgets(data, 256, newFile) != NULL) {
if (linecount != 3) {
linecount++;
continue;
} else {
if (linecount == 3 && data[2] != '\0') {
sscanf(data, "%s %s %s %s %s %s %s %s", nth1, nth2, nth3, nth4,
nth5, nth6, nth7, ip);
sscanf(data, "%s %s %s %s %s %s %s %d.%d.%d.%d", nth1, nth2,
nth3, nth4, nth5, nth6, nth7, &ip1, &ip2x, &ip3, &ip4);
if ((ip[0] <= 'z' && ip[0] >= 'a')
|| (ip[0] <= 'Z' && ip[0] >= 'A')) {
sscanf(data, "%s %s %s %s %s %s %s %s %s",
nth1, nth2, nth3, nth4, nth5, nth6, nth7, ip, ip2);
//Rescanning for anomaly results with additional hostname
strncpy(ip2new, ip2 + 1, strlen(ip2) - 2);
ip2new[strlen(ip2) - 2] = '\0';
int i;
char *temp;
char *ipcmp[4];
i = 0;
temp = strtok(ip2new, ".");
while (temp != NULL) {
ipcmp[i++] = temp;
temp = strtok(NULL, ".");
}
Node *tempnode = createNode(ip2new);
if (Topology != 0) {
addToBack(tempnode);
} else {
Topology = tempnode;
}
} else {
printf("%s\n", ip);
printf("%d.%d.%d.%d\n", ip1, ip2x, ip3, ip4);
Node *tempnode2 = createNode(ip);
if (Topology != 0) {
addToBack(tempnode2);
} else {
Topology = tempnode2;
}
continue;
}
}
if (linecount == 3 && data[2] == '\0') {
linecount = -2;
printf("\n");
}
}
}
}
}
void printNodes()
{
Node *n = Topology;
while (n != 0) {
printf("The node is %d.%d.%d.%d\n", n->IP1, n->IP2, n->IP3, n->IP4);
n = n->next; // Jump to next node
}
}
int main(int argc, char *argv[])
{
int option, fail;
FILE *filedata;
char *file;
file = argv[1];
filedata = readFile(file); //open file
printFile(filedata); //prints the ip addresses
do {
printMenu();
option = getInput();
switch (option) {
case 1:
printf("You have selected 1\n\n");
fail = 0;
printNodes();
break;
case 2:
printf("You have selected 2\n\n");
fail = 0;
break;
case 3:
fail = 1;
break;
default:
printf("Please enter a valid choice (1-3) \n");
fail = 0;
break;
}
} while (fail != 1);
while (Topology != 0) {
free(Topology);
Topology = Topology->next;
}
}
Your create node method have 4 parameters:
Node *createNode(int ip1, int ip2, int ip3, int ip4)
But you invoke this method by passing only one parameter:
Node *tempnode = createNode(ip2new);
Node *tempnode2 = createNode(ip);
Also you pass arrays when your method accept only integers.
This is at least two sources of errors in your code.
There are two corrections that I can spot. First is that you are calling createNode() with the wrong number of arguments. You have defined createNode() to take 4 integral arguments, but in each of your calls, you are passing it a string argument. The compiler should have given you a diagnostic about this issue (my compiler refuses to compile the code). You should never ignore a compiler diagnostic (at least, not without first fully understanding what the diagnostic means).
Change those calls to use the 4 integral variables that you scanned.
Node *tempnode = createNode(ip1, ip2x, ip3, ip4);
Node *tempnode2 = createNode(ip1, ip2x, ip3, ip4);
The second error is that your if (linecount != 3) { only allows you to process data when linecount is equal to 3, which is probably not what you want to do. You probably mean to process all lines of data after linecount becomes 3.
if (linecount < 3) {
linecount++;
continue;
} else {
I find it odd that you have initialized linecount to -1, but it just means you won't start processing the file until you reach the fourth line of input.
As has been mentioned by others, you cannot read from memory that has already been freed. Doing so causes undefined behavior. In your loop to release the memory held by Topology, save the pointer to the next item before freeing the current item.
while (Topology != 0) {
void *cur = Topology;
Topology = Topology->next;
free(cur);
}
There's a few issues here.
You mix your usage of NULL and 0. While both will work, in C it is idiomatic to use NULL, and it is best to be consistent in your usage.
Your createNode function expects 4 integers, but your code is calling this function and only providing one argument.
You have undefined behaviour in your loop:
while (Topology != 0) {
free(Topology);
Topology = Topology->next;
}
It is undefined behaviour to access Topology once it has been freed. In your case, you are attempting to access the next member of Topology after it has been freed.

Resources