Read data from file into structure - c

I am working on a program that can process structure items in linkedlist/nodes.
I have most of the functions running fine, however am stuck on how to read from a txt file into a structure (the readFromFile function).
I have been reading around but am still quite confused, mainly on how to write this as a function instead of in main, and also reading into a structure
any help would be appreciated.
EDIT:
I cannot seem to get the functions in the answers to work at the moment, so I am changing to trying to make the program read from txt in main.
I could open the file, but the problem is:
How do I read data into my linked list?
(code has been modified)
The text file I am reading from is formatted like this:
#1 Flat Blade Screwdriver
12489
36
.65
1.75
#2 Flat Blade Screwdriver
12488
24
.70
1.85
#1 Phillips Screwdriver
12456
27
0.67
1.80
#2 Phillips Screwdriver
12455
17
0.81
2.00
Claw Hammer
03448
14
3.27
4.89
Tack Hammer
03442
9
3.55
5.27
Cross Cut Saw
07224
6
6.97
8.25
Rip Saw
07228
5
6.48
7.99
6" Adjustable Wrench
06526
11
3.21
4.50
My program so far:
#include "stdafx.h"
#include <stdlib.h>
typedef struct inventory
{
char invName[36];
int invPartNo;
int invQOH;
float invUnitCost;
float invPrice;
}stock;
struct NODE
{
union
{
int nodeCounter;
void *dataitem;
}item;
struct NODE *link;
};
struct NODE *InitList();
void DisplayNode(struct inventory *);
struct inventory * ReadData(FILE *);
void DisplayList(struct NODE *);
struct NODE* GetNode(FILE *);
void Add2List(struct NODE *, struct NODE *);
struct NODE* SearchList(struct NODE *, int );
void DeleteNode(struct NODE *, int );
int main(int argc, char* argv[])
{
struct NODE *header;
header = InitList();
char ch, file_name[25];
FILE *fp;
printf("Enter the name of file you wish to see\n");
gets(file_name);
fp = fopen(file_name,"r"); // read mode
if( fp == NULL )
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
printf("The contents of %s file are :\n", file_name);
while( ( ch = fgetc(fp) ) != EOF )
{
//what to put here?
}
fclose(fp);
DisplayList(header);
return 0;
}
struct NODE *InitList()
{
struct NODE *temp = (struct NODE*)malloc(sizeof NODE);
temp->item.nodeCounter = 0;
temp->link = NULL;
return temp;
}
void Add2List(struct NODE *start, struct NODE *NewNode)
{
struct NODE *current = start;
while (current->link != NULL)
current = current->link;
current->link = NewNode;
NewNode->link = NULL;
start->item.nodeCounter++;
}
struct NODE* GetNode(FILE *fptr)
{
struct NODE *temp = (struct NODE*)malloc(sizeof NODE);
temp->item.dataitem = ReadData(fptr);
temp->link = NULL;
return temp;
}
void DisplayList(struct NODE *start)
{
struct NODE *current = start->link;
while (current != NULL)
{
DisplayNode((struct inventory *)current->item.dataitem);
current = current->link;
}
}
void DisplayNode(struct inventory *stuff)
{
/*
char invName[36];
int invPartNo;
int invQOH;
float invUnitCost;
float invPrice;
*/
printf("Name: %s", stuff->invName);
printf("Part Number: %d", stuff->invPartNo);
printf("Quantity on hand: %d", stuff->invQOH);
printf("Unit Cost: %0.2f", stuff->invUnitCost);
printf("Price %0.2f", stuff->invPrice);
}
struct inventory * ReadData(FILE *fptr)
{
struct inventory *temp = (struct inventory *)malloc(sizeof inventory);
if(fptr==stdin)
printf("Enter item name: ");
fscanf_s(fptr, "%s", temp->invName);
if(fptr==stdin)
printf("Enter item part number: ");
fscanf_s(fptr, "%d", &temp->invPartNo);
if(fptr==stdin)
printf("Enter item quantity on hand: ");
fscanf_s(fptr, "%d", &temp->invQOH);
if(fptr==stdin)
printf("Enter item unit cost: ");
fscanf_s(fptr, "%f", &temp->invUnitCost);
if(fptr==stdin)
printf("Enter item price: ");
fscanf_s(fptr, "%f", &temp->invPrice);
return temp;
}
struct NODE* SearchList(struct NODE *start, int oldData)
{
struct NODE* current = start;
struct inventory * st = (struct inventory *)current->link->item.dataitem;
while (st->invPartNo != oldData && current != NULL)
{
current = current->link;
if(current->link)
st = (struct inventory *)current->link->item.dataitem;
}
return current;
}
void DeleteNode(struct NODE *start, int oldData)
{
struct NODE *current, *oldNode;
current = SearchList( start, oldData);
oldNode = current->link;
current->link = oldNode->link;
free(oldNode);
start->item.nodeCounter -= 1;
}

You can use fscanf() and fgets() to read the data as,
void readFromFile( )
{
stock array[20];
int i,j;
i=0;
fp = fopen("input.txt", "r");
if( fp != NULL ){
while ( !feof(fp ) ){
fgets(array[i].invName,sizeof array[i].invName,fp);
fscanf(fp,"%d %d %f %f ",&array[i].invPartNo,&array[i].invQOH,&array[i].invUnitCost,&array[i].invPrice);
i++;
}
}
The array[] will have the data and i will be number of struct data read.
Here all spaces in fscanf() are put to skip the [enter] character since the data is in different lines.
read about fscanf() with its format matching and fgets() it can help in reading files.
To avoid feof() can use,
while (fgets(array[i].invName,sizeof array[i].invName,fp)) {
fscanf(fp,"%d %d %f %f ",&array[i].invPartNo,&array[i].invQOH,&array[i].invUnitCost,&array[i].invPrice);
i++;
}
for This particular file format.

The algorithm:
Open the text file in 'text' 'read' mode.
Create an array of stock structures, if you know number of items beforehand, else use a linked list with each node of type stock.
To read data from file to corresponding field you can use fscanf .
When you think you have finished reading data, close the file.
Notes:
The file pointer is automatically incremented so you need not worry about incrementing it to read next set of data.
Do not forget to close the file.
To check whether the file handling functions are working fine, do check the return value of all the functions.
Important:
Since your invPartNo field in the file has integer data starting with 0, you may not want to read it as integer, otherwise it will be treated as "octal number" not a decimal number.

Your _tmain could look like below, this code assumes that the contents in the file are complete (i.e. contains the correct number of lines):
int _tmain(int argc, _TCHAR* argv[])
{ struct NODE *header = InitList();
if (argc > 1)
{ FILE *f;
if ((f = fopen(argv[1], "rt") == NULL)
{ printf(_T("Could not open file %s\n"), argv[1]);
return 1;
}
while (!feof(f))
Add2List(header, GetNode(f));
fclose(f);
}
else
{ int PCounter = 2;
while (PCounter--)
Add2List(header,GetNode(stdin));
}
DisplayList(header);
return 0;
}
EDIT:
Run the program from the command-prompt and pass the file name as a parameter

Related

Why is my Professor's Linked List Printing Backwards?

I have a project that I'm working on for a Systems Programming course. I'm building off of my professor's code. (Please don't mind her lack of labelling, etc. - I'm gonna try to clean this up as best as I can.)
Does anybody know why her linked list code is printing backwards?
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
char name[15];
char title[15];
int year;
struct Node *next;
struct Node *prev;
};
typedef struct Node *Box;
Box print_list(Box pointer);
Box insert_node(FILE *inputp);
int main() {
Box head = NULL, temp;
FILE *inputp, *outputp;
int i;
inputp = fopen("input.txt", "r");
outputp = fopen("output.txt", "w");
head = insert_node(inputp);
for (i = 0; i < 4; i++) {
temp = insert_node(inputp);
temp->next = head;
head = temp;
}
print_list(head);
return 0;
}
Box print_list(Box pointer) {
Box here = pointer;
while (here != NULL) {
printf("%s, %s, %d \n", here->name, here->title, here->year);
here = here->next;
}
return pointer;
}
Box insert_node(FILE *inputp) {
Box temp = NULL;
temp = (Box)malloc(sizeof(struct Node));
fscanf(inputp, "%s", &temp->name);
fscanf(inputp, "%s", &temp->title);
fscanf(inputp, " %d", &temp->year);
temp->next = NULL;
temp->prev = NULL;
return temp;
}
This program's purpose is to read a .txt file "playlist" of songs and create a linked list out of them. The input is:
Rachmaninov Concerto_No_2 1999
Mozart Symphony_No_41 2000
Vivaldi The_Seasons 2003
Beethoven Symphony_No_5 1994
Bach Toccatas 2005
While the program outputs:
Bach, Toccatas, 2005
Beethoven, Symphony_No_5, 1994
Vivaldi, The_Seasons, 2003
Mozart, Symphony_No_41, 2000
Rachmaninov, Concerto_No_2, 1999
(I also don't know why she included an output file in the code, all of the output is in the console, not stored in a file. Ignore that.)
The list prints in reverse order because you insert each new node at the beginning of the list. You should use a tail pointer to keep track of the end of the list.
Also note these remarks:
both the next and the prev links should be updated.
hiding pointers behind typedefs as in typedef struct Node *Box; is considered bad practice because it is confusing and error prone.
insert_node is a confusing name for a function that merely allocates a new node from file data.
insert_node should test if fscanf() succeeded at reading the data
fscanf(inputp, "%s", &temp->name); has undefined behavior if the name of the composer exceeds 14 bytes. The same applies to the title. The maximum number of characters to store into the destination arrays before the null terminator should be specified as %14s and these arrays should be defined with a larger length.
main should check if a node was successfully allocated and initialized from file data. Instead of hardcoding the number of nodes, one should iterate as long as nodes can be read from the file.
Here is a modified version:
#include <error.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
char name[40];
char title[40];
int year;
struct Node *next;
struct Node *prev;
};
void print_list(const Node *pointer);
Node *read_node(FILE *inputp);
int main() {
Node *head = NULL;
Node *tail = NULL;
Node *node;
FILE *inputp, *outputp;
int i;
inputp = fopen("input.txt", "r");
if (!inputp) {
fprintf(stderr, "cannot open input.txt: %s\n", strerror(errno));
return 1;
}
outputp = fopen("output.txt", "w");
if (!outputp) {
fprintf(stderr, "cannot open output.txt: %s\n", strerror(errno));
return 1;
}
while ((node = read_node(inputp)) != NULL) {
if (!head) {
head = tail = node;
} else {
node->prev = tail;
tail = tail->next = node;
}
}
print_list(head);
// should free node list
return 0;
}
void print_list(const Node *pointer) {
while (pointer != NULL) {
printf("%s, %s, %d\n", pointer->name, pointer->title, pointer->year);
pointer = pointer->next;
}
}
Node *read_node(FILE *inputp) {
Node *temp = malloc(sizeof(*temp));
if (temp != NULL
&& fscanf(inputp, "%39s%39s%d", &temp->name, &temp->title, &temp->year) == 3) {
temp->next = NULL;
temp->prev = NULL;
return temp;
} else {
free(temp);
return NULL;
}
}

How can I create a BST by reading from a text file?

I have to create a database of students, that contains their ID, name, surname, and grade. This information is read from a txt file that looks like this:
AE797989 Spears Michael 10.00
AA566734 Walsh Brad 10.00
AE808090 Jones Dimitris 5.00
...
and contains 19 students
I have to read each line of the file and create a binary search tree based on their ID. There seems to be a problem when I'm creating a node, because when I try to search a student I can't. Here's my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
struct node
{
struct node *left;
char ID[100];
char NAME[100];
char LAST_NAME[100];
float Grade;
struct node *right;
};
struct node *newNode(char, char, char, float);
struct node *insertNode(struct node node, char id, char name, char last_name, float grade);
void search(struct node *root, char *ID);
void deleteFromBST(char *ID);
int main()
{
char ID[100];
int insertDone = 0;
int ch;
while (1) {
printf("\n1. Insertion\t2. Deletion\n");
printf("3. Searching\t4. Display In Order\n5. Edit\t 6. Exit\n");
printf("Enter your choice:");
scanf("%d", &ch);
switch (ch) {
case 1:
if (insertDone)
puts("Inserton was already done");
else {
struct node* insertNode(struct node *node,char *id, char *name, char *last_name, float grade)
{
if (node == NULL)
return newNode(*id,*name,*last_name,grade);
if ( strcmp(id , node->ID) < 0)
node->left = insertNode(node->left,id,name,last_name,grade);
else if ( strcmp( id , node->ID) >= 0)
node->right = insertNode(node->right,id,name,last_name,grade);
return node;
}
insertDone = 1;
}
break;
case 2:
break;
case 3:
printf("Enter the AM to search:");
scanf("%99s", ID);
void search(struct node *root, char *ID)
{
int flag=0;
if (!root)
{
printf("Search element unavailable in BST\n");
return;
}
while (root != NULL) {
if (strcmp(root->ID, ID) == 0) {
printf("Student ID : %s\n", root->ID);
printf("First Name : %s\n", root->NAME);
printf("Last Name : %s\n", root->LAST_NAME);
printf("grade : %lg\n", root->Grade);
flag = 1;
break;
}
else if (strcmp(ID , root->ID) > 0)
{
return search(root->right,ID);
}
else if(strcmp(ID , root->ID) < 0)
{
return search(root->left,ID);
}
if (!flag)
printf("Search element unavailable in BST\n");
}
}
break;
case 4:
//display();
break;
case 5:
break;
case 6:
exit(0);
default:
printf("U have entered wrong option!!\n");
break;
}
}
struct node* newNode(char *id, char *name, char *last_name, float grade)
{
struct node *newnode = malloc(sizeof(struct node));
struct node Node;
FILE *fp;
fp = fopen ("Foitites-Vathmologio-DS.txt","rb");
if (fp == NULL)
{
fprintf(stderr,"Could not open file");
return;
}
char line[4096];
while (fgets(line, sizeof line,fp))
{
size_t len = strlen(line);
if (len && (line[len - 1] == '\n'))
{
/* incomplete line */
if (sscanf(line,"%99s %99s %99s %f",Node.ID, Node.NAME, Node.LAST_NAME, &Node.Grade) != 4)
{
puts("invalid file");
return;
}
strcpy(newnode->ID , id);
strcpy(newnode->NAME , name);
strcpy(newnode->LAST_NAME , last_name);
newnode->Grade = grade;
newnode->left = newnode->right = NULL;
return newnode;
}
}
fclose(fp);
}
return 0;
}
I get no error messages.. thank you for your time!
If you get no error message with this code, I would suggest you to use a different compiler. Mine chokes in main at:
switch (ch) {
case 1:
if (insertDone)
puts("Inserton was already done");
else {
struct node* insertNode(struct node *node, char *id, char *name,
char *last_name, float grade) // ERROR HERE
{
if (node == NULL)
It looks that you have copied the definition of the function instead of just calling it.
My problem is that you managed to write many different errors in a single program. And the global design of how the program should be structured is not clear: it looks like you started coding without first writing on a paper (yes papers and pencils are still very good tools for beginners) what each function should do, what was its its inputs and what should be its outputs and eventually what data it was including (for example what part is in charge of the file name). Of course, I could write a BST program for you, but you would not learn anything from that.
So here are some hints:
in a BST, you insert new data under existing nodes so you will need a function insertNode with following input parameters: the current root node (or NULL at first time), the id, name, last_name and grade to insert. You should build a new copy of the input strings (strdup is your friend). This function will allocate a new structure, fills is fields, and either return it if the current root was NULL, or insert it at its correct place in the existing tree
you want to process all lines from a file. You will need a function that open the file, read it line by line and will use previous one to insert the new record in the BST
BTW a function definition is something like
struct node *insert(struct node *root, const char id*, const char *name, const char *last_name, float grade) {
struct node * newnode = malloc(sizeof *newnode);
...
return root;
}
outside of any other function definition, while a function call will be like:
struc node *root = NULL;
char id[100], name[100], last_name[100];
float grade;
...
if (sscanf(line,"%99s %99s %99s %f",id, name, last_name, &grade)) != 4)
{
puts("invalid file");
return;
}
root = insert(root, id, name, last_name, grade); // here is the function call

Dynamic list in C headache, printing list in reverse? Why?

I'm trying to learn how to work with dynamic lists in C, but can't seem to wrap my head around it - so help would be appreaciated. I've got a struct that has some info that i'm reading from a txt file in the command line and would need to add the info to a dynamic list..
this is what i have so far. I'm at a loss with pointers and don't know if the arguments are correct and where to go from there.
Have spent the better part of the weekend looking for a way to get this done. It isn't hard as I get the concept, just that the nuts and bolts of it are just eluding me...
#include <stdio.h>
#include <stdlib.h>
#define SIZE_MAX 20
#define BUFFER_MAX 256
FILE *file;
/*struct*/
struct student {
char name[SIZE_MAX];
int grade;
struct student *next;
};
typedef struct student Student;
int addToList(Student **head, char *, int);
void printList(Student **head);
void releaseMem(Student **head);
/*functions*/
void addToList(Student **head, char *name, int grade ){
//???
}
/*Main*/
int main (int argc, char *argv[]){
Student *head=NULL,*tail=NULL;
int grade = 100 ;
char buffer [BUFFER_MAX];
char name[SIZE_MAX];
/*opening file*/
file = fopen(argv[1], "r");
if (file == NULL){
printf("\n\tWARNING: No data found.\n");
exit(1);
}
else{
printf("Reading file %s \n",argv[1]);
}
/*creating first node*/
Student* new_student(Student*)malloc(sizeof(Student));
while(fgets(buffer, BUFFER_MAX,file)!= NULL){
sscanf(buffer,"%s%d",name,&grade);
//printf("%s %d\n",string, grade);
addToList(&head,name,grade);
}
return 0;
}
Edit: So far I've managed to add the data from the file to a dynamic list (thank you for the help). Here is what I have:
#include <stdio.h>
#include <stdlib.h>
#define SIZE_MAX 20
#define BUFFER_MAX 256
FILE *file;
/*Struct*/
struct student {
char name[SIZE_MAX];
int grade;
struct student *next;
};
typedef struct student Student;
int addToList(Student **head, char *, int);
void printList(Student *head);
void releaseMem(Student *head);
/*functions*/
int addToList(Student **head, char *name, int grade ){
Student *new_student = malloc( sizeof( Student ) );
{
Student *new_student = malloc( sizeof( Student ) );
int success = new_student != NULL;
if ( success )
{
strcpy( new_student->name, name );
new_student->grade = grade;
new_student->next = *head;
*head = new_student;
}
return success;
}
}
void printList(Student *head){
Student * current = head;
int i = 1;
while (current != NULL) {
printf("%d. Student: %s grade %d\n",i,current->name ,current->grade);
i++;
current = current->next;
}
}
void releaseMem(Student *head){
Student * current = head;
while (current != NULL) {
free(current);
current = current->next;
}
printf("mem cleared.\n");
}
/*Main*/
int main (int argc, char *argv[]){
Student *head=NULL,*first=NULL, *temp = NULL;
int grade = 100 ;
char buffer [BUFFER_MAX];
char name[SIZE_MAX];
/*opening file*/
file = fopen(argv[1], "r");
if (file == NULL){
printf("\n\tWARNING: No data found.\n");
exit(1);
}
else{
printf("reading file %s. \n",argv[1]);
}
printf("data added to list.\n");
while(fgets(buffer, BUFFER_MAX,file)!= NULL){
sscanf(buffer,"%s%d",name,&grade);
addToList(&head,name,grade);
}
printList(head);
releaseMem(head);
return 0;
}
Works (almost) like i'd like it to work. For some reason the printList function prints the content of the file in reverse order and after fiddling with it for some time I don't know how to print it from the beginning to the end instead from the end to the beginning. I suppose it has to do with pointers but more than that i'm at a loss what to do... What am I missing here? How would I go about reversing the printing order with keeping the (formatting) as it currently is?
you should allocate new students in the student list and place it to the last member's next like this :
//since we are adding new members after the last member in linked list
//we are not going to change value of head so sending **head is not useful
void addToList(Student *head,char *name,int grade){
Student *node;
for(node = head; node->next != NULL; node = node->next );
// now node points the last member of your linked list
// now we are adding new student to the linked list with allocating memory
node->next = (Student *)malloc(sizeof(student));
node->next->grade = grade;
strcpy(node->next->name,name);
}
The program will not compile at least because this statement
Student* new_student(Student*)malloc(sizeof(Student));
is invalid. And even if to write it like
Student* new_student = (Student*)malloc(sizeof(Student));
it does not make sense because new items should be added to the list by using the function addToList.
The declaration of the variable tail also does not make sense because it is impossible to pass it to the function (as it is declared) addToList along with the head.
As for the function itself then it is better to declare it the following way
int addToList( Student **head, const char *name, int grade );
The function can be defined like
int addToList( Student **head, const char *name, int grade )
{
Student *new_student = malloc( sizeof( Student ) );
int success = new_student != NULL;
if ( success )
{
strcpy( new_student->name, name );
// or
// strncpy( new_student->name, name, SIZE_MAX );
// new_student->name[SIZE_MAX - 1] = '\0';
new_student->grade = grade;
new_student->next = *head;
*head = new_student;
}
return success;
}

C programming. File I/O, Link List and Struct

I have an assignment that requires me to edit a C program provided to me so that it can read from a text document where each line looks like:
int%char%char%Double%int%int%int
with any number of lines and an empty line at the end of the file.
This text file is passed to this program:
#include <stdlib.h>
#include <stdio.h>
struct node{
int element;
struct node * next;
};
// node structure
struct node * head = NULL; // head node
void add_node(int num) {
if (head == NULL){
head = (struct node *) malloc(sizeof(struct node));
head->element = num;
}
else{
struct node * p = head;
while(p->next != NULL)
p = p->next;
p->next = (struct node *) malloc(sizeof(struct node));
p->next->element = num;
}
}
void print_list() {
struct node * p = head;
while(p != NULL){
printf("%d ", p->element);
p = p->next;
}
}
void free_list() {
struct node * p = head;
while(head != NULL){
p = head->next;
free(head);
head = p;
}
}
int main(int argc, char const *argv[]) {
int n, i;
for (i = 0; i < 10; i++) {
scanf("%d", &n);
add_node(n);
}
print_list();
free_list();
return 0;
}
I need to edit this program to include the 7 fields from the file (ID, Category, Detail, Amount, Year, Month, Day) in the struct node. Then have it read from the text file (File_name.txt for now) add the fields without the % separator between them in the struct node, and then print them out in order as such (RecordID: (ID) Category: (category) Amount: $(amount) Date: (Month)-(Day)-(Year) Detail: (detail)) and free all pointers before the program is terminated. I don't expect you all to do the assignment for me, its just that I have no idea how C programming works and I need to do this so if anyone can help point me in the right direction on how to go about this it would be much appreciated.
From what I see.
You'd be having to Create a struct of your own with specified variables from the file.
Read every line and intelligently parse them... the function strtok should do be able to do this in C.
Extract variable to store in created struct using a function which should not be too hard to write
And the rest you can or should be able to take care of
This might have not been as useful as you hope would buh you can try to make me understand so I can help do better
This should get you started on the right path:
int main(int argc, char const *argv[]) {
char filename[100];
printf("Enter the name of the file: ");
/*stdin is a FILE pointer to standard input */
fgets(filename, 100, stdin);
/*Now you open the file for reading "r" means read mode*/
FILE *fp = fopen(filename, "r");
/*Basic error checking*/
if (!fp) {
perror("File opening failed");
return EXIT_FAILURE; /*This is macro defined in stdlib.h*/
}
int id, year, month, day;
char category, detail;
double amt;
/* Here the fun begins. Use fscanf*/
while(fscanf(fp, "ID(%d)%%Category(%c)%%Detail(%c)%%Amount(%lf)%%Year(%d)%%Month(%d)%%Day(%d)",
&id, &category, &detail, &amt, &year, &month, &day) == 7) {
/* Do what ever you want with those values - create a node or something*/
}
/* Finally close the file */
fclose(fp);
return 0;
}
Remember that each time through the loop, the variables change.

Scanf Validation

Can someone help me validate the inputs for the Scanf's i have below. I want the programme to ask for the data to be re-entered if the Scanf's are within an incorrect range or not an interger. I put in a do while loop before with an if statement but when i compiled it the first printf and scanf just looped
#include <stdio.h>
#include <stdlib.h>
int MenuLoop = 0;
int MaxPackets = 4;
int currentPackets= 0;
int menu;
/*********************************************************
* Node to represent a Cat which includes a link reference*
* a link list of nodes with a pointer to a Cat Struct *
* would be better but this is for illustartion only! *
**********************************************************/
struct Packet {
int Source;
int Destination;
int Type;
int Port;
char *Data;
struct Packet *next; // Link to next Cat
};
typedef struct Packet node; // Removes the need to constantly refer to struct
/*********************************************************
* Stubs to fully declared functions below *
**********************************************************/
void outputPackets(node **head);
void push(node **head, node **aPacket);
node* pop(node **head);
void AddPacket();
void AddPacket();
void SavePacket();
void ShowCurrent();
void ExitProgramme();
main() {
do{
Menu();
} while(menu<4);
}
void AddPacket(){
int option;
/*********************************************************
* pointers for the link list and the temporary P to *
* insert into the list *
**********************************************************/
node *pPacket, *pHead = NULL;
/*********************************************************
* Create a cat and also check the HEAP had room for it *
**********************************************************/
pPacket = (node *)malloc(sizeof(node));
if (pPacket == NULL)
{
printf("Error: Out of Memory\n");
exit(1);
}
currentPackets++;
printf("Enter Source Number between 1-1024:\n");
scanf("%i", &pPacket->Source);
printf("Enter Destination Number between 1-1024:\n");
scanf("%i", &pPacket->Destination);
printf("Enter Type Number between 0-10:\n");
scanf("%i", &pPacket->Type);
printf("Enter Port Number between 1-1024:\n");
scanf("%i", &pPacket->Port);
printf("Enter Data Numberbetween 1-50:\n");
scanf("%s", &pPacket->Data);
printf("Do you want to Enter another Packet?");
pPacket->next = NULL;
/*********************************************************
* Push the Cat onto the selected Link List, the function *
* is written so the program will support multiple link *
* list if additional 'pHead' pointers are created. *
* Who says you cannot herd cats! *
**********************************************************
* NOTE: The push parameters are using references to the *
* pointers to get round the pass by value problem caused *
* by the way C handles parameters that need to be *
* modified *
**********************************************************/
push(&pHead, &pPacket);
pPacket = (node *)malloc(sizeof(node));
if (pPacket == NULL)
{
printf("Error: Out of Memory\n");
exit(1);
}
outputPackets(&pHead);
/*********************************************************
* Display the Link List 'pHead' is passed as a reference *
**********************************************************/
return 0;
do{
if(currentPackets == MaxPackets);
{
printf("Packet limit reached please save\n");
}
}while(currentPackets<MaxPackets);
return 0;
}
void outputPackets(node **head)
{
/*********************************************************
* Copy Node pointer so as not to overwrite the pHead *
* pointer *
**********************************************************/
node *pos = *head;
/*********************************************************
* Walk the list by following the next pointer *
**********************************************************/
while(pos != NULL) {
printf("Source: %.4i Destination: %.4i Type: %.4i Port: %.4i \n", pos->Source, pos->Destination, pos->Type, pos->Port);
pos = pos->next ;
}
printf("End of List\n\n");
}
void push(node **head, node **aPacket)
{
/*********************************************************
* Add the cat to the head of the list (*aCat) allows the *
* dereferencing of the pointer to a pointer *
**********************************************************/
(*aPacket)->next = *head;
*head = *aPacket;
}
node *pop(node **head)
{
/*********************************************************
* Walk the link list to the last item keeping track of *
* the previous. when you get to the end move the end *
* and spit out the last Cat in the list *
**********************************************************/
node *curr = *head;
node *pos = NULL;
if (curr == NULL)
{
return NULL;
} else {
while (curr->next != NULL)
{
pos = curr;
curr = curr->next;
}
if (pos != NULL) // If there are more cats move the reference
{
pos->next = NULL;
} else { // No Cats left then set the header to NULL (Empty list)
*head = NULL;
}
}
return curr;
}
void SavePacket(){
FILE *inFile ;
char inFileName[10] = { '\0' } ;
printf("Input file name : ") ;
scanf("%s", inFileName) ;
//Open file
inFile = fopen(inFileName, "w+");
if (!inFile)
{
fprintf(stderr, "Unable to open file %s", &inFile);
exit(0);
}
//fprintf(inFile, "Source: %i Destination: %i Type: %i Port: %i \n", pos->Source, pos->Destination, pos->Type, pos->Port);
fclose(inFile);
}
void ShowCurrent(){
}
void ExitProgramme(){}
void Menu(){
printf("********Welcome****** \n");
printf("Creator Ben Armstrong.\n\n");
printf("*Please Choose an option*\n");
printf("1. Add a new packet\n");
printf("2. Save current packet to file\n");
printf("3. Show current list of packets\n");
printf("4. Exit\n");
scanf("%i", &menu);
switch(menu)
{
case 1:
AddPacket();
break;
case 2:
SavePacket();
break;
case 3 :
ShowCurrent();
break;
case 4 :
ExitProgramme();
break;
}
}
This is my full code as u can see im trying to implement a link list which the data has to be validated for
Use the following macro
#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND) \
do {\
char tmp;\
while(((scanf(" "FORM"%c",X,&tmp)!=2 || !isspace(tmp)) && !scanf("%*[^\n]"))\
|| !(COND)) {\
printf("Invalid input, please enter again: ");\
}\
} while(0)
You find in this topic the macro explaination
Example of using it :
int main()
{
.......
printf("Enter Source Number between 1-1024:\n");
SCAN_ONEENTRY_WITHCHECK("%i", &pPacket->Source, (pPacket->Source>=1 && pPacket->Source<=1024);
printf("Enter Destination Number between 1-1024:\n");
SCAN_ONEENTRY_WITHCHECK("%i", &pPacket->Destination, (pPacket->Destination>=1 && pPacket->Destination<=1024);
printf("Enter Type Number between 0-10:\n");
SCAN_ONEENTRY_WITHCHECK("%i", &pPacket->Type, (pPacket->Type>=0 && pPacket->Type<=10);
printf("Enter Port Number between 1-1024:\n");
SCAN_ONEENTRY_WITHCHECK("%i", &pPacket->Port, (pPacket->Port>=1 && pPacket->Port<=1024);
printf("Enter Data Numberbetween 1-50:\n");
SCAN_ONEENTRY_WITHCHECK("%i", &pPacket->Data, (pPacket->Data>=1 && pPacket->Data<=50);
}
Here is one approach using strtol:
#include <stdlib.h>
#include <stdio.h>
struct Packet {
int Source;
int Destination;
int Type;
int Port;
int Data;
};
void func(struct Packet *pPacket) {
char entry[100];
int i;
char *tail;
do {
printf("Enter Source Number between 1-1024:\n");
scanf("%99s", entry);
i = strtol(entry, &tail, 0);
} while (*tail || i < 1 || i > 1024);
pPacket->Source = i;
}
int main(int argc, char* argv[])
{
struct Packet pPacket;
func(&pPacket);
printf("pPacket->Source is now %i.\n", pPacket.Source);
return 0;
}

Resources