How to search on struct char c? - c

#include<stdio.h>
#include<stdlib.h> //libraries
#include<string.h>
#define ARRAY_SIZE 4 //define the array size is 4
Declare a Person structure containing the following two data members: name and age.
struct Person
{
char name[20];
int age;
};
Define fillPersons function that takes an empty array of Persons, and fills the array.
void fillPersons(struct Person * myPs);
For function using
struct Person p[ARRAY_SIZE];
Define searchPerson function that takes an array of Persons, and the name to search for. The function will return the corresponding age if the person is found, -1 otherwise.
int searchPerson(struct Person * myPs, char * myName);
Define printPersons function that takes an array of Persons, and prints the content of the array.
void printPersons(struct Person * myPs);
Main Fuction
int main()
{
struct Person p[ARRAY_SIZE];
int a;
int isFound;
char myName[20];
Switch case for user interface
do
{
printf("1)FILL ARRAY\n");
printf("2)SEARCH BY NAME\n");
printf("3)PRINT ARRAY\n");
printf("4)EXIT\n");
printf("Search Operation:");
scanf_s("%d", &a);
switch (a)
{
case 1:fillPersons(p); break;
I write the main part of searching but i cant fill the function.
case 2:printf("\Give the name to search for:");
scanf_s("%s", &myName);
isFound = searchPerson(p, myName);
if (isFound == -1)
{
printf("%s not avaible in the array. \n", myName);
}
else
{
printf("The age of %s is %d.\n", myName, isFound);
}
break;
After this part it is okay to read names and ages but cant do it searching part.
case 3:printPersons(p); break;
case 4:printf("\nProgram exits ..."); exit(0);
}
} while (a != 4);
system("pause");
return 0;
}
It is okay this scanf part
void fillPersons(struct Person * myPs)
{
int i;
for (i = 0; i < 4; i++)//defining 4 person i<4
{
scanf_s("%20s", p[i].name,_countof(p[i].name));//if i dont do _coutof
scanf_s("%d", &p[i].age); // i get null.ptr error
} // on visiual studio
}
Printing the student names and ages
void printPersons(struct Person * myPs)
{
int i;
for (i = 0; i < 4; i++)
{
printf("%s %d", p[i].name, p[i].age);
}
}
But i dont know how to fill with inside on fuction?
int searchPerson(struct Person * myPs, char * myName)
THE OUTPUT SHOULD BE LIKE THIS

Seems the function you are missing is strcmp to compare two strings.
It could be like:
int searchPerson(struct Person * myPs, char * myName)
{
int i;
for (i = 0; i < ARRAY_SIZE; i++)
{
if (strcmp(myPs[i].name, myName) == 0)
{
return myPs[i].age;
}
}
return -1;
}
In general notice:
When you pass the array to a function as struct Person * myPs, you must use myPs inside the function. Further you should use the defined array size instead of hard coding a 4.
So your printPersons should be:
void printPersons(struct Person * myPs)
{
int i;
for (i = 0; i < ARRAY_SIZE; i++)
{
printf("%s %d", myPs[i].name, myPs[i].age);
}
}
Same applies to fillPersons

First thing, you put in your question all the functions except the one that is giving you problems: searchPerson.
Then, your error is with this instruction:
scanf_s("%s", &myName);
Accordingly that you declared myName as a char pointer, this way, you're assigning the string to the address of myName, not to the memory cells it's pointing to.
Instead, this should be:
scanf_s("%s", myName);

Related

passing 'person [4]' to parameter of incompatible type 'person'

Here I'm trying to write a c programming below,Here I created a data type person which has two arguments name and number (creating a name of the candidate and votes they have recieved), and when prompt for input,if user enters the name in the array of person data_type and number corresponds to that number should increase,but I got stuck in this error below.
#include<stdio.h>
#include<cs50.h>
#include<string.h>
//Making person variable
typedef struct
{
string name;
int number;
}
person;
int update_vote(string name,person arr);
int main(void)
{
person cand[4];
cand[0].name="Brian";
cand[1].name="David";
cand[2].name="Obama";
cand[3].name="Biden";
cand[0].number=0;
cand[1].number=0;
cand[2].number=0;
cand[3].number=0;
//print the candidate names on the screen
float len=sizeof(cand)/sizeof(cand[0]);
int yu =(int) len;
printf("Candidates Who are participating:");
printf("\n");
for (int i=0;i<yu;i++)
{
printf("%i.%s ",i+1,cand[i].name);
}
printf("\n");
//prompt for voters and take votes and update
int voters=get_int("Enter the number of voters:");
for (int j=0;j<voters;j++)
{
string vote=get_string("Enter your vote:");
int update=update_vote(vote,cand);
if (update!=-1)
{
cand[update].number++;
}
else{
printf("Invalid name entered");
}
}
printf("%d",cand);
}
int update_vote(string name,person arr)
{
float len=sizeof(arr)/sizeof(arr[0]);
int yu =(int) len;
for(int i=0;i<yu;i++)
{
if (strcmp((name,arr[i].name)==0))
{
return i;
}
}
return -1;
}
But got stuck in figuring out why the error is occuring below
error: passing 'person [4]' to parameter of incompatible type 'person'
int update=update_vote(vote,cand);
The error is because you are passing person* where person is expected as an argument.
You should change the type of argument so that it can receive (a pointer to) an array.
Also note that sizeof cannot be used to determing the number of elements of arrays passed as arguments. You should pass the number of elements separately.
Another point is that printf("%d",cand); will invoke undefined behavior because data having wrong type is passed. %d expects int. If you want to print a pointer, you should cast it to void* and use %p format specifier.
Try this:
#include<stdio.h>
#include<cs50.h>
#include<string.h>
//Making person variable
typedef struct
{
string name;
int number;
}
person;
int update_vote(string name,person* arr,int arrSize); /* fix arguments */
int main(void)
{
person cand[4];
cand[0].name="Brian";
cand[1].name="David";
cand[2].name="Obama";
cand[3].name="Biden";
cand[0].number=0;
cand[1].number=0;
cand[2].number=0;
cand[3].number=0;
//print the candidate names on the screen
float len=sizeof(cand)/sizeof(cand[0]);
int yu =(int) len;
printf("Candidates Who are participating:");
printf("\n");
for (int i=0;i<yu;i++)
{
printf("%i.%s ",i+1,cand[i].name);
}
printf("\n");
//prompt for voters and take votes and update
int voters=get_int("Enter the number of voters:");
for (int j=0;j<voters;j++)
{
string vote=get_string("Enter your vote:");
int update=update_vote(vote,cand,yu); /* pass the number of elements */
if (update!=-1)
{
cand[update].number++;
}
else{
printf("Invalid name entered");
}
}
printf("%p",(void*)cand); /* use correct way to print a pointer */
}
int update_vote(string name,person* arr,int arrSize) /* fix arguments */
{
int yu =arrSize; /* use the passed size instead of sizeof */
for(int i=0;i<yu;i++)
{
if (strcmp((name,arr[i].name)==0))
{
return i;
}
}
return -1;
}
Because person cand[4]; , when you use " int update=update_vote(vote,cand);" , it means 'person *' that it's pointer.

Why am I getting garbage value after displaying the data

I am getting garbage value when I display the records.
I have to create a database of students in C using array of structures and without pointers.
Is there any other way of doing this?
How to use array of structures?
#include <stdio.h>
struct student {
char first_name[10],last_name[10];
int roll;
char address[20];
float marks;
};
void accept(struct student);
void display(struct student);
void main() {
struct student S[10];
int n, i;
printf("Enter the number of records to enter : ");
scanf("%d", &n);
for (i = 0; i < n; i++) {
accept(S[i]);
}
for (i = 0; i < n; i++) {
display(S[i]);
}
}
void accept(struct student S) {
scanf("%s", S.first_name);
scanf("%s", S.last_name);
scanf("%d", &S.roll);
scanf("%s", S.address);
scanf("%f", &S.marks);
}
void display(struct student S) {
printf("\n%s", S.first_name);
printf("\n%s", S.last_name);
printf("\n%d", S.roll);
printf("\n%s", S.address);
}
Everything in C is pass-by-value. Which means you are modifying variable copy in stack frame, while real variable passed as parameter remains untouched.
You have to pass an pointer to variable which you want to modify in function.
// Function declaration
void accept(struct student *);
// Call
accept(&S[i]);
// Usage in function via dereference operator
scanf("%s",S->first_name);
If you would like to enter unknown amount of records, you should use VLA (since c99) or dynamically allocate structures.
VLA
scanf("%d",&n);
struct student S[n];
Dynamic callocation
scanf("%d",&n);
struct student * S = malloc(sizeof(struct student) * n);
Because in your case, if user input more that 9 records you are touching outside of bounds, which has undefined behavior.
There are multiple issues in your code:
The standard prototype for main without arguments is int main(void)
You should allocate the array dynamically with calloc.
you should pass structure pointers to the accept and display functions instead of passing structures by value. Passing the destination structure by value is incorrect as the accept function cannot modify the structure in the main function, which remains uninitialized and causes garbage to be displayed. Note that it is actually undefined behavior to access uninitialized data so the program could behave in even worse ways.
You should provide scanf() with the maximum number of arguments to store into character arrays to avoid potential buffer overflows.
you should verify the return values of scanf() to avoid undefined behavior on invalid input.
you could use the %[^\n] scan set to allow embedded spaces in the address field.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct student {
char first_name[10], last_name[10];
int roll;
char address[20];
float marks;
};
void accept(struct student *sp);
void display(const struct student *sp);
int main(void) {
struct student *S;
int n, i, j;
printf("Enter the number of records to enter : ");
if (scanf("%d", &n) != 1)
return 1;
S = calloc(sizeof(*S), n);
if (S == NULL) {
return 1;
}
for (i = 0; i < n; i++) {
accept(&S[i]);
}
for (i = 0; i < n; i++) {
display(&S[i]);
}
free(S);
return 0;
}
void accept(struct student *sp) {
if (scanf("%9s%9s&d %19[^\n]%f",
sp->first_name, sp->last_name, &sp->roll,
sp->address, &sp->marks) != 5) {
printf("missing input\n");
exit(1);
}
}
void display(const struct student *sp) {
printf("%s\n", sp->first_name);
printf("%s\n", sp->last_name);
printf("%d\n", sp->roll);
printf("%s\n", sp->address);
printf("%f\n", sp->marks);
printf("\n");
}

Handling struct functions in C - Can enter an array but not an int

I'm having a bit of trouble with using structs inside functions.
The program is meant to:
Create an array containing five structures of type Person
Allow the user to enter the datatypes through use of functions.
Print the five entered people one by one.
While point 1 and 3 work fine, it's point 2 that I'm having issues with. The name will enter and print just fine, but regardless of what I enter into scanf it returns and prints '-858993460'.
int calls = 0;
typedef struct person {
char name[20];
int bYr;
}Person;
int main(int argc, char** argv) {
Person psn[5];
for (int i = 0; i < 5; i++) {
printf("Please enter the name and birthyear of person %d.", i+1);
personName(psn[i].name);
personBirthyear(psn[i].bYr);
}
for (int i = 0; i < 5; i++) {
printPerson(psn[i]);
}
getchar();
return 0;
}
int personBirthyear(int birthyear) {
printf("\nBirthyear: ");
scanf("%d", &birthyear);
getchar();
return birthyear;
}
char* personName(char* pername) {
printf("\nName: ");
fgets(pername, 20, stdin);
return pername;
}
void printPerson(Person prsn) {
printf("Person %d:\nBirthyear: %d\nName: %s\n", calls+1, prsn.bYr, prsn.name);
calls++;
}
Easy enough: you are not updating a Person' year, but you are passing it as a copied argument (you copy an int in personBirthyear and a pointer to a char in personName).
Thus:
personName(psn[i].name); // works
personBirthyear(psn[i].bYr); // fails
You need to pass the address of year, and work with pointers here:
int personBirthyear(int* birthyear) {
printf("\nBirthyear: ");
scanf("%d", birthyear);
getchar();
return *birthyear;
}
Or, you could also remove the birth year:
int personBirthyear() {
int birthyear;
printf("\nBirthyear: ");
scanf("%d", &birthyear);
getchar();
return birthyear;
}
Then: psn[i].bYr = personBirthyear();
In any case, you don't check the result of scanf; thus you don't know if you actually read a number. You should check it:
int n = scanf("%d", &birthyear);
getchar();
if (n != 1) return -1;
return birthyear;
The getchar is still mandatory to "clear" away the character that made scanf fail (otherwise, it would be reread again and again...).
you have some problems in your code :
You are not receiving a output while returning from function.
Without function declaration compiler will confuse about function return type.
you should know if you want to accept modified data between function call, data should provide as pass by reference. in your program, you give data to personBirthyear() function as call by value.

Am I using structs in the wrong way?

I have come across this wierd and mysterous (at least to me) error that I am finding a very hard time finding. It gives me an error at the line where I call my function input(student_list1[MAX], &total_entries); where the compiler says:
incompatible type for agument 1 in 'input'
What am I doing wrong here? I sense it something very simple and stupid but I have gone through the code several times now without any avail.
#define MAX 10
#define NAME_LEN 15
struct person {
char name[NAME_LEN+1];
int age;
};
void input(struct person student_list1[MAX], int *total_entries);
int main(void)
{
struct person student_list1[MAX];
int total_entries=0, i;
input(student_list1[MAX], &total_entries);
for(i=0; i<total_entries; i++)
{
printf("Student 1:\tNamn: %s.\tAge: %s.\n", student_list1[i].name, student_list1[i].age);
}
return 0;
} //main end
void input(struct person student_list1[MAX], int *total_entries)
{
int done=0;
while(done!=1)
{
int i=0;
printf("Name of student: ");
fgets(student_list1[i].name, strlen(student_list1[i].name), stdin);
student_list1[i].name[strlen(student_list1[i].name)-1]=0;
if(student_list1[i].name==0) {
done=1;
}
else {
printf("Age of student: ");
scanf("%d", student_list1[i].age);
*total_entries++;
i++;
}
}
}
struct person student_list1[MAX] in the function argument is actually a pointer to struct person student_list1.
student_list1[MAX] you passed is a (out of bound) member of the array struct person student_list1[MAX]. Valid array index shoudl be between 0 to MAX - 1.
Change it to:
input(student_list1, &total_entries);
Note that here the array name student_list1 is automatically converted to a pointer to student_list1[0].
There are many things wrong with the code; this is my attempt at making it somewhat more robust:
#include <stdio.h>
#include <string.h>
#define MAX 10
#define NAME_LEN 15
// use a typedef to simplify code
typedef struct person {
char name[NAME_LEN];
int age;
} person_t;
// size qualifier on student_list is redundent and person_t* does the same
void input(person_t *student_list, int *total_entries);
int main(void)
{
person_t student_list[MAX];
int total_entries, i;
// pass array and not the non-existent 'student_list[MAX]' element
input(student_list, &total_entries);
for(i=0; i<total_entries; i++)
{
// age is an int, not a string so use %d
printf("Student 1:\tName: %s.\tAge: %d.\n", student_list[i].name, student_list[i].age);
}
return 0;
} //main end
void input(person_t *student_list, int *total_entries)
{
int done = 0, i = 0;
*total_entries = 0;
while (i < MAX) {
printf("Name of student: ");
// use NAME_LEN instead of strlen(list[i].name) because latter is
// probably not initialized at this stage
if (fgets(student_list[i].name, NAME_LEN, stdin) == NULL) {
return;
}
// detect zero-length string
if (student_list[i].name[0] == '\n') {
return;
}
printf("Age of student: ");
scanf("%d", &student_list[i].age);
// read the newline
fgetc(stdin);
*total_entries = ++i;
}
}
input(student_list1[MAX], &total_entries); shoud be input(student_list1, &total_entries);.
In C,
void input(struct person student_list1[MAX], int *total_entries);
equals
void input(struct person *student_list1, int *total_entries);

dynamic array of structs in C

I am trying to learn about structs, pointers, and dynamic arrays in C. I don't understand how to create a dynamic array of structs using pointers. My code doesn't work, and I don't know what's wrong with it. I have seen several examples of dynamic arrays, but non with structs. Any help would be appreciated. Please give some explanation, not just code snippets as I do want to understand not just solve this problem.
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
struct *struct_array;
int i,m,n,p;
struct data
{
char inputA[20];
char inputB[20];
};
struct data get_data()
{
struct data thisdata;
printf("Please enter input A\n");
scanf("%s", thisdata.inputA);
printf("Please enter input B\n");
scanf("%s", thisdata.inputB);
return thisdata;
}
void Output(struct data struct_array, int n)
{
int index = 0;
for(i = 0; i<n ;i++)
{
printf("%s ", struct_array[i].inputA);
printf("%s ", struct_array[i].inputB);
}
}
void resizeArray(int n)
{
struct_array = (int*)realloc(n*sizeof(int));
}
void mainMenu()
{
printf("Please select from the following options:\n");
printf("1: Add new students to database\n");
printf("2: Display current student database contents\n");
printf("3: exit the program\n");
scanf("%d", &p);
if(p == 1)
{
printf("Please enter the number of students to register:\n");
scanf("%d", &n);
resizeArray(n);
for(i = n; i<n ;i++)
{
struct_array[i] = get_data();
}
}
else if(p == 2)
{
Output(struct_array, n);
}
else
{
free(struct_array);
exit(0);
}
}
int main()
{
struct_array = (int*)realloc(2*sizeof(int));
mainMenu();
}
You have several errors in your source code:
struct *struct_array; (l. 5)
What does it mean? Did you want to write struct data *struct_array?
printf("%s ", struct_array[i].inputA); (l.32 & l. 33)
The argument struct_array masks the global declaration, and it is not an array. Why did you add this argument?
struct_array = (int *)realloc(n * sizeof(int)); (l. 39)
You have forgotten an argument. Did you want to use malloc instead? Besides, the cast is not necessary (and incorrect!).
Unless you are using an hosted environnment and C99/C11, you should return a value from main.
Your variable index is not used. Why did you declare it?
for(i = n; i < n; i++) (l. 53)
You won't have any iteration here...
The following code works as expected.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* TODO: Avoid global variables. */
struct data *struct_array;
struct data {
char inputA[20];
char inputB[20];
};
/*
* TODO: Try to avoid passing your structure (40 bytes + padding)
* without pointer.
*/
struct data get_data(void)
{
struct data thisdata;
printf("Please enter input A\n");
/* TODO: Avoid using `scanf` for human inputs. */
scanf("%s", thisdata.inputA);
printf("Please enter input B\n");
scanf("%s", thisdata.inputB);
return thisdata;
}
void Output(size_t n)
{
size_t i;
for (i = 0; i < n; i++) {
printf("%s ", struct_array[i].inputA);
printf("%s ", struct_array[i].inputB);
}
}
void resizeArray(size_t n)
{
/* TODO: Handle reallocations errors. */
struct_array = realloc(struct_array, n * sizeof *struct_array);
}
void mainMenu(void)
{
size_t i, n;
int p;
/* TODO: Use a loop ? */
printf("Please select from the following options:\n");
printf("1: Add new students to database\n");
printf("2: Display current student database contents\n");
printf("3: exit the program\n");
scanf("%d", &p);
switch (p) {
case 1:
printf("Please enter the number of students to register:\n");
scanf("%u", &n);
resizeArray(n);
for (i = 0; i < n; i++)
struct_array[i] = get_data();
break;
case 2:
Output(n);
break;
}
}
int main(void)
{
struct_array = malloc(2 * sizeof(int));
mainMenu();
free(struct_array);
return 0;
}
Your definition
struct *struct_array;
is erroneous. You must use the name of your type, the data.
struct data *struct_array;
This way you can allocate the array
struct_array = malloc(MaxNumElements * sizeof(struct data));
and later you should free the memory
free(struct_array);
EDIT: Type definition must occur before the var declaration.
struct data ....
struct data* your_variable;
P.S. If you do not want to type struct keyword each time you use the data type, use the typedef:
typedef struct data_s
{
char inputA[20];
char inputB[20];
} data;
Do you know how to use typedef?
I would suggest it, makes your code easier to understand and you won't have to be typing the word struct a thousand times. Also you could treat the new type similar to the primitive types (ints, chars, etc), just don't forget to use the dot (.) to access the individual fields you might want.
You could type for instance:
typedef struct{
char inputA[20];
char inputB[20];
} data;
Now you could declare variables like this:
data data_variable;
data *pointer_to_data;
And to you could allocate memory as follows:
pointer_to_data = (data*) malloc(sizeof(data)* N);
where N is the amount of struct data you want to allocate. Same works for realloc.
struct_array = (int*)realloc(2*sizeof(int));
By the above statement you are trying to assign address of an int to a pointer of type struct data.
You need to use:
struct_array = (struct data*)realloc(2*sizeof(struct data));

Resources