How to determine height and length of a 2D array from stdin? - c

My program has to read contents of a file like so:
name_of_program < Test.txt
Test.txt is a 2D array of integers (integers are separated by spaces, sometimes multiple ones, rows of integers are separated by EOL), but of unknown length and height. How do I determine them?
I plan on storing each row in a node of a linked list as an array of integers.
EDIT: My program roughly looks like this:
#include <stdio.h>
#include <stdlib.h>
struct node {
int *val; //stores the row
struct node *next;
};
struct node *addnode(int *val, struct node *next);
struct node *mergesort(struct node *head, int column); //column by which I'll sort it
struct node *merge(struct node *head_one, struct node *head_two, int column);
int main(int column) //number of column to sort by, should run like that "name_of_program column < Test.txt" in Unix systems
{
struct node *head;
struct node *current;
struct node *next;
head = NULL;
/* Reading from stdin line by line, writing it to list and linking nodes - I have only the last bit done */
head = mergesort(head, column);
/* Writing to stdout, row by row of sorted list, I can't do that without the previous bit */
for(current = head; current != NULL; current = next)
next = current->next, free(current);
return 0;
};
struct node *addnode(int *val, struct node *next)
{
struct node *tnode;
tnode = (struct node*)malloc(sizeof(*tnode));
if(tnode != NULL) {
tnode->val = val; //not sure about this line, would it write whole array, or just one element?
tnode->next = next;
};
return tnode;
}
struct node *mergesort(struct node *head, int column)
{
struct node *head_one;
struct node *head_two;
if((head == NULL) || (head->next == NULL))
return head;
head_one = head;
head_two = head->next;
while((head_two != NULL) && (head_two->next != NULL)) {
head = head->next;
head_two = head->next->next;
};
head_two = head->next;
head->next = NULL;
return merge(mergesort(head_one, column), mergesort(head_two, column), column);
}
struct node *merge(struct node *head_one, struct node *head_two, int column)
{
struct node *head_combined;
if(head_one == NULL)
return head_two;
if(head_two == NULL)
return head_one;
if(head_one->val[column] < head_two->val[column]) {
head_combined = head_one;
head_combined->next = merge(head_one->next, head_two, column);
} else {
head_combined = head_two;
head_combined->next = merge(head_one, head_two->next, column);
};
return head_combined;
}

You can start by reading file line by line in C you can use getline function.
You will need to allocate sufficiently large buffer considering maximum length of line.
Process the line, retrieving integers from line, this can be done by looping through line buffer
and skipping white spaces. The integers can be stored either in 2D array or linked list which you can created.

Related

Read access violation when trying to compare int?

I am getting a read access violation and I cant understand why. I though I allocated everything correctly and I shouldn't be reading past the end of anything? Any ideas or help is greatly appreciated.
I am trying to read in a file that has a single integer per line and store those into a binary tree and linked list. The tree actually holds the data and the linked list just holds pointers to the nodes in the tree.
The error happens in the insert() function when data and node->num are being compared.
The newNode() function creates both a tree node and a linked list node, it only returns the tree node because of the double pointer handling the linked list.
// Garrett Manley
// delete these when turning it in
#pragma warning(disable : 4996)
#include <stdio.h>
#include <stdlib.h>
// define structs
struct treeNode {
int num;
struct treeNode *right, *left;
};
struct listNode {
struct treeNode *tNode; // data is a pointer to the tree
struct listNode *next;
};
// creates and returns a new node with given data, also adds node to linked list
struct treeNode *newNode(int data, struct listNode *(*list)) {
// make tree node
struct treeNode *node = malloc(sizeof(struct treeNode));
node->num = data;
node->left = NULL;
node->right = NULL;
// make list node
// insert entry into linked list
struct listNode *newNode;
newNode = malloc(sizeof(struct listNode));
newNode->tNode = node;
newNode->next = *list;
*list = newNode;
return (node);
}
// inserts given node into the tree in sorted order
struct treeNode *insert(struct treeNode *node, int data, struct listNode *(*list)) {
if (node == NULL) { // if the tree is empty return new node
return (newNode(data, list));
} else { // if there is a node use recursion to get to the bottom of the tree and add a node in the right spot
if (data <= node->num) {
node->left = insert(node->left, data, list);
} else {
node->right = insert(node->right, data, list);
}
return (node); // return the (unchanged) node pointer
}
}
// print linked list by looping through list, keep looping until node.next == null
// while looping print like this node.data.data to get the tree nodes data
void printList(struct listNode *(*list)) {
struct listNode *tmp = *list;
while (tmp->next != NULL) {
tmp = tmp->next;
printf("here");
}
}
// skim through the file and find how many entries there are
int SCAN(FILE (*stream)) {
int size = 0;
char *str = malloc(100 * sizeof(char));
while (fgets(str, 100, stream) != NULL) {
size++;
}
return size;
}
// loop through the file and load the entries into the main data array
void LOAD(FILE *stream, int size, struct treeNode *(*tree), struct listNode *(*list)) {
rewind(stream);
int i;
char *tmp = malloc(100 * sizeof(char));
for (i = 0; i < size; i++) {
fgets(tmp, 100, stream);
// recursively call insert to create the list, fix
*tree = insert(*tree, atol(tmp), list);
}
}
// free up everything
void FREE(struct treeNode *BlackBox, int size) {
// free linked list first
// then free the tree nodes, do this recursively
}
int main(int argv, char *argc[]) {
FILE *file = fopen("./hw7.data", "r");
int size = SCAN(file);
struct treeNode *tree = malloc(size * sizeof(struct treeNode));
struct listNode *list = malloc(size * sizeof(struct listNode));
LOAD(file, size, &tree, &list);
// print output
// print linked list
//printList(list);
fclose(file);
return 0;
}
There is no need to allocate memory in main for the tree, nodes are allocated by insert as needed. Allocating uninitialized memory for tree and list causes undefined behavior when the members pointed to by these pointers are dereferenced.
Change the initializations to:
struct treeNode *tree = NULL;
struct listNode *list = NULL;
Also note that the parentheses in return (node); are unnecessary, it is customary to write return node; instead.
Was allocating memory twice, removed malloc() in main() and now program works.

How to change sinlgy linked list to doubly linked list?

I have a program that I am supposed to change it from a singly linked list to a doubly linked list. This means that I use pointer that points to the next node and a pointer that points to previous node.
How do I do this while recycling my previous code. Is there a way to do this with minimum steps involved?
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
//declaring structure
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
//prototypes
node *create(int n);
void display_recursive(node *n);
int main()
{
int n = 0;
node *head = NULL;
printf("How many entries?\n");
scanf("%d", &n);
//call to create list
head = create(n);
printf("\nThe linked list in order is:\n");
display_recursive(head);
return 0;
}
node *create(int n)
{
node *head = NULL;
node *temp = NULL;
node *p = NULL;
for (int i = 0; i < n; i++)
{
temp = (node*)malloc(sizeof(node));
printf("What is the name of song %d\n", i + 1);
scanf("%s", &temp->songName);
printf("What is the length of song %d (in seconds)?\n", i + 1);
scanf("%d", &temp->songLength);
printf("Is song %d copyrighted?(1 = YES, 0 = NO)\n", i + 1);
scanf("%d", &temp->copyright);
temp->next = NULL;
if (head == NULL)
{
head = temp;
}
else
{
// if not empty, attach new node at the end
p = head;
while (p->next != NULL)
{
p = p->next;
}
p->next = temp;
}
}
return head;
}
void display_recursive(node *n) {
if (!n) {
return;
}
display_recursive(n->next);
printf("Song: %s, ", n->songName);
printf("%d minutes, ",n->songLength);
if (n->copyright == 1)
{
printf("Copyrights\n");
}
else if (n->copyright == 0)
{
printf("No copyrights\n");
}
}
I don't really know how the code should look or what I have to add to achieve a doubly linked list.
You just need a pointer point to previous node
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
struct node* prev;
}node;
just like #T1412 said, you need to add a new member to the structure.
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
struct node* prev;
}node
now you need to modify the create() function so that each node's prev pointer is pointing to previous node, and the HEAD node's prev points to NULL.
Similarly, you need to modify all the linked list related functions to incorporate the prev pointer.
1) strongly suggest changing:
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
to:
struct NODE
{
char songName[20];
int songLength;
int copyright;
struct NODE * prev;
struct NODE * next;
};
typedef struct NODE node;
Then wherever in the code that it is linking in a new node, add the necessary statement to set the 'prior' field. Remember that the firs node will contain NULL in the 'prior' field.

Create a new node for each entry in a .txt file

Okay so I've been doing a program which would read elements of a txt file using scanf (cmd input redirection). A new node must be created for every entry in the file and add it at the end of the list. Here's my code so far:
struct Elem{
int Atnum;
char Na[31];
char Sym[4];
};
struct nodeTag {
struct Elem entry;
struct nodeTag *pNext; // pointer to the next node
};
typedef struct nodeTag Node;
The function that would initialize it is this:
Node *
InitializeList(Node *pFirst, int n)
{
int i;
Node *head, *temp = 0;
pFirst = 0;
for (i=0; i<n; i++){
head = (Node *)malloc(sizeof(Node));
scanf("%d", &head->entry.AtNum);
scanf("%s", head->entry.Na);
scanf("%s", head->entry.Sym);
if (pFirst != 0)
{
temp->pNext = head;
temp = head;
}
else
{
pFirst = temp = head;
}
fflush(stdin);
temp->pNext = 0;
}
return pFirst;
}
and lastly, print it
void
Print( Node *pFirst )
{
Node *temp;
temp = pFirst;
printf("\n status of the linked list is\n");
while (temp != 0)
{
printf("%d %s %s", temp->entry.AtNum, temp->entry.Na, temp->entry.Sym);
temp = temp -> pNext;
}
}
Now, I can't get the program to run properly. No run-time errors though but the output seems to be garbage. I've been working for hours for this and I cant' get my head around it. Thank you for your help!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Elem
{
int AtNum;
char Na[31];
char Sym[4];
};
struct nodeTag
{
/* entry must be a pointer in order to not lose the values
and/or encounter memory conflicting errors
*/
struct Elem *entry;
struct nodeTag *pNext;
};
typedef struct nodeTag Node;
// insert node at the first location
Node *insertFirst(Node *head, struct Elem *data)
{
Node *node = (Node *) malloc(sizeof(Node));
// fill in data
node->entry = data;
/* point it to old first node
in simple words: "put this node before the head"
*/
node->pNext = head;
// point first to new first node
head = node;
return head;
}
Node *InitializeList(int n)
{
int i;
Node *head = NULL;
struct Elem *data;
for (i = 0; i < n; i++)
{
// allocate memory for the struct Elem of each node
data = (struct Elem*) malloc(sizeof(struct Elem));
scanf("%d", &data->AtNum);
scanf("%s", data->Na);
scanf("%s", data->Sym);
head = insertFirst(head, data);
}
return head;
}
//display the list
void printList(Node *head)
{
Node *ptr = head;
printf("\nStatus of the linked list is:\n");
//start from the beginning
while(ptr != NULL)
{
printf("%d %s %s", ptr->entry->AtNum, ptr->entry->Na, ptr->entry->Sym);
printf("\n");
ptr = ptr->pNext;
}
}
int main(int argc, char *argv[])
{
Node *head;
head = InitializeList(3);
printList(head);
return 0;
}
I hope I didn't come too late! If not, please check this answer as the solution, thanks! :-)

BST dictionary error?

I'm building a BST dictionary tree. I'm getting an error at the strcmp line but i have no idea why. the error is EXC_BAD_ACCESS(Code = 1). This tree would be just a right tree because the first line of the file is a so it would be the root with no left children. I commented beside the line of the error.
first couple of lines from text;
a un, uno, una[Article]
aardvark cerdo hormiguero
aardvark oso hormiguero[Noun]
aardvarks cerdos hormigueros
aardvarks osos hormigueros
my code;
#include <stdio.h>
typedef struct node{
char lineOfChar[200];
struct node *left;
struct node *right;
}BST;
typedef struct nodeSec{
BST *next;
}mainLink;
int main(int argc, const char * argv[]) {
struct node *head = malloc(sizeof(BST)); //Define the Head of the linked list of BST
struct nodeSec *headOfHead = malloc(sizeof(mainLink));
headOfHead->next = head;
struct node *current = &head; //Progress down the tree
FILE *file;
file = fopen("/Users/bassammetwally/Desktop/Homework5/text","r");
int times = 0;
char arrayOfLine[200];
while(fgets(arrayOfLine, 200, file)){ //While loop to read lines into the node's array
if (times == 0) // head of linked list to run once
{
for (int counterFirstTime = 0; counterFirstTime < 140; counterFirstTime++)
{
head->lineOfChar[counterFirstTime] = arrayOfLine[counterFirstTime]; // copy the array into the node array
}
times++; // increase times so the previous block would not repeat
}
else {
struct node *temp = malloc(sizeof(BST)); //start a temp node to store the current information for further sorting
for (int counterFirstTime = 0; counterFirstTime < 40; counterFirstTime++)
{
temp->lineOfChar[counterFirstTime] = arrayOfLine[counterFirstTime];//copying line into the node array
}
int q = 2;
while (q == 2)
{
int characterCompare;
if (head != NULL && temp != NULL)
{
characterCompare = strcmp(temp->lineOfChar, head->lineOfChar);//compares the two characters of the array WHERE I GET THE ERROR
}
if (characterCompare > 0) // if temp is bigger..
{
current = head;
head = head->right;// go to the right of the tree
if (head == NULL)// if its NULL and empty then just store it there
{
head = malloc(sizeof(BST));
head = temp;
current->right= head;
break;
}
}
else if (characterCompare < 0){ //since there will not be any duplicates
current = head;
head = head->left;
if (head == NULL)// if its NULL and empty then just store it there
{
head = malloc(sizeof(BST));
head = temp;
current->left = head;
break;
}
}
else if( characterCompare == 0)
{
continue;
}
}
}
head = headOfHead->next;
}
return 0;
}
You have a few problems with pointers. Note that 'head' is a pointer to 'node' structs. In the line;
struct node *current = &head;
you are not assigning current to point to head, you are assigning current to point to the pointer head (you are taking the address of a pointer).
You also have set headOfNext to point to head and then later with;
head = headOfHead->next;
you are simply setting head back to itself.
Finally, there is no need for struct for nodesec. It only contains one element, so you can just use that element. (Unless you have a future plan to expand the struct.)

Linked List removeNode C Programming

I was having some confusion between ListNode and LinkedList. Basically my question was divided into 2 parts. For first part, I was supposed to do with ListNode. The function prototype as such:
int removeNode(ListNode **ptrHead, int index);
All function were working fine for the ListNode part. Then as for the second part, I was supposed to change the function above to this:
int removeNode(LinkedList *11, int index);
My code for part 1 which is working fine look like this:
int removeNode(ListNode **ptrHead, int index) {
ListNode *pre, *cur;
if (index == -1)
return 1;
else if (findNode(*ptrHead, index) != NULL) {
pre = findNode(*ptrHead, index - 1);
cur = pre->next;
pre->next = cur->next;
return 0;
}
else
return 1;
}
ListNode *findNode(ListNode *head, int index) {
ListNode *cur = head;
if (head == NULL || index < 0)
return NULL;
while (index > 0) {
cur = cur->next;
if (cur == NULL) return NULL;
index--;
}
return cur;
}
And here is my entire code for the part 2 which is not working:
#include "stdafx.h"
#include <stdlib.h>
typedef struct _listnode {
int num;
struct _listnode *next;
}ListNode;
typedef struct _linkedlist {
ListNode *head;
int size;
}LinkedList;
void printNode2(ListNode *head);
int removeNode2(LinkedList *ll, int index);
int main()
{
int value, index;
ListNode *head = NULL, *newNode = NULL;
LinkedList *ptr_ll = NULL;
printf("Enter value, -1 to quit: ");
scanf("%d", &value);
while (value != -1) {
if (head == NULL) {
head = malloc(sizeof(ListNode));
newNode = head;
}
else {
newNode->next = malloc(sizeof(ListNode));
newNode = newNode->next;
}
newNode->num = value;
newNode->next = NULL;
scanf("%d", &value);
}
printNode2(head);
printf("\nEnter index to remove: ");
scanf("%d", &index);
removeNode2(ptr_ll, index);
printNode2(head);
return 0;
}
void printNode2(ListNode *head) {
printf("Current list: ");
while (head != NULL) {
printf("%d ", head->num);
head = head->next;
}
}
int removeNode2(LinkedList *ll, int index) {
ListNode *head = ll->head;
if (head == index)
{
if (head->next == NULL)
{
printf("There is only one node. The list can't be made empty ");
return 1;
}
/* Copy the data of next node to head */
head->num = head->next->num;
// store address of next node
index = head->next;
// Remove the link of next node
head->next = head->next->next;
return 0;
}
// When not first node, follow the normal deletion process
// find the previous node
ListNode *prev = head;
while (prev->next != NULL && prev->next != index)
prev = prev->next;
// Check if node really exists in Linked List
if (prev->next == NULL)
{
printf("\n Given node is not present in Linked List");
return 1;
}
// Remove node from Linked List
prev->next = prev->next->next;
return 0;
}
When I try to run the part 2, the cmd just not responding and after a while, it just closed by itself and I have no idea which part went wrong. I was thinking am I in the correct track or the entire LinkedList part just wrong?
When I tried to run in debug mode, this error message popped up:
Exception thrown at 0x01201FD1 in tut.exe: 0xC0000005: Access violation reading location 0x00000000.
If there is a handler for this exception, the program may be safely continued.
Thanks in advance.
You say that you got the linked list to work wihen the list is defined via the head pointer only. In this set-up, you have to pass a pointer to the head pointer when the list may be updated, and just the head pointer when you only inspect the list without modifying, for example:
int removeNode(ListNode **ptrHead, int index);
ListNode *findNode(ListNode *head, int index);
Here, the head pointer is the handle for the list that is visible to the client code.
The approach with the list struct defines a new interface for the linked list. While the head node is enough, it might be desirable to keep track of the tail as well for easy appending or of the number of nodes. This data can be bundles in the linked list struct.
What that means is that the handling of the nodes is left to the list and the client code uses only the linked list struct, for example:
typedef struct ListNode ListNode;
typedef struct LinkedList LinkedList;
struct ListNode {
int num;
ListNode *next;
};
struct LinkedList {
ListNode *head;
ListNode *tail;
int size;
};
void ll_print(const LinkedList *ll);
void ll_prepend(LinkedList *ll, int num);
void ll_append(LinkedList *ll, int num);
void ll_remove_head(LinkedList *ll);
int main()
{
LinkedList ll = {NULL};
ll_append(&ll, 2);
ll_append(&ll, 5);
ll_append(&ll, 8);
ll_print(&ll);
ll_prepend(&ll, 1);
ll_prepend(&ll, 0);
ll_print(&ll);
ll_remove_head(&ll);
ll_print(&ll);
while (ll.head) ll_remove_head(&ll);
return 0;
}
There's also one difference: In the head-node set-up, the head node might be null. Here, the list cannot be null, it must exist. (Its head and tail members can be null, though.) Here the list is allocated on the stack, its address &ll must be passed to the functions.
In the linked list set-up, the distinction between modifying and read-only access is done via the const keyword:
void ll_print(const LinkedList *ll);
void ll_prepend(LinkedList *ll, int num);
In your example, you take a mixed approach with two independent structures, a head node and a list. That can't work, one single list is described by one struct, pick one.
The advantage to the linked list structure approach is that all required data like head, tail and size are always passed together to a function. You can also hide the implementation from the user by not disclosing the struct members, so that theb user can only work on pointers to that struct.
Finally, here's an example implementation of the above interface for you to play with:
void ll_print(const LinkedList *ll)
{
ListNode *node = ll->head;
while (node != NULL) {
printf("%d ", node->num);
node = node->next;
}
putchar('\n');
}
void ll_prepend(LinkedList *ll, int num)
{
ListNode *nnew = malloc(sizeof *nnew);
nnew->next = ll->head;
nnew->num = num;
ll->head = nnew;
if (ll->tail == NULL) ll->tail = ll->head;
ll->size++;
}
void ll_append(LinkedList *ll, int num)
{
ListNode *nnew = malloc(sizeof *nnew);
nnew->next = NULL;
nnew->num = num;
if (ll->tail == NULL) {
ll->tail = ll->head = nnew;
} else {
ll->tail->next = nnew;
ll->tail = nnew;
}
ll->size++;
}
void ll_remove_head(LinkedList *ll)
{
if (ll->head) {
ListNode *ndel = ll->head;
ll->head = ll->head->next;
ll->size--;
free(ndel);
}
}

Resources