Since I've had several members tell me to post the whole program I'm gonna post the whole program so you can exectue it.
In this program I want to be able to register car parts and change the inventory balance.
Now to the issue. Every function itself worsk well, the problem starts when I call searchIt() function to changeIn() function. I need searchIt() so I can search the item before modifying its inventory balance.
Issues:
Whenever I serach for an item and change inventory on that item, it changes on every item.
In menu if I choose (3)change inventory balance and then serach for an item that does not exist it does not tell me "Wrong item number" instead it exits the program.
The inventory balance goes to negative numbers.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXELENGTH 20
#define MAX 100
struct car{
int itemNmr;
char name[MAXELENGTH];
int inventory;
};
typedef struct car Car;
void registerArticle(Car a[], int *pN);
void print(Car a[], int n);
void changeIn(Car a[], int n);
int searchIt(Car a[], int n);
Car createIt(int itemNmr, char name[],int inventory){
Car c;
c.itemNmr = itemNmr;
strcpy(c.name, name);
c.inventory = inventory;
return c;
}
int main(){
Car reg[MAX];
int choice;
int nrOfIt=0;
while(1){
printf("(1)Register new pars\n(2)Display all parts\n(3)Change inventory\n(4)Search\n(5)Exit\n");
scanf("%d", &choice);
switch(choice){
case 1: registerArticle(reg, &nrOfIt);
break;
case 2: print(reg,nrOfIt);
break;
case 3: changeIn(reg,nrOfIt);
break;
case 4: searchIt(reg,nrOfIt);
break;
case 5: printf("Exit");
return 0;
default: printf("Try again!");
break;
}
} return 0;
}
void registerArticle(Car a[], int *pN){
int inventory;
int itemNmr;
char name[MAXELENGTH];
while(1){
printf("Item number(0 to exit): ");
scanf("%d%*c", &itemNmr);
if(itemNmr==0){
return;
}
printf("Name: ");
scanf("%s%*c", name);
printf("Inventory: ");
scanf("%d%*c", &inventory);
a[*pN]=createIt(itemNmr,name,inventory);
(*pN)++;
}
}
void print(Car a[], int n){
if(n==0){
printf("the list is empty\n");
}else{
for(int i=0;i<n;i++){
printf("%d\t\t%s\t\t%d\n", a[i].itemNmr, a[i].name, a[i].inventory);
}
return;
}
}
int searchIt(Car a[], int n){
while(1){
int itemN;
printf("Type item number: ");
scanf("%d", &itemN);
if(itemN==0){
break;
}
int found =0;
for(int i=0;i<n;++i)
{
if(itemN==a[i].itemNmr)
{
printf("%d\t\t%s\t\t%d\n", a[i].itemNmr, a[i].name, a[i].inventory);
return i;
break;
}
}
if(!found)
{
printf("Wrong item number!");
}
}
return 0;
}
void changeIn(Car a[], int n){
int input;
int i;
searchIt(a,i);
printf("Increase or decrease by: ");
scanf("%d", &input);
for(i=0;i<n;i++)
a[i].inventory += input;
if(a[i].inventory<0)
a[i].inventory = 0;
}
```
This:
void changeIn(Car a[], int n)
{
int input;
int i;
searchIt(a, i);
passes an uninitialized register-length to searchIt(), probably causing it to go way out of bounds. Then it throws away the return value of searchIt(), and then uses the still uninitialized i to index into the array. Not good. It should be:
void changeIn(Car a[], int n)
{
int input;
const int i = searchIt(a, n);
Edit:
As you pointed out in a comment, yes the loop in changeIt() makes no sense; you don't want to change more than one element so there is no need to loop. Looping is for expressing repetition and there's no need for that here.
It should just be:
a[i].inventory += input;
if (a[i].inventory < 0)
a[i].inventory = 0;
Related
This is for schoolwork and the question is asking to make a programme like a student database where I am able to input, print and remove students from the structure s using pointers function. However I am unable to delete the student records as something weird happens. The target student gets deleted but the rest of the students records(names only) are shifted, with only the first character being correct. Please help!
#include <stdio.h>
#include <string.h>
#define SIZE 50
typedef struct {
int id;
char name[50];
} Student;
void inputStud(Student *s, int size);
void printStud(Student *s, int size);
int removeStud(Student *s, int *size, char *target);
int main()
{
Student s[SIZE];
int size=0, choice;
char target[80], *p;
int result;
printf("Select one of the following options: \n");
printf("1: inputStud()\n");
printf("2: removeStud()\n");
printf("3: printStud()\n");
printf("4: exit()\n");
do {
printf("Enter your choice: \n");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter size: \n");
scanf("%d", &size);
printf("Enter %d students: \n", size);
inputStud(s, size);
break;
case 2:
printf("Enter name to be removed: \n");
scanf("\n");
fgets(target, 80, stdin);
if (p=strchr(target,'\n')) *p = '\0';
printf("removeStud(): ");
result = removeStud(s, &size, target);
if (result == 0)
printf("Successfully removed\n");
else if (result == 1)
printf("Array is empty\n");
else if (result == 2)
printf("The target does not exist\n");
else
printf("An error has occurred\n");
break;
case 3:
printStud(s, size);
break;
}
} while (choice < 4);
return 0;
}
void inputStud(Student *s, int size)
{
int i=0;
char *p,dummy[50];
while (i<size) {
printf("Student ID: \n");
scanf("%d",&((s+i)->id));
printf("Student Name: \n");
scanf("\n");
fgets((s+i)->name, 50,stdin);
if (p=strchr((s+i)->name,'\n')) *p = '\0';
i++;
}
}
void printStud(Student *s, int size)
{
int i;
printf("The current student list: \n");
if (size==0) printf("Empty array\n");
else {
for (i=0; i<size; i++) {
printf("Student ID: %d ",(s+i)->id);
printf("Student Name: %s\n",(s+i)->name);
}
}
}
int removeStud(Student *s, int *size, char *target)
{
int i,j,k;
if (*size==0) return 1;
for (i=0;i<*size;i++) {
if (strcmp(((s+i)->name),target)==0) {
--*size;
for (j=i; j<=*size; j++) {
k = j + 1;
*((s+j)->name) = *((s+k)->name);
(s+j)->id = (s+j+1)->id;
if ((s+j+1)->id=='\0') (s+j)->id = '\0';
}
return 0;
}
}
return 2;
}
you were almost there.
The problem is at line 97: *((s+j)->name) = *((s+k)->name);
To make it work, this instruction should be substituted with:
strcpy((s+j)->name, (s+k)->name);
Why:
you are coping with char arrays, so doing *((s+j)->name) = *((s+k)->name) means: "put the value of the first char of s+k->name into s+j->name first char".
Instead, you want to copy the whole name of s+k into the s+j name.
on how to use strcpy you can take a look here
whenever I load the data, the program only retrieve the first line of the file and then it loops. It looks like the problem lies within the load function and insert function because that's where the code loads the data from the file and where the data loaded insert to the array of the code, I tried adding a sign if the code really loops the, and it really did loop. I think the problem is !feof int the load function but i don't know if it really is.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <stdbool.h>
#define MAX 10
//Variables
int Ident[MAX];
float grade[MAX];
char name[MAX][20];
int last;
//Functions
int GetRec();
float ComputeGrade(int q1, int q2);
void display();
void EmpList();
int IsEmpty();
int IsFull();
int DelRec();
int menu();
void CheckID(int x);
void save();
void load();
void insert(int x, char n[], float a);
int main(){
EmpList();
load();
menu();
}
void EmpList(){
last = -1;
}
int IsFull(){
return (last==MAX - 1);
}
int IsEmpty(){
return (last==-1);
}
int menu(){
int Opt;
do{
system("cls");
printf("[1] Insert\n");
printf("[2] Delete\n");
printf("[3] Display\n");
printf("[4] Exit\n");
scanf("%d", &Opt);
switch(Opt){
case 1: system("cls");
GetRec();break;
case 2: DelRec();
break;
case 3: system("cls");
display();
break;
case 4: save();
return 0;
break;
default:menu();
break;
}
}while(1);
}
int GetRec(){
char NameTemp[20];
int quiz_1, quiz_2, Idtemp;
float ave;
printf("Insert Mode\n");
printf("Input ID no:");
scanf("%d", &Idtemp);
printf("Input name: ");
scanf("%s", &NameTemp);
printf("Input quiz 1: ");
scanf("%d", &quiz_1);
printf("Input quiz 2: ");
scanf("%d", &quiz_2);
ave = ComputeGrade(quiz_1, quiz_2);
CheckID(Idtemp);
insert(Idtemp, NameTemp, ave);
}
void CheckID(int x){
for(int check = 0; check <= last; check++){
if(x == Ident[check]){
printf("Id already exist\nTry another one.");
getch();
system("cls");
GetRec();
}
}
}
void insert(int x, char n[], float a){
char *ptr;
if (IsFull()){
printf("Full.");
getch();
menu();
}
else if(x == -1){
EmpList();
}
else{
last++;
printf("%d", last);
Ident[last] = x;
grade[last] = a;
ptr = n;
strcpy(name[last], n);
}
}
float ComputeGrade(int q1, int q2){
float ave;
ave = (q1 + q2) / 2.0;
return ave;
}
int DelRec(){
printf("Delete Mode\n");
printf("Input Id no: ");
getch();
main();
}
void display(){
if(IsEmpty()){
printf("Empty");
getch();
menu();
}
else{
for(int counter = 0; counter <= last; counter++){
printf("[%d]%s\t%.2f\n", Ident[counter], name[counter], grade[counter]);
}getch();
}
}
void save(){
FILE *fp;
fp=fopen("database.dbf","w+");
for(int counter = 0; counter <= last; counter++){
fprintf(fp, "%d %s %.2f\n", Ident[counter], name[counter], grade[counter]);
}
fclose(fp);
}
void load(){
FILE *fp;
int id = -1,grd = 0;
char nm[20];
fp=fopen("database.dbf","r+");
while(!feof(fp)){
fscanf(fp,"%d %s %d", &id, &nm, &grd);
insert(id, nm, grd);
}
fclose(fp);
}
Your load() function always does insert(-1, ...) and insert() tests for -1 and does something you don't want it to do.
I'm 2nd year computer engineer and still in learning process of C language. I'd like to undesrtand how to dynamically alocate an array by using function instead of allocate inside the main.
Here is the code that works when I allocate array inside main.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
#define ESC_KEY 27
#define NUM_1_KEY 49
#define NUM_2_KEY 50
void find_two_largest(int a[], int n, int *largest, int *second_largest);
void arrayInit(int *,int *, int, int);
void randGenArray(int [], int);
void inputArray(int[], int);
void result(int, int);
void loading(void);
int menu(void);
int main(void)
{
system("color f5");
int n,i,largest,largest_2, *a;
arrayInit(a,&n, 2, 10);
if(menu())
randGenArray(a,n);
else
inputArray(a,n);
find_two_largest(a,n,&largest,&largest_2);
result(largest,largest_2);
return 0;
}
void find_two_largest(int a[], int n, int *largest, int *second_largest)
{
int i=0,j=0;
system("cls");
loading();
*largest = 0;
*second_largest = *largest;
for (i=1;i<n;i++){
if(*largest<a[i])
*largest=a[i];
}
for(j=1;j<n;j++){
if(*largest==a[j])
continue;
else{
if(*second_largest<a[j])
*second_largest=a[j];
}
}
return;
}
void randGenArray(int a[], int n)
{
srand(time(NULL));
int i;
for(i=0; i<n; i++){
a[i]=rand()%100;
Sleep(10);
printf("\n>> Integer %d: %d", i+1, a[i]);
}
printf("\n\n\nPress any key to continue...");
getch();
return;
}
void inputArray(int a[], int n)
{
int i;
for(i=0; i<n; i++){
printf("\n Please enter integer %d: ", i+1);
scanf("%d",&a[i]);
}
return;
}
int menu(void)
{
char _char;
printf("\n Please choose one of the following options:\n 1.Fill array manually\n 2.Fill array by random numbers\n\n ");
while(1)
{
_char = getch();
switch(_char)
{
case ESC_KEY:
printf("\n\n Thank you for using our software!\n\n");
exit(0);
case NUM_1_KEY:
system("cls");
return 0;
case NUM_2_KEY:
system("cls");
return 1;
default:
break;
}
}
}
void arrayInit(int *a,int *n, int min, int max)
{
printf("\n Please enter a length of the array: ");
do{
scanf("%d", n);
if (*n<min||*n>max)
printf("\nThe ranged is limited. Please enter the value between %d and %d.\n", min, max);
} while(*n<min||*n>max);
a = (int*)calloc(*n,sizeof(int));
return;
}
void loading(void)
{
printf("\n Loading");
printf(".");
Sleep(300);
printf(".");
Sleep(300);
printf(".");
Sleep(300);
system("cls");
return;
}
void result(int l, int l2)
{
system("cls");
printf("\n Largest = %d Second Largest = %d",l,l2);
Sleep(500);
printf("\n\n\n Thank you using our software! ;D\n\n");
return;
}
But if you cut and paste this line from arrayInit to main and change *n to n - it will work!
a = (int*)calloc(*n,sizeof(int));
I'm sorry for asking about so stupid and obvious things but I didn't figure it out by myself. Thank you for any advice.
Here is a simple program which will show you how to do that -
#include <stdio.h>
#include <stdlib.h>
void create(int **p,int n); // function taking arguments as int ** and n is number of elements
int main(void) {
int *a;
int n=5,i; // declare and initialize n
create(&a,n); // pass address of a to function
for(i=0;i<n;i++){
a[i]=i; // store value of i in a[i]
printf("%d\n",i); // print a[i]
}
free(a); // free the allocated memory
return 0;
}
void create(int **p, int n){
*p=calloc(n,sizeof(int)); // allocate memory to *p (type- is int *)
}
Working Code
You must change your function return type
void * arrayInit(int *n, int min, int max)
{
printf("\n Please enter a length of the array: ");
do{
scanf("%d", n);
if (*n<min||*n>max)
printf("\nThe ranged is limited. Please enter the value between %d and %d.\n", min, max);
} while(*n<min||*n>max);
return calloc(*n,sizeof(int));
}
And call it from main in this way: a = arrayInit(&n, 2, 10);
I want to pass a pointer to a multidimensional Array, so the value could be kept not copied. How can I do it? I also keep tracking the int count, will it work every time? The array that I need is memory. The struct has been declared before, outside the main.
struct registers
{
int data;
} registerX, registerY;
void first(int *counter, struct registers* X1, int **m)
{
int value;
printf("Enter the value for the X\n");
scanf("%d", &value);
X1->data = value;
m[*counter][1] = X1->data;
*counter = *counter++;
}
int main()
{
int memory[SIZE][2];
int count = 0;
int choice;
printf("Enter the instruction number:\n");
while(choice != 107)
{
scanf("%d", &choice);
if(choice == 101)
{
memory[count][0] = 101;
first(&count, ®isterX, &memory[count][1]);
}
The function signature should be:
void first(int *counter, struct registers* X1, int m[][2])
Or equivalently:
void first(int *counter, struct registers* X1, int (*m)[2])
The call should be:
first(&count, ®isterX, memory);
First of all, apart from what Kerrek SB said, you could replace
*counter = *counter++;
with this
(*counter)++;
EDIT: Sorry, I made a mistake trying to say what's wrong with *counter = *counter++, but I got some strange results with the sentence *pointer = *pointer++.
Second, I see that you are using registerX while it's just a type, so you could first do this.
registerX *rgx = NULL;
rgx = malloc(sizeof(registerX));
and use.
first(&count, rgx, memory);
Considering what I said above, this code worked for me.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5
typedef struct registers {
int data;
} registerX, registerY;
void first(int *counter, struct registers *X1, int m[][2]) {
int value;
printf("Enter the value for the X: ");
scanf("%d", &value);
X1->data = value;
m[*counter][1] = X1->data;
(*counter)++;
return ;
}
int main() {
int memory[SIZE][2];
int count = 0;
int choice;
registerX *rgx = NULL;
rgx = malloc(sizeof(registerX));
printf("Enter the instruction number: ");
while(choice != 107) {
scanf("%d", &choice);
if (choice == 101) {
memory[count][0] = 101;
first(&count, rgx, memory);
printf("Number %d was stored in memory[%d][%d]\n\n", memory[count-1][1], count-1, 1);
}
printf("Enter more instructions: ");
}
return 0;
}
The problem i have is even though i set the array called exam[] to zero in main, when i call the function displayAllExam() only some are set to zero and others are set to random numbers that probably represent spaces in ram. This is messing up my displayExamAverage() function because when i run the code i can add values to the array but if i dont add 50 values then there will be random numbers in there. Also im really stuck on the displayHighLow function which is ment to find the highest and lowest value of the array
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define pause system("pause")
#define cls system("cls")
#define flush fflush(stdin)
#define SIZE 50
//Lets Prototype
int getChoice();
void displayMenu();
void addScores(int a[],int *c);
void displayAllExam(int a[]);
void displayExamAverage(int a[], int *c);
void displayHighLow(int a[], int *c);
main(){
int exams[SIZE] = {0}, counter = 0;
char choice;
do {
choice = getChoice();
switch(choice){
case 1:
addScores(&exams[SIZE],&counter);
break;
case 2:
displayExamAverage(&exams[SIZE],&counter);
break;
case 3:
displayHighLow(&exams[SIZE], &counter);
break;
case 4:
displayAllExam(&exams[SIZE]);
break;
}
}while (choice != 5);
}//end main
int getChoice(){
int result = 0;
do{
displayMenu();
scanf_s("%i", &result);
if(result < 1 || result >5 ){
printf("Invalid Selection, please enter a number between 1 and 5\n");
pause;}
} while(result < 1 || result > 5);
return result;
}//end getChoice
void displayMenu() {
cls;
printf("MAIN MENU\n\n");
printf("1: add an exam score\n");
printf("2.Display exam average\n");
printf("3.Display High and Low score\n");
printf("4.Display all scores\n");
printf("5.Quit\n\n");
printf("Enter your choice: \n\n");
return;
}//end display menu
void addScores(int a[SIZE],int *c){
int i=0;
printf("please enter your score..");
scanf_s("%i", &a[i]);
}//end add scores
void displayExamAverage(int a[],int *c){
float average, total = 0.0;
int i;
for(i=0; i < *c; i++)
total = total + a[i];
average = total/ *c;
printf("%f",average);
pause;
}//end displayExamAverage
void displayHighLow(int a[],int *c){
int high= a[0], low= a[0];
int i,x,y;
for(i=0; i < *c; i++){
if(a[*c]> a[0])
high = a[i];
}
for(i=0; i < *c; i++){
if(a[*c]<a[0])
low = a[i];
}
printf("The low is %i", low);
printf("The high is %i", high);
pause;
}//end DisplayHighLow
void displayAllExam(int a[SIZE]){
int i;
for(i=0;i < SIZE; i++)
printf("the %i score is %i\n",i+1,a[i]);
pause;
}//end displayAllExam
You're passing a pointer to the position just after the end of the array. That's a big no-no, if you plan to read or write to it:
displayAllExam(&exams[SIZE]);
Instead, just pass it like this:
displayAllExam(exams);
Same goes for all your other calls.