Looping through linked list - endless loop - c

Teaching myself to program, I decided to make a simple wattage calculator. Each state has a different (average) price/KWh. My problem starts a line 34 in the code. The curr->next is never null.
What am I doing wrong?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
float calculate(float w, float cents, float h);
struct states
{
char *name;
char *price;
struct states *next;
};
int main()
{
float watts,hours,cents;
int a = 0;
struct states *curr, dict[52];
char st_ab[52][3] = {"ID","ND","WA","AR","UT","LA","WY","SD","NE","KY","WV","OK","OR","MT","MS","TN","IN","NC","MS","IA","KS","VA","NM","MN","SC","AZ","GA","AL","CO","OH","TX","IL","FL","NV","MI","WI","PA","MD","DC","DE","MA","RI","CA","ME","VT","NJ","NH","AK","CT","NY","HI"};
char st_pr[52][5] = {"8.0","8.1","8.2","8.7","8.8","8.9","8.9","9.0","9.0","9.0","9.2","9.2","9.4","9.6","9.7","9.8","10.0","10.2","10.3","10.5","10.5","10.5","10.7","10.9","11.0","11.1","11.1","11.1","11.2","11.2","11.3","11.7","11.7","11.7","13.0","13.0","13.2","13.7","13.7","13.7","14.8","14.9","15.2","15.5","16.1","16.3","16.5","17.5","18.1","18.1","33.2"};
char state[2];
for(a=0;a<=52;a++)
{
memset(&dict[a],0,sizeof(struct states)); /* zero out structure */
if(a==52)
{
break; /* if this is the last struct, leave it NULL so we can loop through linked list */
}
dict[a].next=&dict[a+1];
}
for(curr = dict;curr ->next != NULL;curr = curr->next) /* fill our list with state abbr. and cost/KWh */
{
curr->name = st_ab[a];
curr->price = st_pr[a];
a++;
}
puts("Dictionary loaded!");
printf(" Two letter state code: "); /* get info from user */
scanf("%s",state);
printf(" Wattage of appliance: ");
scanf("%f",&watts);
printf(" Hours of use per day: ");
scanf("%f",&hours);
for(curr = dict; curr->next != NULL; curr=curr->next)
{
printf("comparing %s with %s\n", curr->name,state); /* search for our state, set cents respectively */
if((strcmp(curr->name,state)) == 0)
{
printf("State found! -- %s\n",state);
cents=atof(curr->price);
printf("%f cents\n",cents);
break;
} else {
printf("state didn't match\n");
continue;
}
}
printf("\nAverage cost per day: %.2f\n", calculate(watts,cents,hours));
printf("Average cost per year: %.2f\n\n", (calculate(watts,cents,hours)) * 365);
return 0;
}
float calculate(float w, float c, float h)
{
float kwh = (w/1000) * h;
float cos = kwh*(c/100);
return(cos);
}

The problem is in
dict[a].next = &dict[a+1];
The C standard guarantees that &dict[a+1] is never NULL, even though it is one past the end of the array. This causes the next loop to go past the end of the list, with undefined behavior resulting (the program might do anything). After the first loop, do
dict[51].next = NULL;
to end the linked list.
EDIT: with for(a=0;a<=52;a++) you actually walk two elements past the end of the array, so the behavior is undefined in two places. To fix that, you need to loop until a<52.

"curr->next is never null" - well, how do you expect your for loop to stop if your stopping condition is curr->next that equals to null?

Related

Violation of access with pointers and scanf

The following code is supposed to insert the name of a good, whether it's getting stored or sent away (with just a single letter, like i for in or o for out) and in conclusion how much of that item is getting moved.
Then the program should end whenever I write the END phrase.
Problem is, I am finding a violation of access while trying to save the number of items, and cannot seem to find where I am doing something wrong.
#define MAX 20
#define END "FINE"
typedef struct type_struct {
char name[MAX];
char move[2];
int quantity;
struct type_struct* next;
}type;
void insert(type* p) {
type* aux;
aux = p;
while (aux != NULL)
aux = aux->next;
aux = malloc(sizeof(type));
printf("name of good: ");
scanf("%s", aux->name);
getchar();
printf("in or out?: ");
scanf("%c", aux->move);
printf("quantity: ");
scanf("%d", aux->quantity);
printf("\n");
}
int main(void) {
type* phrase=NULL;
char fine[5];
strcpy(fine, END);
do {
insert(phrase);
} while ((strcmp(phrase, fine) == 0));
}
It should be very simple, however, I am clueless and hope you might give me a hand

Modifying data in a Linked List in C?

When I modify the linked list (based on the ID), it modifies the node successfully but deletes the rest of the list. The whole list stays only if I modify the most recent node that I've added to the list.
I know that the problem is at the end where it says:
phead=i;
return phead;
But I don't know how to fix it as I haven't found anything to help me, even though I'm sure it is simple to know why it is wrong.
struct ItemNode *modify1Item(struct ItemNode *phead){
int modID;
int lfound=0;
int lID;
char lDesc[30];
char lName[30];
double lUPrice;
int lOnHand;
struct ItemNode *i=phead;
printf("Enter the ID of the item that you want to modify\n");
scanf("%d", &modID);
while(i != NULL){
if(i->ID == modID){
break;
}
i= i->next;
}
if(i==NULL){
printf("An item with that ID wasn't found.\n");
return 0;
}
else{
printf("Enter new Name\n");
scanf("%s", lName);
strcpy(i->name, lName);
printf("Enter new Description\n");
scanf("%s", lDesc);
strcpy(i->desc, lDesc);
printf("Enter new Unit Price $\n");
scanf("%lf", &lUPrice);
i->uPrice = lUPrice;
printf("Enter new Number of Items On Hand\n");
scanf("%d", &lOnHand);
i->onHand = lOnHand;
}
phead=i;
return phead;
}
When I return it, i say head=modify1Item(phead);
I tested your code everything worked as expected. Without seeing your code, I can't comment much. But I think, for your code, the only time everything would get delete is if you assign the return value incorrectly. So this below is probably something close to your code. For the test code below, unless you modify it, the IDs are 0, 1, and 2. Oh and the reason why I commented only work for 0 to 9 is because I don't want to make up the entire char string so I used i ^ 48. Of which, 0 - 9 ^ 48 would turn into the correspondent ASCII code of 0 - 9. If you go beyond that, you may get weird result for that two string that all.
I just noticed that you use NULL in your search. Thus, I updated the code so the "next" of last index will be NULL otherwise if your code found nothing, it will run forever.
#include <stdio.h>
#include <string.h>
typedef struct ItemNode {
int ID;
int uPrice;
int onHand;
char name[30];
char desc[30];
struct ItemNode * next;
} ItemNode ;
struct ItemNode * modify1Item(struct ItemNode * phead){
int modID;
int lfound=0;
int lID;
char lDesc[30];
char lName[30];
double lUPrice;
int lOnHand;
struct ItemNode *i = phead;
printf("Enter the ID of the item that you want to modify\n");
scanf("%d", &modID);
while(i != NULL){
if(i->ID == modID){
break;
}
i = i->next;
}
if(i==NULL){
printf("An item with that ID wasn't found.\n");
return 0;
} else {
printf("Enter new Name\n");
scanf("%s", lName);
strcpy(i->name, lName);
printf("Enter new Description\n");
scanf("%s", lDesc);
strcpy(i->desc, lDesc);
printf("Enter new Unit Price $\n");
scanf("%lf", &lUPrice);
i->uPrice = lUPrice;
printf("Enter new Number of Items On Hand\n");
scanf("%d", &lOnHand);
i->onHand = lOnHand;
}
phead=i;
return phead;
}
int main(){
// only work for 0 - 9.
int index = 3;
ItemNode iArr[index];
for ( int i = 0; i < index; i++ ){
iArr[i].ID = i;
iArr[i].uPrice = i + i;
iArr[i].onHand = i * i;
iArr[i].name[0] = i ^ 48;
iArr[i].desc[0] = i ^ 48;
// If last index link back to first index.
// Updated: but for you usage case
// because of your search function
// last index should be NULL otherwise your
// search will run forever
if ( i < index - 1 ) iArr[i].next = &iArr[i + 1];
else iArr[i].next = NULL; // if change search method with unique ID then you can use -> &iArr[0];
}
// Mod 0
ItemNode * test = modify1Item(iArr);
printf("0 name: %s\n\n",iArr[0].name );
// Mod 1
ItemNode * test1 = modify1Item(iArr);
printf("1 name: %s\n\n",iArr[1].name );
// Mod 2
ItemNode * test2 = modify1Item(iArr);
printf("2 name: %s\n\n",iArr[2].name );
// Check if 0 is still there.
printf("0 name: %s\n\n",iArr[0].name );
return 0;
}

Write a program in C that uses the rand() function to create 1000 structs

I have these challenges:
Define a struct containing 4 data types
Write a program in C that uses the rand() function to create 1000 instances of these structs
Inserts them in the linked list and prints out the first 10 to the console.
Modify the linked list code provided in the file code.c
so that it works for inserting structs of type given in your answer to Question 1.
#include <stdio.h>
#include <stdlib.h>
#include<malloc.h>
//#include "users.h"
int i;
//Stime = srand(time(0));
typedef struct users
{
int UserID;
char FullName[50];
int Age;
//double Height;
float Weight;
}users;
typedef struct node
{
//Stime = srand(time(0));
users data;
struct node *next;
} node;
node* insert(node *ptr, users data)
{
node *entry = (node*)malloc(sizeof(node));
//printf("enter the data item\n");
//scanf("%d",*node-> next);
if(entry == NULL)
{
printf("No Free Memory!\n");
exit(0);
}
else
{
entry->data = data;
entry->next = NULL;
if(ptr == NULL)
{
ptr = entry;
}
else
{
node *temp = ptr;
while(temp->next != NULL)
{
temp = temp->next;
}
temp->next = entry;
}
}
return ptr;
}
/
obviously U[i] is not the correct way to do this.
if I wanted to have unique constructors o-n (max 1000) how would I do it?
int main()
{
int i= 0;
node *first = NULL;
srand(time(0));
users U[i] = {
(U[i].UserID = 600000+rand()% 33331),
(strcpy( U[i].FullName , " Nathanial Rivers")),
(U[i].Age = 18+rand()% 82),
(U[i].Weight = 40+rand()% 99)
};
//users U1 = {600000,"Martin Toomey",19,76.6};
users U2 = {(U2.UserID = 600000+rand()% 33331),"bob boby",21,77.7};
users U3 = {600002,"abcdefg ",17,79.1};
printf(" Name: %s \n",U1.FullName);
printf(" User ID: %d \n Age is: %d \n Weight is: %f \n \n",U1.UserID, U1.Age, U1.Weight );
for (i=0; i<10; i++){
srand(time(0));
first = insert(first, U[i]);
/first = insert(first, U2);
//first = insert(first, U3);
//printf(" User ID: %d \n Age is: %d \n Weight is: %f \n \n",U1.UserID, U1.Age, U1.Weight );}
printf(" User ID: %d \n", U[i].UserID);
printf(" Age %d \n", U[i].Age);
printf(" User ID: %d \n", U[i].UserID);
printf(" Age %d \n", U2.Age);
}
//printf(U1);
first = insert(first, U2);
//printf(*U2);
first = insert(first, U3);
return 0;
}
In main() function, I'm trying to generate 100 unique users using rand
I have thought that if I have a print function or param in first and every time I call first in the loop in prints the user info with C I'm not sure if that possible
Any pointers on how to improve my code greatly appreciated I know U1 U2 U3.... shouldn't be used as var names its bad practice.
There are many problems in your posted code:
struct users[] user[i] = new users [100]:
Semicolon ; missing at end of the line
by using a typedef you don't have to specify the type via struct
if you want to use an array you should create it above the for-loop
in C you allocate dynamic memory with malloc: user* tmp = malloc(sizeof(user))
printf(user):
Semicolon ; missing at end of line
printf doesn't know the internal structure of the struct. So you have ot print have to declare it like with: printf(" User ID: %d \n Age is: %d \n Weight is: %f \n",Nathan.UserID, Nathan.Age, Nathan.Weight );
struct users Nathan;
by using a typedef you don't have to specify the type via struct.
Use user Nathan; instead
I would recommend you to use online resources or books and start with easier challenges.

Adding records with pointers to arrays

I have to create a program which adds records to a simple phone book. The code is below, but it doesn't work - function ends and then it stucks on declaring struct record x and doesn't want to display my added record - the program breaks down. When I put this part of code on the end of the function (but instead of "struct record x = array[0];" I put "struct record x = (*array)[0]") it works - record is printed. So I guess the problem is something about pointers, but I'm struggling and I really couldn't find out what's wrong. I remember that few weeks ago I created a program which was very similar but it was adding a new record to an array of integers, with fixed values and it was working well, so maybe there's something with structures that I don't know about. Thanks for any help!
I know the program isn't done yet and I know that I didn't make any action for temp_array == NULL, it'll be done after I found out what's going on.
struct record {
char f_name[SIZE];
char name[SIZE];
long int phone;
};
int add_record(struct record** array, int n)
{
struct record* temp_array = malloc((n+1) * sizeof(struct record));
if (temp_array == NULL)
{
free(temp_array);
return -1;
}
int i;
for (i=0; i < n; i++)
{
temp_array[i] = (*array)[i];
}
struct record new_record;
printf("\nAplly data.");
printf("\nFirst name: "); /*fgets(new_record.f_name, SIZE, stdin);*/ scanf("%s", &new_record.f_name);
printf("Surname: "); /*fgets(new_record.name, SIZE, stdin);*/ scanf("%s", &new_record.name);
printf("Phone number: "); scanf("%d", &new_record.phone);
temp_array[n] = new_record;
free (*array);
*array = temp_array;
//struct record x = (*array)[0];
//puts(x.f_name); puts(x.name); printf("%d", x.phone);
return 0;
}
main()
{
struct record* array; int n = 0;
int choice;
printf("\n1. Add record\n2. Delete record\n3. Find record\n0. Exit\n\nChoose action: ");
scanf("%d", &choice);
switch(choice) {
case 0: printf("\nKsiazka zostala zamknieta.\n"); return;
case 1: add_record(&array, n); n++; break;
case 2: return;
case 3: return;
default: printf("Wrong choice.\n\n"); return;
}
struct record x = array[0];
puts(x.f_name); puts(x.name); printf("%d", x.phone);
}
struct record* array=NULL;, and use %ld for long int – BLUEPIXY

Searching through a linked list.

So i've been trying to understand the difference between a regularly defined structure without using malloc linked list that does utilize malloc.
The issue that i'm having right now is trying to search through the structure (pi) to find each part number that has a cost greater than what was entered into the search. this is my entire program so far. I've added comments for each section.
I'm simply not sure how i am suppose to search through each structure to compare its price to the search price.
#include <stdio.h>
#include <stdlib.h>
struct Item {
int quantity;
float cost;
char partNum[10];
struct Item *next;
};
void printItem(struct Item* pi);
void enterItem(struct Item* pi);
char search [100];
void main(int argc, char* argv[])
{
struct Item *pi;
struct Item *head;
int done = 0;
int i,j;
char choice;
// ENTERING ITEM INTO THE STRUCTURE
head = NULL;
while (!done) {
printf("Enter another item? (y/n)");
choice = getchar();
if (choice == 'y' || choice == 'Y') {
pi = (struct Item *)malloc(sizeof(struct Item));
enterItem(pi);
pi->next = head;
head = pi;
} else {
done = 1;
}
}
// SEARCHING FOR ITEM BY PRICE
printf("Enter a price to find all items more expensive, or type 'exit':");
while (strcmp(search, "exit") !=0) {
gets(search);
for (j = 0; j<i ; i++) {
if (strcmp(pi[j].cost, search) ==0) {
printItem(pi);
pi = pi->next;
}
}
}
}
getchar();
getchar();
}
// FUNCTION FOR PRINTING STRUCTURE ITEM
void printItem(struct Item* pi) {
printf("Quantity: %d\n", pi->quantity);
printf("Cost: $%.2f\n", pi->cost);
printf("Part # %s\n", pi->partNum);
printf("\n\n");
}
// FUNCITON FOR ENTERING IN NEW ITEM
void enterItem(struct Item* pi) {
printf("Quantity? ");
scanf("%d", &pi->quantity);
printf("Cost? ");
scanf("%f", &pi->cost);
getchar(); //need to clear out the carriage return from typeing in the cost
printf("Part Number? ");
gets(pi->partNum);
}
What you were doing wrong is comparing string(search variable) with a float(cost variable) using strcmp. This won't give you the desired output.
Instead, lets use -1 to indicate the exit, since parsing string and converting it to float is off-topic. Start iterating from head up to finding NULL, and compare the prices of the each item.
float price;
struct Item *it = head;
printf("Enter a price to find all items more expensive, or type '-1' to exit:");
scanf("%f", price);
// check price for the 'exit' -- compare with -1
while (it != NULL) {
if (it->cost > price)
printItem(pi);
it = it->next;
}

Resources