Assigning point to customer C programming - c

I would like to get assistance in my coding. I created a customer loyalty system using C (using file) and now I need to assign some called points to my customer, but what happenned is it will not assign any points to them.
{
for (int i = 0; i < (count / 3); i++)
{
fscanf(reward_file, "%s\n%s\n%d\n", user[i].Username, user[i].Password, &user[i].Points);
if (Point = user[i].Points)
{
strcpy(user[i].Points, Reward);
Point = Point + Reward;
printf("%d", Point);
system("pause");;
}
}
fclose(reward_file);
FILE *new_file = fopen("CustomerRegistration.txt", "w");
for (int i = 0; i < NumOfCust; i++)
{
fprintf(new_file, "%s\n%s\n%d\n", user[i].Username, user[i].Password, user[i].Points);
}
fclose(new_file);
printf("You Have Successfully Added Your Point!!!\n");
printf("You Will be Redirected Back to Customer Privilege Menu");
system("TIMEOUT \t 5");
}
I am using struct for my customer and here is the code
struct USER
{
char Username[255];
char Password[255];
int Points;
};
struct USER user[100];
Data is obtained from a function called "Login"
FILE *LOGINFILE = fopen("CustomerRegistration.txt", "r");
if (LOGINFILE)
{
system("cls");
printf("!!!Hello Customer!!!\n");
printf("Please type in your Username and Password\n");
printf("Username\t: ");
//while ((c = getchar()) !='\n');
gets(UN);
printf("Password\t: ");
gets(Pswd);
I also assigned global variable called "Point"
int Point = 0;
Your help will be highly appreciated.

From what I am understanding from your posted code you want to add a Reward to the Customer Points.
Firstly you just need to add to user.Points the Reward, using strcpy makes no sense because that function is used for copying strings.
that if( Point = user[i].Points ) also makes no sense firstly because C equality condition is represented by a double equal sign ( "==" ) and you don't need to make that check.
The .Points member is an int and Reward is also an int ,so you can do arithmethic operations and there is no need to use another Point auxiliar.
for (int i = 0; i < (count / 3); i++)
{
fscanf(reward_file, "%s\n%s\n%d\n", user[i].Username, user[i].Password, &user[i].Points);
user[i].Points += Reward;
printf("%d", user[i].Points);
system("pause");;
}
.....

the first loop:
for (int i = 0; i < (count / 3); i++)
the second loop
for (int i = 0; i < NumOfCust; i++)
if NumOfCust is greater than (count/3)) you'll get unitialized values on CustomerRegistration.txt. I can't see the values of those variables, but make sure it doesn't happen. The best would be to use the last value of i in the first loop to the stop condition for the second loop.

Related

How can I arrange the structs in an array of structs in an ascending order?

I am sorry if this sounds confusing, I will try to be as clear as possible. I have an array of structs, where the array stores a struct that I have defined as a Business Card. However, before adding any new business cards into the array, I have to store the structs in ascending order based on the integer value of the Employee ID.
Here is the struct:
typedef struct{
int nameCardID;
char personName[20];
char companyName[20];
} NameCard;
Hence, I tried to use relational operators to compare between the values of the ID and copy it in ascending order to another temporary array I named fakeHolder, before finally copying over to the actual array. However, I can't seem to understand why it is not in order after inputting my data as ID 9, 7, 5.
Here is my helper function:
int addNameCard(NameCard *nc, int *size){
int i = 0;
// Why is this a pointer?
NameCard fakeHolder[10];
char dummy[100];
char *p;
printf("addNameCard():\n");
if(*size == MAX){
printf("The name card holder is full");
// To quit the program
return 0;
}
// Keeps it to Fake Name Card Holder First
printf("Enter nameCardID:\n");
scanf("%d", &fakeHolder->nameCardID);
scanf("%c", &dummy);
printf("Enter personName:\n");
fgets(fakeHolder->personName, 20, stdin);
if(p = strchr(fakeHolder->personName, '\n')){
*p = '\0';
}
printf("Enter companyName:\n");
fgets(fakeHolder->companyName, 20, stdin);
if(p = strchr(fakeHolder->companyName, '\n')){
*p = '\0';
}
// Compare the ID value
for(int j = 0; j < *size; j += 1){
if(fakeHolder->nameCardID == (nc+j)->nameCardID){
printf("The nameCardID has already existed");
}
else if(fakeHolder->nameCardID < (nc+j)->nameCardID){
fakeHolder[(j+1)].nameCardID = (nc+j)->nameCardID;
strcpy(fakeHolder[(j+1)].personName,(nc+j)->personName);
strcpy(fakeHolder[(j+1)].companyName, (nc+j)->companyName);
}
}
*size += 1;
// Transfer to the Actual Name Card Holder
for(int k = 0; k < *size; k += 1){
(nc+k)->nameCardID = fakeHolder[k].nameCardID;
strcpy((nc+k)->personName, fakeHolder[k].personName);
strcpy((nc+k)->companyName, fakeHolder[k].companyName);
}
printf("The name card has been added successfully\n");
return 0;
}
Your current code has several problems, and you can rewrite it to be much more maintainable and easier to work with. For example,
i (in int i = 0;) is not being used
scanf("%c", &dummy); is there, I assume, to remove trailing \n - but a 100-char buffer for a single character to read is... surprising. See scanf() leaves the new line char in the buffer for lots of discussion on different approaches to "trailing stuff after integer".
splitting addNameCard into 2 functions, one to actually request a NameCard and another to insert it into the array, would divide up responsibilities better, and make your program easier to test. Avoid mixing input/output with program logic.
The question you ask can be solved via the standard library qsort function, as follows:
#include <stdlib.h>
typedef struct{
int nameCardID;
char personName[20];
char companyName[20];
} NameCard;
void show(NameCard *nc, int n) {
for (int i=0; i<n; i++, nc++) {
printf("%d,%s,%s\n",
nc->nameCardID, nc->personName, nc->companyName);
}
}
// comparison functions to qsort must return int and receive 2 const void * pointers
// they must then return 0 for equal, or <0 / >0 for lower/greater
int compareCardsById(const void *a, const void *b) {
return ((NameCard *)a)->nameCardID - ((NameCard *)b)->nameCardID;
}
int main() {
NameCard nc[10];
nc[0] = (NameCard){1, "bill", "foo"};
nc[1] = (NameCard){3, "joe", "bar"};
nc[2] = (NameCard){2, "ben", "qux"};
show(nc, 3);
// calling the libraries' sort on the array; see "man qsort" for details
qsort(nc, 3, sizeof(NameCard), compareCardsById);
show(nc, 3);
return 0;
}

Everytime I declare I function, my variable made by the function changes. C Language

so I am working on my Binary adding program, but now I am stuck. I want to declare 2 variables for the first binary and second one, so I use the getBinary function I created to declare these 2. However, after I entered value for firstBin, I got the value I want, but after I entered the value for secBin, the value of firstBin somehow changes and become the same as secondBin. I was hoping for the variable to be unchangable. Thanks for the help
#include <stdio.h>
int * getBinary(){
int i;
int j;
static int first8bits[8];
for (i = 0; i != 8; i++){
printf("Input 8-bits Binary:");
scanf("%d",&first8bits[i]);
}
for (j = 0; j != 8; j++)
printf("%d",first8bits[j]);
printf("\n");
return first8bits;
}
int main(){
int o;
printf("Input the first Set of Binary...");
const int * firstBin = getBinary();
printf("Input the second Set of Binary...");
int * secBin = getBinary();
for (o = 0; o != 8; o++)
printf("%d",firstBin[o]);
}
Because of the static keyword.
Don't use static. Try:
int* first8bits = malloc(8 * sizeof(int));
This way you will allocate new memory each time you call it. You can still access it with the same [ i ] subscript. Remember to free the memory again at the end of main!
free(firstBin);
free(secBin);

Sorting Words and Numbers from a file in C

I have been tasked with writing a function that takes a string reference and an integer reference parameter. The function must scan a .txt file and set the reference parameters to the name of the player with the highest score and the corresponding score.
This is written in the scores.txt file I must reference:
Ronaldo
10400
Didier
9800
Pele
12300
kaka
8400
Cristiano
8000
I currently have this much coding wrote however I am stuck as to how I am suppose to match the names up with the score since they have to be in no particular order. Within my coding I sort the numbers from greatest to least but I am not sure if this is needed or not.
FILE *input;
char name[name_len];
double score[score_len];
int a;
int b;
double placeholder;
input = fopen("scores.txt", "r");
if (input == NULL)
{
printf("\n Cannot open scores.txt for input\n");
}
for (a =0; a < 5; ++a)
fscanf(input, "%s%lf", name, score);
for (a = 0; a < 5; ++a) /* Repeats the step until three numbers are sorted*/
{
for (b = a + 1; b < 5; ++b) /* Repeats until the last two numbers are sorted*/
{
if (score[a] < score[b]) /* Sorts the 3 numbers using a placeholder to exchange the numbers in the array*/
{
placeholder = score[a];
score[a] = score[b];
score[b] = placeholder;
}
}
}
fclose(input);
return 0;
Any help regarding the solution or how I can move forward is much appreciated.
You can just read the number and name in, and replace the value of the score and the name if its bigger.
char name[name_len];
double score[score_len];
char highScoreName[name_len];
double highScore = 0;
...
for (int a = 0; a < 5; ++a)
{
fscanf(input, "%s %lf", name, score[a]);
if (highScore < score[a])
{
highScore = score[a];
strcpy(highScoreName, name);
}
}

Navigating 2D arrays by category?

Once again, I'd like to thank everyone for their prompt responses to my previous Gradebook question. I am now further along in the project, and have hit a (in my opinion) thornier problem.
The instructions call for me to create a function with this prototype:
int set_assignment_score(Gradebook *gb, char name[MAX_NAME_LEN], char a_name[], int score);
Once again, it will enter the Gradebook structure through the *gb pointer, but this time, it is meant to access the Scores array:
int scores[MAX_NUMBER_OF_STUDENTS][MAX_NUMBER_OF_ASSIGNMENTS]
... and deposit the "score" integer inside a specific cell for further use. The two Char parameters are important, because later on I will need to retrieve each specific integer from the Scores array and match it up with its precise name and a_name in a print_gradebook function.
I would love to share what code I have so far, but the fact of the matter is that I barely know where to start. I think that the key, however, is knowing how to navigate an integer array using char name and char a_name in place of the usual [i] and [j].
Any suggestions, advice, mockery, or requests for clarification are welcome. Please.
Here is the Gradebook structure:
typedef struct gradebook {
int number_of_students;
Students students[MAX_NUMBER_OF_STUDENTS];
int number_of_assignments;
char assignment_names[MAX_NUMBER_OF_ASSIGNMENTS][MAX_NAME_LEN + 1];
int scores[MAX_NUMBER_OF_STUDENTS][MAX_NUMBER_OF_ASSIGNMENTS];
} Gradebook;
EDIT: Thanks, everyone! Combining your advice, I came up with this:
int set_assignment_score(Gradebook *gb, const char name[MAX_NAME_LEN], const char a_name[], int score) {
int i, j;
for(i=0; i< MAX_NUMBER_OF_STUDENTS; i++) {
if(strcmp(gb->students[i].name, name) == 0) {
for(j=0; j< MAX_NUMBER_OF_ASSIGNMENTS; j++) {
if(strcmp(gb->assignment_names[j], a_name) == 0) {
gb->scores[i][j] = score;
}
}
}
}
printf("%d\n", gb->scores[i][j]);
return 1;
}
I suspect it's a lot clumsier than it needs to be, but it gets the job done. Funnily enough, the printf function I put in to test it doesn't provide the result I want (I guess I'm printing the address or something?), but the actual function does.
Yes, that's the general idea. The reason the printf doesn't work is because the loops continue running after you've found the matching student name and assignment name. So after the loops are done, you've lost the values of i and j. In fact, after the loops are done, i==MAX_NUMBER_OF_STUDENTS and j==MAX_NUMBER_OF_ASSIGNMENTS.
To keep the values of i and j, you should break from the loop when you find the matching name. (I also added some error checking to handle the case where one or both of the names aren't found.)
int set_assignment_score(Gradebook *gb, const char name[MAX_NAME_LEN], const char a_name[], int score)
{
int i, j;
for(i=0; i< MAX_NUMBER_OF_STUDENTS; i++)
if(strcmp(gb->students[i].name, name) == 0)
break;
for(j=0; j< MAX_NUMBER_OF_ASSIGNMENTS; j++)
if(strcmp(gb->assignment_names[j], a_name) == 0)
break;
if ( i == MAX_NUMBER_OF_STUDENTS || j == MAX_NUMBER_OF_ASSIGNMENTS )
{
printf( "unable to set score (i=%d, j=%d)\n", i, j );
return 0;
}
gb->scores[i][j] = score;
printf("%d\n", gb->scores[i][j]);
return 1;
}

C Comparing 2 strings turned into memory allocation issue

Let me start off by saying, I do realize there are a lot of questions with the exact same title, but I didn't find what I was looking for in any of them. I tried to write the following code, in order to errorcheck the user's input, so he wouldn't give 2 variables the same name. Needless to say, it failed, and that is why I am here. While printing the strings I was comparing out as strings, using printf("%s", temp[j].name); was working fine, the character-by-character printing was outputting a series of characters that, from what I know, shouldn't be there. I would like to know what this could all be about, and if there is anyway to solve it, so I can actually compare the 2, without using something from string.h
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#define ARRAYLENGTH 20
typedef struct{
char name[ARRAYLENGTH];
char type[ARRAYLENGTH];
char value[ARRAYLENGTH];
}variable;
int main(){
int amount = 3;
int i, j, k;
variable * varray;
variable * temp;
int flag;
int added = 1;
varray = malloc(amount*sizeof(variable));
if (varray == NULL){
printf("error");
return 1;
}
temp = malloc(amount*sizeof(variable));
if (temp == NULL){
printf("error");
return 1;
}
printf("Give the name of variable # 1 \n");
scanf("%s", varray[0].name);
for (i = 1; i < amount; i++){
flag = 0;
while (flag == 0){
printf("Give the name of variable # %d \n", i + 1);
scanf("%s", temp[i].name);
for (j = 0; j < added; j++){
for (k = 0; temp[i].name[k] != '\0'; k++){
printf("%c,", temp[i].name[k]);
}
printf("\n");
for (k = 0; temp[i].name[k] != '\0'; k++){
if (varray[j].name[k] != temp[i].name[k]){
flag = 1;
break;
}
if (varray[j].name[k] == temp[i].name[k]){
flag = 0;
}
}
}
if (flag == 0){
printf("The variable name you gave already exists, please choose another one. \n");
}
if (flag == 1){
for (j = 0; j < ARRAYLENGTH; j++){
varray[i].name[j] = temp[i].name[j];
}
}
if(flag == 1){
added +=1;
}
}
}
for (i = 0; i < amount; i++){
printf("%s \n", varray[i].name);
}
free(varray);
free(temp);
}
The code compiles without problem, but when I tried to run it, I found that, no matter what my, as a user, input was, the flag would always be 1 in the end. The block of code
printf("\n");
for (k = 0; k < ARRAYLENGTH; k++){
printf("%c,", temp[i].name[k]);
}
printf("\n");
And when the user input is the name John, outputs the following on Visual Studio 2013's Developer command prompt:
Give the name of variable # 1
John
Give the name of variable # 2
John
J,o,h,n,
The variable name you gave already exists, please choose another one.
Give the name of variable # 2
George
G,e,o,r,g,e,
Give the name of variable # 3
George
G,e,o,r,g,e,
G,e,o,r,g,e,
The variable name you gave already exists, please choose another one.
Give the name of variable # 3
John
J,o,h,n,
J,o,h,n,
John
George
John
What I am guessing this problem is about, is that the memory the system is allocating to temp and varray are already being used elsewhere. This errorcheck is crucial for a project I have to do, so I would appreciate any help I can get in solving this problem greatly. Thanks in advance,
LukeSykpe
The problem is with your printing logic.
The scanf function writes the user input into the array, followed by a terminating `\0' character. It does not know the size of your array (20), so it doesn't touch the part of the array that it doesn't actually write.
Instead of this:
for (k = 0; k < ARRAYLENGTH; k++){
write:
for (k = 0; temp[i].name[k] != '\0'; k++) {
Note that you don't need to check for running off the end of the array here. Instead, make sure that the user string is not too big for your array. See this for how to do that.
Edit : This post is not to answer the original question, but to answer a follow-up question posted in comments. I tried to incorporate this into the previous answer, but the owner refused. So here it is.
The problem with your varray comparisons is that, with the code you are showing at least, varray is never initialized. So
if (varray[j].name[k] != temp[i].name[k])
Is a bit like taking a random byte in memory, assigning it to a variable and doing this :
if (RandomByteValue != temp[i].name[k])
Which 90% of the time will be true thus setting your flag to 1.
Essentially, you're missing a
varray[i] = lastVariableGotFromUser
At the end of each main loop.
--- Edit : Added in minor corrections to general functionality ---
Try adding in this :
int added = 1;
Then change this :
for (j = 0; j < amount; j++){
with :
for (j = 0; j < added; j++){
and add in :
if (flag == 1){
// Your for loop
added += 1;
}
What was happening was that you iterated through fields of varray that were uninitialized, and contained random memory. With those modifications (If i didn't forget one, it should work. Try to always limit your loops to only the useful iterations. If you know you only have one variable added in, don't iterate through the 3 fields.
------- Last edit to correct a detail in his code -------
So, your whole :
for (k = 0; temp[i].name[k] != '\0'; k++){
Can be deleted. Now i also know that you don't want to use string.h, However, recoding a strcmp ain't all that complicated. Let's call it
int comp_str(str, str2) // Returns 1 if they don't match, zero if they do.
then just replace your whole for with :
if (comp_str(temp[i].name, varray[j].name) == 0) {
flag = 0;
break;
}
else
flag = 1;
You only want to set the flag when a whole string has been analyzed. So pass it to another function, act upon the return value, and it works! Generally slice your code up. Easier to act/think on. (and also avoids having things like varray[j].name[k] != temp[i].name[k] which is long an not so pleasing to read, in your code.)

Resources