Couldn't understand why my program is producing an error signal.
#include<stdio.h>
#include<stdlib.h>
struct Node{
int data;
struct Node *next;
};
int MAX_SIZE = 1;
char stack[1];
int top = -1;
int isempty() {
if(top == -1)return 1;
else return 0;
}
int isfull() {
if(top == 0)return 1;
else return 0;
}
int pop() {
int data;
if(!isempty()) {
data = stack[top];
top = top - 1;
return data;
} else {
printf("Could not retrieve data, Stack is empty.\n");
}
}
void push(int data) {
if(!isfull()) {
top = top + 1;
stack[top] = data;
} else {
printf("Could not insert data, Stack is full.\n");
}
}
struct Node* newNode(int d){
struct Node *temp = (struct Node*)malloc(sizeof(struct Node));
temp->data = d;
temp->next = NULL;
return temp;
}
struct Node* reverse(struct Node* head){
//reverses the linked list and returns the pointer pointing to the first node of the reversed linked list.
struct Node *prev = NULL, *curr = head;
while (curr) {
struct Node* temp = curr->next;
curr->next = prev;
prev = curr;
curr = temp;
free(temp);
}
head = prev;
return head;
}
struct Node* addition(struct Node* first, struct Node* second){
struct Node *rev1, *rev2;
struct Node *res = NULL, *revres = NULL;
struct Node *temp, *prev = NULL;
int carry = 0, sum;
rev1 = reverse(first);
rev2 = reverse(second);
while (rev1 != NULL || rev2 != NULL) {
sum = carry + (rev1 ? rev1->data : 0) + (rev2 ? rev2->data : 0);
carry = (sum >= 1000) ? 1 : 0;
sum = sum % 1000;
temp = newNode(sum);
if (res == NULL)
res = temp;
else
prev->next = temp;
prev = temp;
if (rev1)
rev1 = rev1->next;
if (rev2)
rev2 = rev2->next;
}
if (carry > 0){
struct Node *new = newNode(carry);
temp->next = new;
free(new);
}
revres = reverse(res);
while (revres->data == 0 && revres->next) {
struct Node* temp = revres;
revres = revres->next;
free(temp);
}
return revres;
}
int length_reversal(struct Node** head_ref){
// reverses the given linkedlist in-place and also returns the number of nodes in the list.
struct Node* prev = NULL;
struct Node* current = *head_ref;
struct Node* next;
int len = 0;
while (current != NULL) {
len++;
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;
return len;
}
void addData(struct Node** head_ref, int new_data){
struct Node* new_node = newNode(new_data);
new_node->next = (*head_ref);
(*head_ref) = new_node;
free(new_node);
}
struct Node* make_empty_list(int size){
struct Node* head = NULL;
while (size--)
addData(&head, 0);
return head;
}
struct Node* multiplication(struct Node* first, struct Node* second){
int m = length_reversal(&first), n = length_reversal(&second);
struct Node* result = make_empty_list(m + n + 1);
struct Node *second_ptr = second, *result_ptr1 = result, *result_ptr2, *first_ptr;
while (second_ptr) {
int carry = 0;
result_ptr2 = result_ptr1;
first_ptr = first;
while (first_ptr) {
int mul = first_ptr->data * second_ptr->data + carry;
result_ptr2->data += mul % 1000;
carry = (mul / 1000) + (result_ptr2->data / 1000);
result_ptr2->data = result_ptr2->data % 1000;
first_ptr = first_ptr->next;
result_ptr2 = result_ptr2->next;
}
if (carry > 0) {
result_ptr2->data += carry;
}
result_ptr1 = result_ptr1->next;
second_ptr = second_ptr->next;
}
length_reversal(&result);
length_reversal(&first);
length_reversal(&second);
while (result->data == 0 && result->next) {
struct Node* temp = result;
result = result->next;
free(temp);
}
return result;
}
struct Node* input(FILE* fp){
char ch;
int i = 0;
struct Node *result = NULL, *first= NULL;
struct Node *it1 = NULL, *it2 = NULL, *it3 = NULL;
char str[3];
while(EOF != (ch=fgetc(fp)) && ch != '\n'){
if(ch == '=')return it1;
else if(ch == '0'||ch == '1'||ch == '2'||ch == '3'||ch == '4'||ch == '5'||
ch == '6'||ch == '7'||ch == '8'||ch == '9'){
if(i==3){printf("invalid input\n"); return NULL;}
str[i] = ch;
i++;
}
else if(ch == '+'){
push(ch);
}
else if(ch == '*'){
push(ch);
}
else if(ch == '$'){
it3 = newNode(atoi(str));
i = 0;
if(!first){
if(!it1)it1 = it3;
else it2 = it3;
}
else{
first->next = it3;
first = NULL;
}
if(!isempty()){
char c = pop();
if(c == '+'){result = addition(it1, it2); it1 = result; it2 = NULL;}
if(c == '*'){result = multiplication(it1, it2); it1 = result; it2 = NULL;}
}
}
else if(ch == ','){
if(first != NULL){
it3 = newNode(atoi(str));
first->next = it3;
first = first->next;
i=0;
}
else{
if(!it1){
first = newNode(atoi(str));
it1 = first;
i=0;
}
else{
first = newNode(atoi(str));
it2 = first;
i=0;
}
}
}
else if(ch == ' ') continue;
else {
printf("Invalid input");
return NULL;
}
}
return it1;
}
void output(FILE *fout, struct Node* list) {
struct Node *temp;
for (temp = list; temp->next != NULL; temp = temp->next)
fprintf (fout, "%03d,", temp->data);
fprintf(fout, "%03d$", temp->data);
fprintf (fout, "\n");
}
int main(){
FILE *fp;
fp = fopen("input_txt.txt", "r");
char c;
while(EOF != (c=getc(fp)) && c != '='){
ungetc(c, fp);
struct Node* res = input(fp);
if(res){
output(stdout, res);
}
}
return 0;
}
I have tried using a debugger to understand the problem, but no luck there.
The problem was described as
"""You will represent an arbitrarily large unsigned integer I by a singly linked list of its DIGITs d1 ,
d2 , ... , dm , where d1 is the least significant DIGIT of I and dm is the most significant DIGIT of I.
Assume that the DIGITs are from a number system with base 1,00010. Implement each DIGIT as a C
unsigned int with DIGIT values in [0, 999].
a) Write C functions to perform the arithmetic operations addition and multiplication of large
unsigned integers.
b) Write a C function to input a large unsigned integer from stdin as comma separated DIGITs
in decimal, ordered on decreasing significance and terminated by a $
c) Write a C function to output a large unsigned integer to stdout in the format used for input,
showing each DIGIT as 3 decimal digits.
d) Write a C main() which will repeatedly accept (from stdin) and evaluate, large integer infix
expressions on large unsigned integer constants using the operators “+” (addition) and “*”
(multiplication). An expression is terminated by “=”. On encountering an “=”, the value of
the expression is to be printed to stdout. Evaluate expressions from left to right. The main() loop
should terminate when it receives an empty expression (terminated by =)."""
This was my assignment question for which the deadline was over a week ago and I couldn't figure out the problem with my code.
For example, the 2 line input
111,041,411,111,011$ + 222,222$ * 003$ =
results in the output
333,124,233,999,699$
Related
I have written this code and in general works good, but trying to run these particular lines in main, when we arrive to the point in which i == 74 the elements of the list are 4 - 11 - 18 - 4 - 10 - 18 - 17 - 22 - 14 - 29 and the swapNodes() function has to swap the two nodes with the keys 18, but instead I get these elements: 4 - 18 - 4 - 10 - 18 - 17 - 22 - 14 - 29. I tried to initialize the list with the exact values as before "swapping" and then try to swap these two nodes and everything works as it should.
PS: I would appreciate if someone could help me to write the swapNodes() function with fewer lines but that's not a necessity at this moment.
typedef struct _node{
int key;
struct _node *next;
struct _node *prev;
}node;
node* createNode(int key){
node* a = (node*)malloc(sizeof(struct _node));
a->key = key;
a->next = NULL;
a->prev = NULL;
return a;
}
void printList(node* head){
while (head != NULL){
printf("%d", head->key);
if(head->next != NULL) printf(" - ");
head = head->next;
}
printf("\n");
}
void fillList(node** head, int dim){
int i;
for(i=0; i<dim; i++)
listInsert(head, createNode(rand()%30));
}
//findes a node given an index, the indices start from 1
node** findNode(node** head, int index){
int i;
for(i=1; i<index; i++)
head = &(*head)->next;
if(head != NULL) return head;
else return NULL;
}
void listInsert(node** head, node* node){
if((*head) == NULL){
(*head) = node;
return;
}
node->next = (*head);
(*head)->prev = node;
(*head) = node;
}
int main(){
node* list = NULL;
fillList(&list, 10);
int i, a, b;
for(i=0; i<100; i++){
printList(list);
a = rand()%10 +1;
b = rand()%10 +1;
swapNodes(&list, *findNode(&list, a), *findNode(&list, b));
printList(list);
printf("\n");
}
return 0;
}
EDIT:
I managed to rewrite the swapNodes() function but this time executing the same lines in main I get a loop in the list for i==15, a==4 and b==2. Again if I try to manualy swap any of the nodes the function works fine.
void swapNodes(node** head, node* a, node* b){
node* aPrev = a->prev;
node* aNext = a->next;
node* bPrev = b->prev;
node* bNext = b->next;
if(a == b) return;
if(a->prev == b ||
(b->prev == NULL && a->next == NULL) ||
(b->prev == NULL && b->next == a) ||
a->next == NULL) return swapNodes(head, b, a);
if(a->prev == NULL)
(*head) = b;
else if(b->prev == NULL)
(*head) = a;
if(a->next == b){
if(aPrev != NULL) aPrev->next = b;
b->prev = aPrev;
b->next = a;
bNext->prev = a;
a->prev = b;
a->next = bNext;
}else{
b->next = aNext;
a->next = bNext;
if(a->prev != NULL)
aPrev->next = b;
if(b->prev != NULL)
bPrev->next = a;
if(a->next != NULL)
aNext->prev = b;
if(bNext != NULL)
bNext->prev = a;
if(b != NULL)
b->prev = aPrev;
if(a != NULL)
a->prev = bPrev;
}
}
Following the idea that #ggorlen gave me, I rewrote the swapNodes() function adding also some new ones and finally it works perfectly. To keep track of where the nodes were before extracting them, I created a struct containing the index returned from the findIndex() function and the node itself. I also changed the findNode() function so that it returns a variable of type node* and not node**. Sure it's not very efficient, but I'll make do.
typedef struct _extractedNode{
struct _node* node;
int index;
}extractedNode;
int findIndex(node* head, node* node){
int i=1;
node* temp = head;
while(node != temp){
temp = temp->next;
i++;
}
return i;
}
extractedNode extractNode(node** head, node* node){
extractedNode extracted;
extracted.index = 0;
if(node == NULL){
printf("extractNode(): il nodo non esiste!\n");
extracted.node = NULL;
extracted.index = -1;
}else{
node* prev = node->prev;
node* next = node->next;
if(prev == NULL){
(*head) = next;
extracted.index = 1;
}
if(extracted.index != 1)
extracted.index = findIndex(*head, node);
if(prev != NULL)
prev->next = next;
if(next != NULL)
next->prev = prev;
node->next = NULL;
node->prev = NULL;
extracted.node = node;
}
return extracted;
}
void listInsertAsIndex(node** head, int index, node* node){
if(index <= 0) return;
if(index == 1) return listInsert(head, node);
else{
node* prev = findNode(*head, index-1);
node* next = prev->next;
prev->next = node;
node->prev = prev;
if(next != NULL){
node->next = next;
next->prev = node;
}
}
}
void swapNodes(node** head, node* a, node* b){
if(a == b) return;
extractedNode aX, bX;
if(a->prev == NULL && a->next == b){
aX = extractNode(head, a);
listInsertAsIndex(head, 2, aX.node);
}else if(b->prev == NULL && b->next == a){
bX = extractNode(head, b);
listInsertAsIndex(head, 2, bX.node);
}else if(a->next == b){
aX = extractNode(head, a);
listInsertAsIndex(head, aX.index +1, aX.node);
}else if(b->next == a){
bX = extractNode(head, b);
listInsertAsIndex(head, bX.index +1, bX.node);
}else{
aX = extractNode(head, a);
bX = extractNode(head, b);
if(aX.index < bX.index){
listInsertAsIndex(head, aX.index, bX.node);
listInsertAsIndex(head, bX.index +1, aX.node);
}else{
listInsertAsIndex(head, bX.index, aX.node);
listInsertAsIndex(head, aX.index, bX.node);
}
}
}
I'm working on a FIFO page replacement algorithm and have it almost working. My code uses scanf() to read in a page number then it adds that item to a linked list, up to 16 pages. However, if the page already exists in the lined list, it does not add the page to this list again. There are three page frames (slots). Everything works properly, but, it does not add that item to the list until scanf() reads another integer to add to the list. I am utterly confused.
#include<stdio.h>
#include<stdlib.h>
typedef struct node {
int num;
struct node * next;
} node_t;
void print_list(node_t * head) {
node_t * current = head;
while (current != NULL) {
printf("%d\n", current->num);
current = current->next;
}
}
int fault(node_t * head, int check) {
node_t * current = head;
while(current->next != NULL){
if(current->num == check)
return 0;
current = current->next;
}
return 1;
}
void addNode(node_t * head, int num) {
node_t * current = head;
while (current->next != NULL) {
current = current->next;
}
/* now we can add a new variable */
current->next = malloc(sizeof(node_t));
current->next->num = num;
current->next->next = NULL;
}
int pop(node_t ** head) {
int retnum = -1;
node_t * nextNode = NULL;
if (*head == NULL) {
return -1;
}
nextNode = (*head)->next;
retnum = (*head)->num;
free(*head);
*head = nextNode;
return retnum;
}
///////////////////////////////////////////////////////
int main(){
int num;
int faults = 0;
int n = 0;
int j = 0;
node_t * head = malloc(sizeof(node_t));
if (head == NULL) {
return 1;
}
head->num = -1;
printf("Input page number up to 16 pages. Enter 'q' to quit.\n");
for(j=0;j<16;j++){
if(scanf("%d\n",&num) == 1) {
if (fault(head, num) == 1 && n < 3) {
n++;
faults++;
addNode(head, num);
}
else if (fault(head, num) == 1 && n >= 3) {
pop(&head);
addNode(head,num);
faults++;
}
}
else{
int c = getchar();
if( c == 'q' ){
break;
}
}
if (n == 1 && faults == 1)
pop(&head);
printf("\nPage Table:\n");
print_list(head);
printf("\nInput page number: \n");
}
printf("Number of page faults: %d\n", faults);
}
I ran it through gdb and it doesn't even call the addNode function until the second integer has been scanned.
(And yes I know scanf is garbage, I just didn't want to bother learning how to do something else)
Thanks for the help!
Your code:
if(scanf("%d\n",&num) == 1) {
should be :
if(scanf("%d",&num) == 1) {
And head needs to be initialized.
node_t * head = malloc(sizeof(node_t));
if (head == NULL) {
return 1;
}
head->next = NULL;
typedef struct node
{
Record data;
struct node *next;
}Node;
Node *head = NULL;
void addRecord(Record x)
{
Node *previousNode = NULL;
Node *newNode;
Node *n;
newNode = (Node*)malloc(sizeof(Node));
newNode->data = x;
newNode->next = NULL;
if (head == NULL) // The list is empty
{
head = newNode;
}
else // The list is not empty
{
n = head;
while (n->next != NULL)
{
***if (n->data < newNode->data && n->next->data > newNode->data)*** // Insertion Sort
{
// We have to put it between these 2 nodes
newNode->next = n->next;
n->next = newNode;
return;
}
else
{
previousNode = n;
n = n->next;
}
}
n->next = newNode;
}
}
I have this error in the code within the if function of the insertion sort. The program says that 'n' must have arithmetic or pointer type. What seems to be the problem?
Operator overload is not supported in C, so you cannot compare Record using > operator unless it is typedefed to int or other aritimetic or pointer type.
To compare something like structures, define comparation function and use it.
Example:
typedef struct {
int a, b;
} Record;
/*
return positive value if *x > *y
return negative value if *x < *y
return 0 if *x == *y
*/
int cmpRecord(const Record* x, const Record* y) {
if (x->a + x->b > y->a + y->b) return 1;
if (x->a + x->b < y->a + y->b) return -1;
return 0;
}
/* ... */
while (n->next != NULL)
{
if (cmpRecord(&n->data, &newNode->data) < 0 && cmpRecord(&n->next->data, &newNode->data) > 0) // Insertion Sort
{
/* ... */
I was tasked with implementing a merge sort algorithm on a list written in C/C++. I have the general idea down, wrote my code and have successfully compiled it. However, when I run it, it will begin fine but then hang on "prepared list, now starting sort" without giving any kind of error. I have tried to look through my code but I am at a complete loss as to what the issue could be. I am also pretty amateurish with debugging, so using gdb to the best of my abilities has lead me no where. Any advice or tips would be a tremendous help, thank you all!
#include <stdio.h>
#include <stdlib.h>
struct listnode
{
struct listnode *next;
int key;
};
//Finds length of listnode
int
findLength (struct listnode *a)
{
struct listnode *temp = a;
int i = 0;
while (temp != NULL)
{
i++;
temp = temp->next;
}
return i;
}
struct listnode *
sort (struct listnode *a)
{
// Scenario when listnode is NULL
if (findLength (a) <= 1)
return a;
//Find middle
int mid = findLength (a) / 2;
struct listnode *temp = a;
struct listnode *first = a;
struct listnode *second;
for (int i = 0; i < mid - 1; i++)
{
temp = a->next;
}
second = temp->next;
temp->next = NULL;
//Recursive calls to sort lists
first = sort (first);
second = sort (second);
if (first != NULL && second != NULL)
{
if (first->key < second->key)
{
a = first;
first = first->next;
}
else
{
a = second;
second = second->next;
}
}
struct listnode *head = a;
struct listnode *tail = a;
while (first != NULL && second != NULL)
{
if (first->key < second->key)
{
tail = first;
first = first->next;
tail = tail->next;
}
else
{
tail = second;
second = second->next;
tail = tail->next;
}
}
if (first == NULL)
{
while (second != NULL)
{
tail = second;
second = second->next;
tail = tail->next;
}
}
while (first != NULL)
{
tail = first;
first = first->next;
tail = tail->next;
}
return a;
}
Here is the test code provided, written in C:int
main (void)
{
long i;
struct listnode *node, *tmpnode, *space;
space = (struct listnode *) malloc (500000 * sizeof (struct listnode));
for (i = 0; i < 500000; i++)
{
(space + i)->key = 2 * ((17 * i) % 500000);
(space + i)->next = space + (i + 1);
}
(space + 499999)->next = NULL;
node = space;
printf ("\n prepared list, now starting sort\n");
node = sort (node);
printf ("\n checking sorted list\n");
for (i = 0; i < 500000; i++)
{
if (node == NULL)
{
printf ("List ended early\n");
exit (0);
}
if (node->key != 2 * i)
{
printf ("Node contains wrong value\n");
exit (0);
}
node = node->next;
}
printf ("Sort successful\n");
exit (0);
}
You're close, but with some silly errors. Check the append operations in the merge step. They're not doing what you think they are. And of course you meant temp = temp->next; in the splitting loop.
If gdb is overwhelming, adding printf's is a perfectly fine way to go about debugging code like this. Actually you want to write a list printing function and print the sublists at each level of recursion plus the results of the merge step. It's fun to watch. Just be neat and delete all that when you're done.
Here's code that works for reference:
struct listnode *sort(struct listnode *lst) {
if (!lst || !lst->next) return lst;
struct listnode *q = lst, *p = lst->next->next;
while (p && p->next) {
q = q->next;
p = p->next->next;
}
struct listnode *mid = q->next;
q->next = NULL;
struct listnode *fst = sort(lst), *snd = sort(mid);
struct listnode rtn[1], *tail = rtn;
while (fst && snd) {
if (fst->key < snd->key) {
tail->next = fst;
tail = fst;
fst = fst->next;
} else {
tail->next = snd;
tail = snd;
snd = snd->next;
}
}
while (fst) {
tail->next = fst;
tail = fst;
fst = fst->next;
}
while (snd) {
tail->next = snd;
tail = snd;
snd = snd->next;
}
tail->next = NULL;
return rtn->next;
}
On my old MacBook this sorts 10 million random integers in a bit over 4 seconds, which doesn't seem too bad.
You can also put the append operation in a macro and make this quite concise:
struct listnode *sort(struct listnode *lst) {
if (!lst || !lst->next) return lst;
struct listnode *q = lst, *p = lst->next->next;
while (p && p->next) {
q = q->next;
p = p->next->next;
}
struct listnode *mid = q->next;
q->next = NULL;
struct listnode *fst = sort(lst), *snd = sort(mid);
struct listnode rtn[1], *tail = rtn;
#define APPEND(X) do { tail->next = X; tail = X; X = X->next; } while (0)
while (fst && snd) if (fst->key < snd->key) APPEND(fst); else APPEND(snd);
while (fst) APPEND(fst);
while (snd) APPEND(snd);
tail->next = NULL;
return rtn->next;
}
Does it have to be a top down merge sort? To get you started, here's a partial fix, didn't check for other stuff. The | if (first != NULL && second != NULL) | check isn't needed since the prior check for length <= 1 takes care of this, but it won't cause a problem.
while (first != NULL && second != NULL)
{
if (first->key < second->key)
{
tail->next = first;
tail = first;
first = first->next;
}
else
{
tail->next = second;
tail = second;
second = second->next;
}
}
if (first == NULL)
{
tail->next = second;
}
else
{
tail->next = first;
}
}
In this code below ,i have got numerals as input,and send the odd numbers to list1 and sent the even numbers to list2.Finally,i have added the values in list1 & list2 and stored them in list3.But i am getting segmentation error.please help me
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct node//list creation
{
int data;
struct node *next;
};
struct node *list1;
struct node *list2;
struct node *list3;
/*creating list*/
void create(struct node *l, int x)
{
l->data = x;
l->next = NULL;
}
/* adding elements to list*/
void addlast(struct node *li, int x)
{
struct node *temp = NULL;
temp = (struct node *) malloc(sizeof(struct node));
temp->data = x;
while (li->next != NULL)
li = li->next;
li->next = temp;
temp->next = NULL;
}
/* printing values */
void print(struct node *lb)
{
if (lb == NULL)
printf("empty");
else
{
while (lb->next != NULL)
{
printf(" % d->", lb->data);
lb = lb->next;
}
printf(" % d->", lb->data);
}
}
/* performing addition */
void add(struct node *l1, struct node *l2)
{
int value, c = 0;
while (l1->next != NULL || l2->next != NULL)
{
value = l1->data+l2->data;
if (c == 0)
{
create(list3, value);
c++;
}
else
{
addlast(list3, value);
}
l1 = l1->next;
l2 = l2->next;
}
printf("list3");
print(list3);
}
int main()
{
int i, n, a[20], c1 = 0, c2 = 0;
list1 = (struct node *) malloc(sizeof(struct node));
list2 = (struct node *) malloc(sizeof(struct node));
list3 = (struct node *) malloc(sizeof(struct node));
printf("\n Enter the number of numbers");
scanf("%d", &n);
for (i = 0; i < n; i++)
{
scanf("%d", &a[i]);
if (a[i] % 2 == 0)
{
if (c1 == 0)
{
create(list1, a[i]);
c1++;
}
else
addlast(list1, a[i]);
}
if (a[i] % 2 != 0)
{
if (c2 == 0)
{
create(list2, a[i]);
c2++;
}
else
addlast(list2, a[i]);
}
}
printf("list1");
print(list1);
printf("\n");
printf("list2");
print(list2);
add(list1, list2);
return 0;
}
The problem is your while loop condition in the add. You should check if either l1->next or l2->next is null. Here is the corrected version.
/* performing addition */
void add(struct node *l1, struct node *l2)
{
int value, c = 0;
//you can only add if the two lists have same number of elems
while (l1->next != NULL && l2->next != NULL)
{
value = l1->data + l2->data;
if (c == 0)
{
create(list3, value);
c++;
}
else
{
addlast(list3, value);
}
l1 = l1->next;
l2 = l2->next;
}
//if lists dont have equal number of elements
//find the list which is not empty and append the
//elems to l3 here
printf("list3");
print(list3);
}