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;
}
Related
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;
New picture from an external compiler.. the exit code is ok?
enter image description here
This is the full code. I'm having a trouble program blows away after printing the wanted output to the screen. I guess it's a problem with the way I allocated memory for the array of structs, and the .name field of each struct in a for loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_NAME_LEN 50
typedef struct stud
{
char *name;
int marks[4];
float avg;
}student;
student* Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void printExcellent(student*);
void main()
{
int size, i;
student *arr, *newArr;
printf("\nEnter the number of students: ");
scanf_s("%d", &size);
newArr = Create_Class(&size);
for (i = 0; i < size; i++)
{
printExcellent(newArr+i);
}
for (i=0;i<size;i++) free(newArr[i].name);
free(newArr);
_getch();
}
student* Create_Class(int size)
{
student *p;
char str[MAX_NAME_LEN];
int i, j;
p = (student*)calloc(size , sizeof(student));
if (!p)
{
printf("Memory allocation failure.");
exit(1);
}
for (i = 0; i < size; i++)
{
printf("Enter your name: ");
rewind(stdin);
gets(str);
p[i].name = (char*)calloc(strlen(str)+1,sizeof(char));
if (!(p[i].name))
{
printf("Memory allocation error!");
exit(1);
}
strcpy_s(p[i].name,50,str);
printf("Enter your marks: ");
for (j = 0; j < 4; j++)
{
scanf_s("%d", &p[i].marks[j]);
}
Avg_Mark(p + i);
}
return p;
}
void Avg_Mark(student* s)
{
int i, sum=0;
for (i = 0; i < 4; i++)
sum += s->marks[i];
s->avg = (float)sum / 4;
}
void Print_One(student* s)
{
printf("The average of %s is %.1f\n", s->name, s->avg);
}
void printExcellent(student* s)
{
if ((s->avg) > 85)
Print_One(s);
}
Gonna point out everything fishy I see for you:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_NAME_LEN 50
typedef struct stud
{
char *name;
int marks[4];
float avg;
}student;
student* Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void printExcellent(student*);
void main()
{
int size, i;
student *arr, *newArr;
printf("\nEnter the number of students: ");
scanf_s("%d", &size);
// This is wrong. Remove the &...
newArr = Create_Class(&size);
for (i = 0; i < size; i++)
{
printExcellent(newArr+i);
}
for (i=0;i<size;i++) free(newArr[i].name);
free(newArr);
_getch();
}
student* Create_Class(int size)
{
student *p;
char str[MAX_NAME_LEN];
int i, j;
// Consider checking size for a sane value.
// Ok, allocate an array of students.
p = (student*)calloc(size , sizeof(student));
if (!p)
{
printf("Memory allocation failure.");
exit(1);
}
for (i = 0; i < size; i++)
{
printf("Enter your name: ");
// These 2 lines scare the heck out of me. I'd really do this differently.
// gets is the devil and the see:
// https://stackoverflow.com/questions/20052657/reversing-stdin-in-c
// for why this may not work well.
rewind(stdin);
gets(str);
// What if str is not a terminated string? Then 1 char of 0? Guess this is ok. Hope it doesn't overflow on the copy below though (consider fixed max size and not using a temporary)
p[i].name = (char*)calloc(strlen(str)+1,sizeof(char));
if (!(p[i].name))
{
printf("Memory allocation error!");
exit(1);
}
// Do a fast copy of up to 50 chars. I'd really want to verify this output to be sure it works.
strcpy_s(p[i].name,50,str);
printf("Enter your marks: ");
for (j = 0; j < 4; j++)
{
// Hope this inputs the way you want.
scanf_s("%d", &p[i].marks[j]);
}
// This should work, but I prefer more explicit pointers.
Avg_Mark(p + i);
}
return p;
}
void Avg_Mark(student* s)
{
// What if s is Null?
int i, sum=0;
// 4 is a magic number. Make this a constant.
for (i = 0; i < 4; i++)
sum += s->marks[i];
// This won't be as accurate as you want. Consider an integer solution.
s->avg = (float)sum / 4;
}
void Print_One(student* s)
{
// What if s is Null? What about s->name?
printf("The average of %s is %.1f\n", s->name, s->avg);
}
void printExcellent(student* s)
{
// What if s is Null?
if ((s->avg) > 85)
Print_One(s);
}
Note: While going through this code, I did not see any "red flags" except for the & on the size and perhaps the gets/rewind calls. I'd still add null asserts to your functions and also walk through it with a debugger to be sure that everything is as you expect. Honestly, there is enough going on here that I'd prefer the debugger help to my quick trace of the code while I was writing comments.
Update
If I change all your scanf_s to scanf() calls, replace your gets() / rewind() calls to a simple scanf("%s", str) call, and change your funky strcpy_s() function to a simpler strcpy() or strncpy() call, your program does not seem to crash for me. My money is that the strcpy_s() call is corrupting RAM while doing its "fast" copy.
I have a code like this for a student management system. The input function works fine but I haven't figured out why my output function stop immediately when i call it.( I know that i can not return a local array from a function in C, but i assign the array to a pointer and return that pointer, is it ok?)
Here is my code:
struct Student
{
char name[50];
char birth[25];
char gender[10];
float math, physics;
};
struct Student* input(int n, struct Student *p)
{
int i, id = 1;
struct Student s[n];
getchar();
for(i = 0; i < n; i++)
{
printf("Name: ");
fgets(s[i].name, 50, stdin);
s[i].name[strlen(s[i].name)-1] = '\0';
printf("Date of birth: ");
fgets(s[i].birth,25,stdin);
s[i].birth[strlen(s[i].birth)-1] = '\0';
printf("Gender: ");
fgets(s[i].gender,10,stdin);
s[i].gender[strlen(s[i].gender)-1] = '\0';
printf("Math = ");
scanf("%f", &s[i].math);
printf("Physics = ");
scanf("%f", &s[i].physics);
getchar();
}
p = s;
return p;
}
void outPut(int n, struct Student *p)
{
int i;
for(i = 0; i < n; i++)
{
printf("%s %s %s %f %f\n", p[i].name, p[i].birth, p[i].gender, p[i].math, p[i].physics);
}
}
int main()
{
int n;
struct Student *p, *p1;
int choice;
printf("-----------Student Management-----------");
printf("\n1. Add new students.\n2. Print student list.\n");
do
{
printf("Your choice = ");
scanf("%d", &choice);
switch(choice)
{
case 1:
printf("Number of students = ");
scanf("%d", &n);
input(n,p);
break;
case 2:
outPut(n,p);
break;
}
}
while(choice!=0);
return 0;
}
You are defining your array as a local variable. It means that it will no longer exist after the function ends. To avoid this, declare your array as a pointer and use malloc to initialize it:
struct Student *s = malloc(sizeof(Student) * n);
It will behave as a regular array and you will be able to use itself as the function return.
#include <string.h>
#include<stdio.h>
#include<stdlib.h>
typedef struct bank
{
char an;
char name;
char type;
int bal;
};
int main()
{
int i=0,n;
printf("Enter the number of accounts\n");
scanf("%d",&n);
struct bank a[n];
printf("Enter the details of the users\n");
for(i=0;i<n;i++)
{
scanf("%s%s%s%d",a[i].an,a[i].name,a[i].type,&a[i].bal);
}
printf("The details of the users are\n");
for(i=0;i<n;i++)
{printf("%s\n%s\n%s\n%d\n\n",a[i].an,a[i].name,a[i].type,a[i].bal);}
char atype[10];
printf("Enter the type of account you want to search\n");
scanf("%s",atype);
char typ[10];
char s[]="savings";
char c[]="current";
int result,res1,res2;
result = strcmp(atype,s);
if(result == 0)
{
for(i=0;i<n;i++)
{
typ[10] = a[i].type;
res1 = strcmp(typ,s);
if(res1 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an,a[i].name,a[i].type,a[i].bal);
}
printf("\n");
}
} else
{
for(i=0;i<n;i++)
{
typ[10] = a[i].type;
res2 = strcmp(typ,c);
if(res2 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an,a[i].name,a[i].type,a[i].bal);
}
printf("\n");
}
}
}
so basically ik its my homework but i did everythimg and i still cannot resolve the segmentation fault.please help
i think its something to do with strcmp() function but oh well
i checked all the sources but couldnt really find any fix.
any help would be appreciated.
For starters:
This
typ[10] = ...
accesses typ one past its valid memory. This invokes undefined behaviour, so anything can happen from then on.
In C array indexing is 0-based. So for char[10] the highest allowed index would be 9. Access the 1st element would be done by using 0.
You have made 2 mistakes here .
First your struct bank declaration was wrong. You forgot to declare name an and type as string. You declared it as just character(char).It should be like :-
struct bank
{
char an[100]; // assuming 100 is max size of input strings
char name[100];
char type[100];
int bal;
};
second you cannot do typ[10] = a[i].type; you should use strcpy() Something like this :-
strcpy(typ,a[i].type);
So this corrected code will work :-
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
struct bank // change made 1
{
char an[100];
char name[100];
char type[100];
int bal;
};
int main()
{
int i = 0, n;
printf("Enter the number of accounts\n");
scanf("%d", &n);
struct bank a[n];
printf("Enter the details of the users\n");
for (i = 0; i < n; i++)
{
scanf("%s%s%s%d", a[i].an, a[i].name, a[i].type, &a[i].bal);
}
printf("The details of the users are\n");
for (i = 0; i < n; i++)
{
printf("%s\n%s\n%s\n%d\n\n", a[i].an, a[i].name, a[i].type, a[i].bal);
}
char atype[10];
printf("Enter the type of account you want to search\n");
scanf("%s", atype);
char typ[10];
char s[] = "savings";
char c[] = "current";
int result, res1, res2;
result = strcmp(atype, s);
if (result == 0)
{
for (i = 0; i < n; i++)
{
strcpy(typ,a[i].type); // change made 2
res1 = strcmp(typ, s);
if (res1 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an, a[i].name, a[i].type, a[i].bal);
}
printf("\n");
}
}
else
{
for (i = 0; i < n; i++)
{
strcpy(typ,a[i].type); // change made 3
res2 = strcmp(typ, c);
if (res2 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an, a[i].name, a[i].type, a[i].bal);
}
printf("\n");
}
}
}
So your mistake was not with strcmp()
I have begin learning pointers in C.
When I try to return pointer in a function, I'm getting segmentation fault error.
Here is the code :
#include<stdio.h>
int *sum(int *, int *);
int main(void)
{
int a, b;
int *ans = NULL;
printf("Enter number a : ");
scanf("%d", &a);
printf("Enter number b : ");
scanf("%d", &b);
ans = sum(&a, &b);
printf("Sum = %d", *ans);
return 0;
}
int *sum(int *p, int *q)
{
int *result = NULL;
*result = *p + *q;
return (result);
}
And the output :
Enter number a : 10
Enter number b : 20
Segmentation fault
Segmentation fault occurs in sum function, when result is declared as pointer. However, I am unable to figure out the reason for the same. Any help regarding this is really appreciable.
You are initing a pointer to NULL and then you are deferencing it: it is Undefined behavior
Change sum function to
int *sum(int *p, int *q)
{
int *result = malloc(sizeof(int));
// check if malloc returned a valid pointer before to dereference it
if (result != NULL)
{
*result = *p + *q;
}
return (result);
}
and add a free call to free the allocated memory.
// check if sum function allocate the pointer before to dereference it
if (ans != NULL)
{
printf("Sum = %d", *ans);
}
free(ans);
return 0;
}
You could also avoid to use pointer to return value:
#include<stdio.h>
int sum(int *, int *);
int main(void)
{
int a, b;
int ans;
printf("Enter number a : ");
scanf("%d", &a);
printf("Enter number b : ");
scanf("%d", &b);
ans = sum(&a, &b);
printf("Sum = %d\n", ans);
return 0;
}
int sum(int *p, int *q)
{
int result = *p + *q;
return (result);
}
The sum function could also be like:
int sum (int *p, int *q)
{
return (*p + *q);
}
EDIT
As #JonathanLeffler wrote in his answer you can do also:
#include<stdio.h>
void sum(int *, int *, int *);
int main(void)
{
int a, b;
int ans;
printf("Enter number a : ");
scanf("%d", &a);
printf("Enter number b : ");
scanf("%d", &b);
sum(&ans, &a, &b);
printf("Sum = %d\n", ans);
return 0;
}
void sum(int *result, int *p, int *q)
{
*result = *p + *q;
}
Allocate memory before trying to store anything, and check the return of malloc()
int *result = NULL;
result = malloc(sizeof(*result));
if(result != NULL)
*result = *p + *q;
else
printf("malloc returned error");
Also, check the return of the function in main() and exit accordingly.
int main(void)
{
.
.
.
ans = sum(&a, &b);
if(ans == NULL)
return 0;
printf("Sum = %d\n", ans);
free(ans); //free the memory then
return 0;
}
A third alternative is to declare ans as a normal int variable in the main function and pass a pointer to it to the sum function, like you do with the other two arguments. This is actually emulating call by reference.
#include<stdio.h>
int *sum(int *, int *);
int main(void)
{
int a, b;
printf("Enter number a : ");
scanf("%d", &a);
printf("Enter number b : ");
scanf("%d", &b);
int* ans = sum(&a, &b);
printf("Sum = %d", *ans);
return 0;
}
int *sum(int *p, int *q)
{
int plus = *p + *q;
int *ans = +
return ans;
}
Store the Sum in a Different variable plus and create a pointer *ans that points to that variable plus and return the pointer variable ans that holds the address of plus