Searching for a string in a struct - c

The code below is a code that will track my product costs and remaining quantity.The problem I'm facing with is I can't search the code by
if(g[n].name == search[10])
The out put keep showing
"Item not found"
Im a beginner of c language and was hope to learn more. Please correct my code and send it here so that I can know why my code is wrong.
#include <stdio.h>
struct product
{
char name[10];
int quantity;
float costs;
};
void fn_search (struct product g[]);
int main ()
{
int n;
struct product g[4];
strcpy(g[0].name,"aa1");
g[0].quantity = 10;
g[0].costs = 1;
strcpy(g[1].name,"bb2");
g[1].quantity = 10;
g[1].costs = 2;
strcpy(g[2].name,"bb3");
g[2].quantity = 10;
g[2].costs = 3;
fn_search (g);
}
void fn_search (struct product g[10])
{
int n;
char search[10];
printf("Search>> ");
scanf("%s",&search[10]);
for (n=0;n<4;n++)
{
if(g[n].name == search[10])
{
printf ("\ncosts = NTD%.2f",g[n].costs);
printf ("\nquantity = %d\n",g[n].quantity);
}
else
{
printf("\nItem not found.");
break;
}
}
}

Two bugs:
Incorrect use of scanf :
scanf("%s",&search[10]); --> scanf("%9s", search);
Note: scanf("%9s", &search[0]); is also fine but the above is the common way.
Incorrect string compare :
if(g[n].name == search[10]) --> if(strcmp(g[n].name, search) == 0)
Also notice that you never initialized g[3] but fn_search checks it.
Then this part:
else
{
printf("\nItem not found.");
break;
}
means that you break the for loop as soon as an item doesn't match. In other words: Currently you only compare against g[0]
You don't want that! Check all items before printing "Item not found".
So the for loop should be more like:
for (n=0;n<4;n++)
{
if(strcmp(g[n].name, search) == 0)
{
printf ("\ncosts = NTD%.2f",g[n].costs);
printf ("\nquantity = %d\n",g[n].quantity);
return; // Exit function when match is found
}
}
// When execution arrives here, there was no matching element
printf("\nItem not found.");
Finally:
void fn_search (struct product g[10])
^^
why ??
Either do
void fn_search (struct product g[])
or
void fn_search (struct product *g)

Related

String in structure gets deleted

I'm working on the last exercise of the "Think like a computer scientist, C version" book and I have some trouble with one particular point.
The exercise consists of making a small game, where the computer picks a random value between 0 and 20 and then asks me to guess the number.
After that, the computer counts the number of tries I made and, if I get a better score than the previous party, I need to store my name and the number of tries in a structure.
My problem is the following: When I restart the game, the string value, player_name, in the structure gets somehow deleted but player_score is still there.
First, I made a "call by value" function to create the structure and then a tried with a "call by reference" but getting the same results.
I think I tried everything I could with my actual knowledge for now; so, if someone could check my code and give me some tips about what's wrong I would much appreciate it!
//HEADERS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define FALSE 0
#define TRUE 1
//TYPEDEF STRUCTS
typedef struct
{
int player_score;
char *player_name;
} HS_Player;
//FUNCTION PROTOTYPES
int Random_Value(void);
int Get_User_Choice(void);
int Check_Result(int computer, int my_choice);
int Try_Again(int game_result, int computer);
void Player_Infos(HS_Player *player_p, int score);
int Game_Restart(void);
//MAIN
int main(void)
{
int end_game;
int high_score_value = 100;
HS_Player player;
while (end_game != TRUE)
{
int computer_number = Random_Value();
printf("Guess the number between 0 et 20 chosen by the computer.\n");
int your_number = Get_User_Choice();
int result_game = Check_Result(computer_number, your_number);
int tries_to_win = Try_Again(result_game, computer_number);
printf("Number of tries: %i\n", tries_to_win);
if (tries_to_win < high_score_value)
{
Player_Infos(&player, tries_to_win );
high_score_value = player.player_score;
}
printf("Highest score: %i By: %s\n", player.player_score, player.player_name);
printf("\n");
end_game = Game_Restart();
}
return EXIT_SUCCESS;
}
//Random_Value FUNCTION
int Random_Value(void)
{
srand(time(NULL));
int x = rand();
int y = x % 20;
return y;
}
//Get_User_Choice FUNCTION
int Get_User_Choice(void)
{
int success, x;
char ch;
printf("Your Guess:\t");
success = scanf("%i", &x);
while (success != 1)
{
printf("Your input is not a number. Please try again:\t");
while ((ch = getchar()) != '\n' && ch != EOF);
success = scanf("%i", &x);
}
if (x < 0 || x > 20)
{
printf("Your input must be between 0 and 20. Please try again.\n");
Get_User_Choice();
}
return x;
}
//Check_Result FUNCTION
int Check_Result(int computer, int my_choice)
{
int check_result;
if (my_choice < computer)
{
printf("Computer number is larger!\n");
check_result = FALSE;
}
else if (my_choice > computer)
{
printf("Computer number is smaller!\n");
check_result = FALSE;
}
else if (my_choice == computer)
{
printf("It's a Match! You chose the same number than the computer.\n");
printf("\n");
check_result = TRUE;
}
return check_result;
}
//Try_Again FUNCTION
int Try_Again(int game_result, int computer)
{
int tries_befor_success = 1;
while (game_result != TRUE)
{
int your_number = Get_User_Choice();
game_result = Check_Result(computer, your_number);
tries_befor_success++;
}
return tries_befor_success;
}
//Player_Infos FUNCTION
void Player_Infos(HS_Player *player_p, int score)
{
char new_name[80];
printf("Congrats! Your made a new high score.\n");
printf("What's your name ?\t");
scanf("%s", new_name);
printf("\n");
player_p->player_score = score;
player_p->player_name = new_name;
}
//Game_Restart FUNCTION
int Game_Restart(void)
{
int quit_value;
printf("Quit Game ?\n");
printf("Press 'y' to quit or any other keys to continue.\n");
fflush(stdin);
char quit_game = getchar();
printf("\n");
if (quit_game == 'y')
{
quit_value = TRUE;
}
else
{
quit_value = FALSE;
}
return quit_value;
}
The problem is that, in your Player_Infos function, you are assigning the address of a local array to the char* player_name pointer member of the passed structure. When that function ends, the local array it used will be deleted and the pointer in the structure will be invalid. (In the case of the player_score, you don't have that problem, because the given value is copied to the structure member.)
There are several ways around this; one would be to use the strdup() function to make a copy of the local char new_name[80]; array – but that is really overkill, and you would need to manage (i.e. free()) that allocated string whenever you make a modification.
A simpler way is to make the player_name member an actual array of char and then use strcpy() to copy the local array into that member.
Better, still, with the player_name member defined as char [80], you can read directly into that (in the function), and avoid the local array completely:
typedef struct
{
int player_score;
char player_name[80];
} HS_Player;
//...
void Player_Infos(HS_Player *player_p, int score)
{
printf("Congrats! Your made a new high score.\n");
printf("What's your name ?\t");
// Read directly. Limit input to 79 chars (allowing room for null terminator).
scanf("%79s", player_p->player_name);
printf("\n");
player_p->player_score = score;
}
Also, just as a "style" tip, you may want to change the member names to just score and name, as the "player" part is implied by the structure type-name itself.
This issue you are having is that you are associating the player name pointer to a variable that goes out of scope when you leave the "player_Infos" function. What you probably would want to do is define the name as a character array in your structure and then use the "strcpy" call in your function instead. Following is a couple of code snippets illustrating that point.
//TYPEDEF STRUCTS
typedef struct
{
int player_score;
char player_name[80];
} HS_Player;
Then, in your function, use the "strcpy" call.
//Player_Infos FUNCTION
void Player_Infos(HS_Player *player_p, int score)
{
char new_name[80];
printf("Congrats! Your made a new high score.\n");
printf("What's your name ?\t");
scanf("%s", new_name);
printf("\n");
player_p->player_score = score;
strcpy(player_p->player_name, new_name);
//player_p->player_name = new_name;
}
When I tested that out, I got a name to appear in the terminal output.
Computer number is smaller!
Your Guess: 4
It's a Match! You chose the same number than the computer.
Number of tries: 8
Highest score: 4 By: Craig
FYI, you will need to include the "string.h" file.
Give that a try.
Name Update
The reason your player.player_name is not getting updated is because you can't assign a string this way in C. When doing player_p->player_name = new_name; you're actually saving in player_p->player_name the memory address of new_name.
Instead, what you want to achieve, is to copy each character of new_name to player_p->player_name and in order to achieve this, you have to change the type of prlayer_name field from char* player_name to char player_name[80], then assign it using, for example, strcpy():
#include <string.h>
// [...]
//TYPEDEF STRUCTS
typedef struct
{
unsigned int player_score;
char player_name[80];
} HS_Player;
// [...]
//Player_Infos FUNCTION
void Player_Infos(HS_Player *player_p, int score)
{
char new_name[80];
printf("Congrats! Your made a new high score.\n");
printf("What's your name ?\t");
scanf("%s", new_name);
printf("\n");
player_p->player_score = score;
strcpy(player_p->player_name, new_name);
}
Data Persistence
To make data (players info) persistent over multiple runs, you have to save the content of the struct to a file.
Example
int Save_Score(char* filename, HS_Player* player)
{
FILE* file = fopen(filename, "w");
if (file == NULL)
{
fprintf(stderr, "\nAn error occurred while opening the file\n");
return -1;
}
if (fprintf(file, "%d %s", player->player_score, player->player_name) < 0)
return -1;
fclose(file);
return 0;
}
int Load_Score(char* filename, HS_Player* player)
{
FILE* file = fopen(filename, "r");
if (file == NULL)
{
fprintf(stderr, "\nAn error occurred while opening the file\n");
return -1;
}
if (fscanf(file, "%d %79s", &player->player_score, player->player_name) < 0)
return -1;
fclose(file);
return 0;
}

Using Struct in C to create a library for items and giving location feedback based upon user entry. I just cant seem to find my error

//make a location marker for key items
#include <stdio.h>
#include <string.h>
struct find {int index; char name[50]; char location[50]; };
int main() {
char locate_item[50];
//using struct to add items
struct find item1;
item1.index = 1;
strcpy(item1.name, "guitar");
strcpy(item1.location, "Usually near the table in the living room area.\n");
struct find item2;
item2.index = 2;
strcpy(item2.name, "ipad");
strcpy(item2.location, "Usually on the table or charging on the bed.\n");
//using while and if statements to get user feedback and display the appropriate location
while (locate_item != item1.name || locate_item != item2.name) {
printf("what is the item you want to find? \n");
scanf("%s", locate_item);
printf("You entered %s\n", locate_item);
if (locate_item == item1.name) {
printf("%s", item1.location);
} else if (locate_item == item2.name) {
printf("%s", item2.location);
} else {
printf("Incorrect entry. Please try again.\n");
}
}
return 0;
}
locate_item != item1.name || locate_item != item2.name compares pointer, however, you want to use strcmp() to compare two strings by value. strcmp() returns 0 if the two strings are the same.
In either case, your program doesn't make a lot of sense. You probably want to find locate_item in the an array of items (renamed from find) along these lines:
#include <stdio.h>
#include <string.h>
struct item {
int index;
char name[50];
char location[50];
};
int main() {
struct item items[] = {
{ 1, "guitar", "Usually near the table in the living room area." },
{ 2, "ipad", "Usually on the table or charging on the bed." },
{ 0 }
};
for(;;) {
printf("what is the item you want to find? \n");
char locate_item[50];
scanf("%s", locate_item);
//printf("You entered %s\n", locate_item);
for(int i = 0; items[i].name[0]; i++) {
if(!strcmp(items[i].name, locate_item)) {
printf("%s\n", items[i].location);
goto done;
}
}
printf("Incorrect entry. Please try again.\n");
}
done:
return 0;
}

Function casts itself c, after it has been casted twice

I've got a university project where I have to write a database of workers. I decided to use dynamic array of structures:
struct data
{
char id[50];
char name[50];
char surname[50];
char account_num[50];
double net_pension,taxed_pension;
};
int main()
{
int current_size=0;
struct data *database;//creating a table
database=(struct data*)malloc(1*sizeof(struct data));//memory allocation
menu(database);//running menu
return 0;
}
function menu
void menu(struct data *database)
{
int current_size=1;
int input=0;
char inpt[512];
do
{
printf("Input function or input help for list of avaible commands \n");
fgets(inpt,511,stdin);
input=mod_input(inpt);
if(input==404)
{
printf("Function does not exist \n");
}
else if(input==1)
{
print_result(database,current_size);
}
else if(input==2)
{
add_element(database,&current_size);
}
else if(input==3)
{
modify_element(database,current_size);
}
else if(input==4)
{
sort_table(database, current_size);
}
else if(input==5)
{
search(database,current_size);
}
else if(input==6)
{
hilfe();
}
else if(input==7)
{
search_by_col(database,current_size);
}
input=8;
}
while(input!=0);
}
decides what we want to do, for example writing "add" will start my problematic function, which is supposed to add new records
void add_element(struct data *database,int *size)
{
int subflag=0;
char inpt[50];
int place=((*size)-1);
int pass=(*size);
printf("%i",pass);
if((*size)!=1)
{
modify_element(database,(*size));
}
do
{
printf("Input unical ID \n");
fgets(inpt,50,stdin);
if(does_exist(inpt,database,pass)==1)
{
subflag=1;
strncpy(database[place].id,inpt,50);
}
else
{
printf("ID exists");
}
}
while(subflag==0);
subflag=0;
do
{
printf("Input name \n");
fgets(inpt,50,stdin);
if(is_word(inpt)==1)
{
subflag=1;
strcpy(database[place].name,inpt);
}
}
while(subflag==0);
subflag=0;
do
{
printf("Input surname \n");
fgets(inpt,50,stdin);
if(is_word(inpt)==1)
{
subflag=1;
strcpy(database[place].surname,inpt);
}
}
while(subflag==0);
subflag=0;
do
{
printf("Input account number \n");
fgets(inpt,50,stdin);
if(is_accnum(inpt)==1)
{
subflag=1;
strcpy(database[place].account_num,inpt);
}
}
while(subflag==0);
subflag=0;
do
{
printf("Input net gain \n");
fgets(inpt,50,stdin);
if(is_num(inpt)==true)
{
printf("%d",atof(inpt));
subflag=1;
database[place].net_pension=atof(inpt);
}
}
while(subflag==0);
subflag=0;
do
{
printf("Input taxed gain \n");
fgets(inpt,50,stdin);
if(is_num(inpt)==true)
{
subflag=1;
database[place].taxed_pension=atof(inpt);
}
}
while(subflag==0);
printf("record added \n");
if((*size)==1)
(*size)++;
}
function modify_size reallocs memory, does_exist ensures, that id's are unique, is acc_num, num and word checks input for given rules. They all work perfectly when you use function first time. But after you try to add second one "record added" does not display and function add runs from the beginning. I ahve no idea why. That is the main problem. Secondary one is menu, because when you input "print" it runs add_element. Code that converts input is:
int mod_input(char function[])
{
printf(function);
if(strcmp(function,"modify")==1)
return 3;
else if(strcmp(function,"sort")==1)
return 4;
else if(strcmp(function,"search")==1)
return 5;
else if(strcmp(function,"help")==1)
return 6;
else if(strcmp(function,"add")==1)
return 2;
else if(strcmp(function,"print")==1)
return 1;
else if(strcmp(function,"search_by_column")==1)
return 7;
return 404;
}
Thank you in advance for help. Also I know that some parts could be done better, but for now, I try to just force it to work.
whole programme
lab3.c and header
Intuitively, what you need to do is pass around a pointer to a pointer to your array, not just a pointer to it. And that's what BLUEPIXY was trying to get at in a comment.
The problem is that if you do x = realloc(y, new_size), there's no guarantee that x will be equal to y.
In particular, database = realloc(database, new_size) inside a subroutine may leave the subroutine with a different value for database than the one passed in as an argument. The caller still has the old value for database.
The results are undefined, and may include worse than what you got.
What you want is something like
struct data *datap;
struct data **database = &datap;
*database = malloc(sizeof(struct data))
With corresponding changes all the way down - basically pass database, and set *database = realloc(...) when you get to that stage.
Also, make sure you update *size appropriately at the same time.

Program printing Windows paths?

I can't figure out why my program is outputting seemingly random Windows paths as shown below.
\maven, : ORS=4 (id: 4677968)
m32\cmd.exe, ò: Æ (id: 5525087)
, : (id: 4653392)
It does this when looping through an array of structures I have and displaying the values inside. Funny thing is though that it works perfectly. If I add 5 entries, it still displays all of them accurately. Yet it prints the random paths shown above before everything else.
I'm going to attach the whole program because I honestly don't know where to narrow the problem down to. I'm new to C and especially new to manually handling memory. So that may be where the problem lies. Thanks ahead of time.
The program:
#include<stdio.h>
#include<string.h>
// Define structures
typedef struct Contact
{
int id;
char fname[24];
char lname[24];
char number[16];
} Contact;
typedef struct Phonebook
{
Contact* contacts;
int contacts_length;
int id_tracking;
} Phonebook;
// Define prototypes
Phonebook addContact(Phonebook);
Phonebook removeContact(Phonebook); // removeContact() prompts the user for information about whom they want to remove.
void viewContacts(Phonebook);
void exportContacts(Phonebook);
Contact findEntry(int, Phonebook);
Phonebook removeEntry(int, Phonebook); // removeEntry() can be called to explicitly remove the entry with the passed in integer id.
int main()
{
// Define variables
int menuChoice = 0, status = 1;
Phonebook phonebook;
phonebook.contacts = (Contact*) malloc(sizeof(Contact));
// Check memory allocation
if(phonebook.contacts == NULL)
{
printf("\nFatal error: Out of memory... now exiting.");
return;
}
// Handle the user
do
{
// Begin collecting and assigning data
printf("\nContact Menu\n");
printf("\n(1.) Add contact");
printf("\n(2.) Remove contact");
printf("\n(3.) View contacts");
printf("\n(4.) Export contacts");
printf("\n(5.) Exit");
printf("\n\nPlease choose a menu option (enter the number): ");
scanf("%d", &menuChoice);
// Interpret menu choice
switch(menuChoice)
{
case 1:
// Begin adding contact
phonebook = addContact(phonebook);
status = 1;
break;
case 2:
phonebook = removeContact(phonebook);
status = 1;
break;
case 3:
viewContacts(phonebook);
status = 1;
break;
case 4:
exportContacts(phonebook);
status = 1;
break;
case 5:
// Free memory
free(phonebook.contacts);
// See ya!
printf("\nGoodbye!");
status = 0;
break;
default:
printf("I'm sorry, I didn't quite understand that. Please try again.");
status = 1;
break;
}
}
while(status != 0);
// Return 0 for exit
return 0;
}
Phonebook addContact(Phonebook phonebook)
{
// Clear screen first
system("cls");
// Define contact and set random id
Contact entry;
entry.id = phonebook.id_tracking;
phonebook.id_tracking++;
// Obtain information
printf("First name (24 characters max): ");
scanf("%s", &entry.fname);
printf("Last name (24 characters max): ");
scanf("%s", &entry.lname);
printf("Telephone number (recommended format: ###-###-####): ");
scanf("%s", &entry.number);
// Handle memory allocation
if(phonebook.contacts_length > 1)
{
phonebook.contacts = (Contact*) realloc(phonebook.contacts, sizeof(Contact) * (phonebook.contacts_length + 1));
}
// Save the contact to the array and count up
phonebook.contacts[phonebook.contacts_length] = entry;
phonebook.contacts_length++;
printf("Contact saved!\n");
return phonebook;
}
Phonebook removeContact(Phonebook phonebook)
{
// First check to make sure they have saved contacts
if(phonebook.contacts_length < 1)
{
// No contacts saved, tell them
printf("\nYou haven't saved any contacts.\n");
return;
}
// Define variables
int i, chosenId = 0;
// Display contacts with their ids
for(i = 0; i < phonebook.contacts_length; i++)
{
Contact entry = phonebook.contacts[i];
printf("\n%s, %s (id: %d)", entry.lname, entry.fname, entry.id);
}
// Handle removal
printf("\n\nPlease enter the ID of the contact you would like to remove: ");
scanf("%d", &chosenId);
// Remove
Phonebook updatedPhonebook = removeEntry(chosenId, phonebook);
printf("Contact removed!\n");
return updatedPhonebook;
}
void viewContacts(Phonebook phonebook)
{
// First check to make sure they have saved contacts
if(phonebook.contacts_length < 1)
{
// No contacts saved, tell them
printf("\nYou haven't saved any contacts.\n");
return;
}
// Define variables
int i;
// Display contacts with their ids
for(i = 0; i < phonebook.contacts_length; i++)
{
Contact entry = phonebook.contacts[i];
printf("\n%s, %s: %s (id: %d)", entry.lname, entry.fname, entry.number, entry.id);
}
printf("\n");
return;
}
/*
* Experimenting with I/O in C
*/
void exportContacts(Phonebook phonebook)
{
// First check to make sure they have saved contacts
if(phonebook.contacts_length < 1)
{
// No contacts saved, tell them
printf("\nYou have no contacts to be exported.\n");
return;
}
// Define and initialize variables
int i;
char outputName[] = "contacts.txt";
FILE *contactFile = fopen(outputName, "w");
// Print message
printf("\nExporting contacts to .txt file... ");
// Print to the file
for(i = 0; i < phonebook.contacts_length; i++)
{
Contact entry = phonebook.contacts[i];
fprintf(contactFile, "%s, %s (id: %d): %s\n", entry.lname, entry.fname, entry.id, entry.number);
}
// Close the file
fclose(contactFile);
// Done
printf("Done!");
printf("\nData exported to contacts.txt located where this program was launched.");
}
Contact findEntry(int id, Phonebook phonebook)
{
int i;
for(i = 0; i < phonebook.contacts_length; i++)
{
Contact entry = phonebook.contacts[i];
if(entry.id == id)
{
return entry;
}
}
}
Phonebook removeEntry(int id, Phonebook phonebook)
{
// Define variables
int i, positionToFree;
// Search for the index of the entry to remove
for(i = 0; i < phonebook.contacts_length; i++)
{
Contact entry = phonebook.contacts[i];
if(entry.id == id)
{
positionToFree = i; // This is the position to be freed
}
// We've found what we need, break now
break;
}
// Loop starting at that entry and remove
for(i = positionToFree; i < phonebook.contacts_length; i++)
{
Contact temp = phonebook.contacts[i + 1];
phonebook.contacts[i] = temp;
}
// Count down for contacts_length
phonebook.contacts_length--;
// Return the updated contacts
return phonebook;
}
This sounds like undefined behaviour.
You never initialise phonebook.contacts_length. It could have any value. When you go to add an entry, it's quite possible that the realloc call fails. You don't check the return value, so you wouldn't know.
Bad juju.

How to approach and optimize code in C

I am new to C and very much interested in knowing how to approach any problem which has more than 3 or 4 functions, I always look at the output required and manipulate my code calling functions inside other functions and getting the required output.
Below is my logic for finding a students record through his Id first & then Username.
This code according to my professor has an excessive logic and is lacking in many ways, if someone could assist me in how should I approach any problem in C or in any other language it would be of great help for me as a beginner and yes I do write pseudo code first.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int id; //Assuming student id to be unique
int age;
char *userName; //Assuming student userName to be unique
char *dept;
}student; // Alias "student" created for struct
student* createstruct(); // All function prototype declared
student* createArray();
void addstruct(student* s2);
void searchChar(student* s2,int num);
void searchInt(student* s2,int num);
student* createstruct() // function createStruct() to malloc data of struct student.
{
student *s;
s = (student*)malloc(sizeof(student));
s->userName = (char*)malloc(sizeof(char)*32);
s->dept = (char*)malloc(sizeof(char)*32);
printf("please enter id ");
scanf("%d",&s->id);
printf("please enter age ");
scanf("%d",&s->age);
printf("please enter userName ");
scanf("%31s",s->userName);
printf("please enter department ");
scanf("%31s",s->dept);
printf("\n");
return s;
}
student* createArray()
{
student *arr; //declaration of arr poiter, type struct student
arr = (student*)malloc(sizeof(student)*10); // memory allocated for a size of 10
return arr;
}
void addstruct(student *s2) // function for adding data to the structures in array
{
int i,num;
student* s1;
printf("please enter the number of records to add:");
scanf("%d",&num);
printf("\n");
if(num>0 && num<11)
{
for(i=0;i<num;i++) // if user want to enter 5 records loop will only run 5 times
{
s1 = createstruct();
s2[i].id = s1->id; // traversing each element of array and filling in struct data
s2[i].age = s1->age;
s2[i].userName = s1->userName;
s2[i].dept= s1->dept;
}
}
else if(num>10) // if user enters more than 10
{
for(i=0;i<10;i++) // loop will still run only 10 times
{
s1 = createstruct();
s2[i].id = s1->id;
s2[i].age = s1->age;
s2[i].userName = s1->userName;
s2[i].dept = s1->dept;
}
printf("Array is full"); // Array is full after taking 10 records
printf("\n");
}
searchInt(s2,num); // Calling searchInt() function to search for an integer in records
searchChar(s2,num); // Calling searchChar() function to search for a string in records
free(s1);
free(s2);
}
void searchChar(student* s2,int num) // function for searching a string in records of structure
{
char *c;
int i;
c = (char*)malloc(sizeof(char)*32);
printf("please enter userName to search ");
scanf("%31s",c);
printf("\n");
for (i=0;i<num;i++) //num is the number of struct records entered by user
{
if ((strcmp(s2[i].userName,c)==0)) //using strcmp for comparing strings
{
printf("struct variables are %d, %d, %s, %s\n", s2[i].id,s2[i].age,s2[i].userName,s2[i].dept);
break;
}
else if(i == num-1)
{
printf("nothing in userName matches: <%s>\n",c);
break;
}
}
}
void searchInt(student* s2,int num) //searchs for an integer and prints the entire structure
{
int i,z;
printf("please enter id to search ");
scanf("%d",&z);
printf("\n");
for (i=0;i<num;i++)
{
if (s2[i].id == z)
{
printf("struct variables are %d, %d, %s, %s\n\n", s2[i].id,s2[i].age,s2[i].userName,s2[i].dept);
break;
}
else if(i == num-1)
{
printf("nothing in id matches: <%d>\n\n",z);
break;
}
}
}
int main(void)
{
student *s2;
s2 = createArray();
addstruct(s2);
return 0;
}
I'm not going to go into optimizing, because if you wanted better theoretical performance you would probably go with different data structures, such as ordered arrays/lists, trees, hash tables or some kind of indexing... None of that is relevant in this case, because you have a simple program dealing with a small amount of data.
But I am going to tell you about the "excessive logic" your professor mentioned, taking your searchInt function as an example:
for (i=0;i<num;i++)
{
if (s2[i].id == z)
{
printf("struct variables are %d, %d, %s, %s\n\n", s2[i].id,s2[i].age,s2[i].userName,s2[i].dept);
break;
}
else if(i == num-1)
{
printf("nothing in id matches: <%d>\n\n",z);
break;
}
}
The thing here is that every time around the loop you're testing to see if you're at the last element in the loop. But the loop already does that. So you're doing it twice, and to make it worse, you're doing a subtraction (which may or may not be optimized into a register by the compiler).
What you would normally do is something like this:
int i;
student *s = NULL;
for( i = 0; i < num; i++ )
{
if( s2[i].id == z ) {
s = &s2[i];
break;
}
}
if( s != NULL ) {
printf( "struct variables are %d, %d, %s, %s\n\n",
s->id, s->age, s->userName, s->dept );
} else {
printf("nothing in id matches: <%d>\n\n",z);
}
See that you only need to have some way of knowing that the loop found something. You wait for the loop to finish before you test whether it found something.
In this case I used a pointer to indicate success, because I could then use the pointer to access the relevant record without having to index back into the array and clutter the code. You won't always use pointers.
Sometimes you set a flag, sometimes you store the array index, sometimes you just return from the function (and if the loop falls through you know it didn't find anything).
Programming is about making sensible choices for the problem you are solving. Only optimize when you need to, don't over-complicate a problem, and always try to write code that is easy to read/understand.

Resources