Function not updating an int field - c

Everything seems to working fine except for my SPOILED votes int is staying at 0 and not being updates by the function. I have tried adding a pointer thinking it would point to the object outside of the function which it does but the ++ function is not updating
#include <stdio.h>
struct candidates
{
char name[20];
int votes;
};
struct candidates electionCandidates[7];
void Initialize(struct candidates EC[]);
void Processvotes(struct candidates EC[], int *BadVote);
void printResults(struct candidates EC[], int *BadVote);
int main()
{
int i, SPOIL = 0;
Initialize(electionCandidates);
Processvotes(electionCandidates, &SPOIL);
printResults(electionCandidates, &SPOIL);
for(i = 0; i < 7; i++)
{
printf("%s",electionCandidates[i].name);
printf("%d\n\n",electionCandidates[i].votes);
}
printf("%d", SPOIL);
}
void Initialize(struct candidates EC[])
{
int i;
FILE *fp;
fp = fopen("elections.txt", "r");
for (i = 0; i < 7; i++)
{
fgets(EC[i].name, 20, (FILE*)fp);
}
fclose(fp);
}
void Processvotes(struct candidates EC[], int *BadVote)
{
int TVOTE, i;
FILE *fp;
fp = fopen("elections.txt", "r");
for (i = 0; i < 7; i++)
{
fgets(EC[i].name, 20, (FILE*)fp);
}
for (i = 0; i < 365; i++)
{
fscanf(fp, "%d", &TVOTE);
if (TVOTE == 1)
EC[0].votes++;
if (TVOTE == 2)
EC[1].votes++;
if (TVOTE == 3)
EC[2].votes++;
if (TVOTE == 4)
EC[3].votes++;
if (TVOTE == 5)
EC[4].votes++;
if (TVOTE == 6)
EC[5].votes++;
if (TVOTE == 7)
EC[6].votes++;
if (TVOTE < 1 || TVOTE > 7)
*BadVote++;
}
fclose(fp);
}
void printResults(struct candidates EC[], int *BadVote)
{
int i, Win = 0, WinSCORE = 0, Runner = 0, RunnerSCORE = 0;
for (i = 0; i < 7; i++)
{
if (EC[i].votes > WinSCORE)
{
WinSCORE = EC[i].votes;
Win = i;
}
if (EC[i].votes == WinSCORE)
{
RunnerSCORE = EC[i].votes;
Runner = i;
}
}
if (WinSCORE == RunnerSCORE)
{
printf("There was a tie between %s and %s who both got a total of %d votes each. There were %d spoiled votes\n", EC[Win].name, EC[Runner].name, WinSCORE, *BadVote);
}
else
printf("%s won the election with a total of %d votes. There was a total of %d spoiled votes.\n", EC[Win].name, WinSCORE, *BadVote);
}
Any help will be appreciated.

The postfix ++ operator takes precedence over the *; when you write *BadVote++, you're actually incrementing the pointer, not the value being pointed to. You should instead write (*BadVote)++. See this question for more.

I'm pretty sure it's a problem with the precedence of the operators. Try this:
if (TVOTE < 1 || TVOTE > 7)
(*BadVote)++;

Related

The file becomes NULL after printing 254 rows in .txt

I am trying to solve the problem of recursion.
The problem is : Given a number n, print out all the possible combinations of set {a, b, ..., a+n-1}. Output the answer in "output-n.txt". 1<=n<=9.
Here's my code:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
void comb(int n,int curlen,int j,int num[],int flag) {
int i,k;
char filename[20] = "output-0.txt";
filename[7] = n + '0';
char ans[20] = { 0 };
FILE* fptr;
fptr = fopen(filename, "a");
if (fptr != NULL) {
if (curlen < n && flag != 0) {
for (i = 0; num[i] != 0; i++) {
ans[i] = num[i] + '`';
}
for (k = 0; k <= curlen; k++) {
fprintf(fptr, "%c", ans[k]);
}
fprintf(fptr, " ");
if (curlen == 0 && num[0] == n) {
fclose(fptr);
}
else {
comb(n, curlen + 1, j + 1, num, 0);
}
}
else {
for (; j <= n; j++) {
num[curlen] = j;
comb(n, curlen, j, num, 1);
}
}
}
}
int main() {
int n,flag=0,num[20] = { 0 };
scanf("%d", &n);
comb(n, 0, 1, num, flag);
system("pause");
return 0;
}
My program is doing fine while 1<=n<=7, but at n=8 and n=9, the FILE pointer becomes NULL in the middle and can only output part of the answers.
I looked closely to the output .txt file and realized that both of the files can only output to the 254th row.I wonder did I make any mistake.
Thanks for answering.
You have hit the limit for the number of open files.
You keep opening the same file for append and don't always close it. When I rearranged the code so that it opens the file once in main in "w" mode, it works correctly.
#include <stdio.h>
#include <stdlib.h>
void comb(FILE *fptr, int n,int curlen, int j, int num[], int flag) {
int i,k;
char ans[20] = { 0 };
if (curlen < n && flag != 0) {
for (i = 0; num[i] != 0; i++) {
ans[i] = num[i] + '`';
}
for (k = 0; k <= curlen; k++) {
fprintf(fptr, "%c", ans[k]);
}
fprintf(fptr, " ");
if (curlen == 0 && num[0] == n) {
//fclose(fptr);
}
else {
comb(fptr, n, curlen + 1, j + 1, num, 0);
}
}
else {
for (; j <= n; j++) {
num[curlen] = j;
comb(fptr, n, curlen, j, num, 1);
}
}
}
int main() {
int n,flag=0,num[20] = { 0 };
char filename[20] = "output-0.txt";
if(scanf("%d", &n) != 1 || n < 1 || n > 9) // sanity check
return 1;
filename[7] = n + '0';
FILE *fptr = fopen(filename, "w"); // open once
if(fptr != NULL) {
comb(fptr, n, 0, 1, num, flag); // pass the file pointer
fclose(fptr);
}
return 0;
}

Updating a file containing an array of structures in C

I need to change only one element of an int array in a structure array and "update" it into the folder.
Here is my code:
This is the structure
typedef struct studenti
{
char index[10];
char ime[20];
char prezime[20];
int kviz[10];
} studenti;
My main
int main(){
studenti student[120];
pretraga(file, student);
}
Function
void pretraga(FILE *file, studenti student[120])
{
int odabir;
int unos;
int bodovi;
int index;
char s[20];
fopen("studenti_2022.txt", "r+");
printf("Unesite prezime:");
scanf("%s",s);
for(int i = 0; i < 120; i++)
{
if(strcmp(student[i].prezime,(s))==0)
{
printf("%s\n%s\n%s\n", student[i].index, student[i].ime, student[i].prezime);
for (int j = 0; j < 10; j++)
{
printf("%d ", student[i].kviz[j]);
}
printf("\n");
}
}
fopen("studenti_2022.txt", "r+");
do
{
printf("Da li zelite urediti kviz(1-DA, 0-NE)?");
scanf("%d", &odabir);
if(odabir == 1){
do
{
printf("Unesite koji kviz zelite urediti: ");
scanf("%d", &unos);
index = unos - 1;
if(unos > 0 && unos < 11)
{
do
{
printf("Unesite broj bodova: ");
scanf("%d", &bodovi);
if(bodovi > 0 && bodovi < 21)
{
for (int j = 0; j < 10; j++)
{
if(j == index)
{
for(int i = 0; i < 120; i++)
{
if(strcmp(student[i].prezime,(s))==0)
{
student[i].kviz[index] = bodovi;
printf("\n\n%d\n\n", student[i].kviz[j]);
fseek(file, sizeof(student[i].kviz[j]), SEEK_CUR);
fprintf(file, "%d", student[i].kviz[j]);
}
}
}
}
}else
{
printf("Greska !\n");
}
}while(bodovi < 0 || bodovi > 20);
}else
{
printf("Greska pri unosu !\n");
}
}while(unos < 0 || unos > 10);
}else if(odabir == 0)
{
return -1;
}
}while(odabir < 0 || odabir > 1);
fclose(file);
}
Do you have any tips what I could change, or maybe another way of doing it? I am new to this so I am open for suggestions. And the file has to remain the same (by the looks of it) I only need to be able to change 1 number in the int array kviz and write it on the place where the number was changed.
This is how the file looks like. The red mark is an example as if I wanted to change that number to 18.
Hope you understood what I wanted to say.
Also, the char s is used for user input to compare a string and display the whole structure of the student. And then I need to change from that specific student an element of int kviz

Incorrect output using strcmp

I'm doing the day 8 of the 30 days of code in HackerRank and I am having a problem with strcmp.
The code asks the user for names of people and their numbers, then asks for other names, if a name wasn't entered before, then it outputs Not found, but if it was then it outputs the name and his number. But for some reason, the output only works in the last loop of the for statement.
Code:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
typedef struct {
char name[100];
int number;
} phonebook;
int main() {
int n = 0;
do {
scanf("%i", &n);
} while (n < 1 || n > 100000);
int i = 0;
phonebook people[n];
for (i = 0; i < n; i++) {
scanf("%s %i", people[i].name, &people[i].number);
}
char othernames[n][100];
for (i = 0; i < n; i++) {
scanf("%s", othernames[i]);
}
for (i = 0; i < n; i++) {
if (strcmp(othernames[i], people[i].name) == 0) {
printf("%s=%i\n", people[i].name, people[i].number);
} else {
printf("Not found\n");
}
}
return 0;
}
You didn't find the othernames from the beginning to end to compare peopleevery time, so you need to replace
for (i = 0; i < n; i++) {
if (strcmp(othernames[i], people[i].name) == 0) {
printf("%s=%i\n", people[i].name, people[i].number);
}
else {
printf("Not found\n");
}
}
to
bool found = false;
for (i = 0; i < n; i++) {
for ( j = 0 ; j < n ; j++ ) {
if (strcmp(othernames[j], people[i].name) == 0) {
printf("%s=%i\n", people[i].name, people[i].number);
found = true;
}
}
}
if ( found == false ) printf("Not found\n");
The problem is othernames should just be an array of char, not a matrix. And for each othername entered, you must scan whole phonebook to find it or display Not found. As coded, you only test if the i-th othername typed happens to correspond to the i-th entry in the phone book.
Here is a modified version:
#include <stdio.h>
#include <string.h>
typedef struct {
char name[100];
int number;
} phonebook;
int main() {
int n = 0;
do {
if (scanf("%i", &n) != 1)
return 1;
} while (n < 1 || n > 100000);
phonebook people[n];
for (int i = 0; i < n; i++) {
if (scanf("%99s %i", people[i].name, &people[i].number) != 2)
return 1;
}
for (int i = 0; i < n; i++) {
char othername[100];
if (scanf("%99s", othername) != 1)
break;
int j;
for (j = 0; j < n; j++) {
if (strcmp(othername, people[j].name) == 0) {
printf("%s=%i\n", people[i].name, people[i].number);
break;
}
}
if (j == n) {
printf("Not found\n");
}
}
return 0;
}
Note that it is probably not a good idea to store phone numbers as int values. Better use a char array so an initial 0 is significant and to store longer numbers.

Changing Struct Array from Function (Reading from file)

I have the following struct
struct candidates
{
char name[20];
int votes;
};
struct candidates electionCandidates[];
I need to read in from a file and update the names electionCandidates[0] through 7.
I can do so with the following
for (i = 0; i < 7; i++)
{
fgets(electionCandidates[i].name, 20, (FILE*)fp);
}
But I need to do this in a function.
I have tried
void Initialize(struct candidates* EC[]);
Initialize(&electionCandidates);
void Initialize(struct candidates* EC[])
{
int i;
FILE *fp;
fp = fopen("elections.txt", "r");
for (i = 0; i < 7; i++)
{
fgets(EC[i].name, 20, (FILE*)fp);
}
fclose(fp);
}
Keeps saying it doesn't see name. Or the whole thing could be wrong. I am not sure.
Any help would be appreciated.
You need to look at your Initialize() function signature, and turn on your compiler warnings (or pay attention to them if they're already on). You are declaring Initialize() to take an array of pointers to struct candidates, which is not what you are passing - an array of struct candidates. The array decays to a pointer, so struct candidates *EC is what your argument should look like (or, alternately, struct candidates EC[], which is equivalent in this case), not struct candidates *EC[]. And then call your function without the &...
Given
struct candidates
{
char name[20];
int votes;
};
struct candidates electionCandidates[];
You want
void Initialize(struct candidates EC[])
{
/* ... */
}
Initialize(electionCandidates);
When passed as a function argument, the array of structs decays to a pointer to its first element.
I got it loading the names and everything but I guess I need to point to SPOIL in this? It is not reading or doing the votes/spoiled votes, giving 0 for both.
#include <stdio.h>
struct candidates
{
char name[20];
int votes;
};
struct candidates electionCandidates[7];
void Initialize(struct candidates EC[]);
void Processvotes(struct candidates EC[], int BadVote);
void printResults(struct candidates EC[], int BadVote);
int main()
{
int i, SPOIL = 0;
Initialize(electionCandidates);
Processvotes(electionCandidates, SPOIL);
printResults(electionCandidates, SPOIL);
}
void Initialize(struct candidates EC[])
{
int i;
FILE *fp;
fp = fopen("elections.txt", "r");
for (i = 0; i < 7; i++)
{
fgets(EC[i].name, 20, (FILE*)fp);
}
fclose(fp);
}
void Processvotes(struct candidates EC[], int BadVote)
{
int TVOTE, i;
FILE *fp;
fp = fopen("elections.txt", "r");
fscanf(fp, "%d", &TVOTE);
for (i = 0; i < 365; i++)
{
if (TVOTE == 1)
EC[0].votes++;
if (TVOTE == 2)
EC[1].votes++;
if (TVOTE == 3)
EC[2].votes++;
if (TVOTE == 4)
EC[3].votes++;
if (TVOTE == 5)
EC[4].votes++;
if (TVOTE == 6)
EC[5].votes++;
if (TVOTE == 7)
EC[6].votes++;
if (TVOTE < 1 || TVOTE > 7)
BadVote++;
}
fclose(fp);
}
void printResults(struct candidates EC[], int BadVote)
{
int i, Win = 0, WinSCORE = 0, Runner = 0, RunnerSCORE = 0;
for (i = 0; i < 7; i++)
{
if (EC[i].votes > WinSCORE)
{
WinSCORE = EC[i].votes;
Win = i;
}
if (EC[i].votes == WinSCORE)
{
RunnerSCORE = EC[i].votes;
Runner = i;
}
}
if (WinSCORE == RunnerSCORE)
{
printf("There was a tie between %s and %s who both got a total of %d votes each. There were %d spoiled votes\n", EC[Win].name, EC[Runner].name, WinSCORE, BadVote);
}
else
printf("%s won the election with a total of %d votes. There was a total of %d spoiled votes.\n", EC[Win].name, WinSCORE, BadVote);
}

Replacing elements in an array

I have a problem thats giving me a huge ache.
This piece of code purpose is to fill up an array with integer values and at the same time defend against strings and etc....but it doesn't defend against duplicates, but tried I got to far as replacing the number with a new number for example
Enter 6 integers
1, 2, 2, 3, 4, 5
my code will let me replace that 2 at position 1 with another number. What I want it to do is not to repeat the same number again, for example please replace 2 at position 1. I dont want the user to enter 2 again... and I want to make it to double check the work the array if any repeating numbers exists thank you.
system("clear");
printf("\nEntering Winning Tickets....\n");
nanosleep((struct timespec[]){{1, 0}}, NULL);
system("clear");
char userInput[256];
char c;
int duplicationArray[6] = {-1, -1, -1, -1, -1, -1};
for (i = 0; i < 6; i++)
{
printf("\nPlease enter the %d winning ticket number!(#'s must be between 1-49): ", i+1);
fgets(userInput, 256, stdin);
if ((sscanf(userInput, "%d %c", &winningNumbers[i], &c) != 1 || (winningNumbers[i] <= 0) || winningNumbers[i] >= 50))
{
printf("\nInvalid Input.\n") ;
nanosleep((struct timespec[]){{0, 350000000}}, NULL);
system("clear");
i = i - 1;
}
}
for (i = 0; i < 6 - 1; ++i)
{
min = i;
for (j = i+1; j < 6; ++j)
{
if (winningNumbers[j] < winningNumbers[min])
min = j;
}
temp = winningNumbers[i];
winningNumbers[i] = winningNumbers[min];
winningNumbers[min] = temp;
}
for (i = 0; i < 6; i++)
{
if (winningNumbers[i] == winningNumbers[i+1])
{
duplicationArray[i] = i;
duplicationCounter++;
}
else
{
duplicationCounter--;
}
}
if (duplicationCounter > -6)
{
for (i = 0; i < 6; i++)
{
int j, min, temp;
min = i;
for (j = i+1; j < 6; ++j)
{
if (duplicationArray[j] > duplicationArray[min])
min = j;
}
temp = duplicationArray[i];
duplicationArray[i] = duplicationArray[min];
duplicationArray[min] = temp;
}
for (i = 0; i < 6; i++)
{
if (duplicationArray[i] == -1)
{
zeroCounter++;
}
}
int resize = (6 - zeroCounter)+1;
for (i = 0; i <= resize; i++)
{
if (duplicationArray[i] == -1)
{
i++;
}
else if (duplicationArray[i] != -1)
{
system("clear");
printf("\nDuplicated numbers has been dected in your array. ");
printf("\nPlease replace the number %d at postion %d with another number: ", winningNumbers[duplicationArray[i]], duplicationArray[i]);
fgets(userInput, 256, stdin);
if ((sscanf(userInput, "%d %c", &winningNumbers[duplicationArray[i]], &c) != 1 || (winningNumbers[i] <= 0) || winningNumbers[i] >= 50))
{
printf("\nInvalid Input.\n") ;
nanosleep((struct timespec[]){{0, 350000000}}, NULL);
system("clear");
i = i - 1;
}
}
}
duplicationCounter = 0;
for (i = 0; i < 6; i++)
{
if (winningNumbers[i] == winningNumbers[i+1])
{
duplicationArray[i] = i;
duplicationCounter++;
}
else
{
duplicationCounter--;
}
}
printf("%d, ", duplicationCounter);
}
#include <stdio.h>
#include <stdint.h>
#define DATA_SIZE 6
int main(void){
char userInput[256];
int inputNum, winningNumbers[DATA_SIZE];
uint64_t table = 0;
int i=0;
while(i<DATA_SIZE){
printf("\nPlease enter the %d winning ticket number!(#'s must be between 1-49): ", i+1);
fgets(userInput, sizeof(userInput), stdin);
if(sscanf(userInput, "%d", &inputNum) != 1 || inputNum <= 0 || inputNum >= 50)
continue;
uint64_t bit = 1 << inputNum;
if(table & bit)
continue;
table |= bit;
winningNumbers[i++] = inputNum;
}
for(i=0;i<DATA_SIZE;++i)
printf("%d ", winningNumbers[i]);
printf("\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define DATA_SIZE 6
int inputNumberWithRangeCheck(const char *msg, const char *errMsg, int rangeStart, int rangeEnd){
char inputLine[256];
int n;
for(;;){
printf("%s", msg);
fgets(inputLine, sizeof(inputLine), stdin);
if(sscanf(inputLine, "%d", &n) != 1 || n < rangeStart || n > rangeEnd)
fprintf(stderr, "%s", errMsg);
else
return n;
}
}
int inputNumber(void){
return inputNumberWithRangeCheck(
"\nPlease enter the winning ticket number!(#'s must be between 1-49): ",
"Invalid Input.\n",
1,49);
}
int *inputArray(int *array, size_t size){
int i;
for(i=0;i<size;++i){
printf("\nInput for No.%d\n", i+1);
array[i] = inputNumber();
}
return array;
}
int **duplicateCheck(int *array, size_t size){
int **check, count;
int i, j;
check = malloc(size*sizeof(int*));
if(!check){
perror("memory allocate\n");
exit(-1);
}
//There is no need to sort the case of a small amount of data
//(Cost of this loop because about bubble sort)
for(count=i=0;i<size -1;++i){
for(j=i+1;j<size;++j){
if(array[i] == array[j]){
check[count++] = &array[i];
break;
}
}
}
check[count] = NULL;
if(count)
return check;
else {
free(check);
return NULL;
}
}
int main(void){
int winningNumbers[DATA_SIZE];
int **duplication;
int i, j;
inputArray(winningNumbers, DATA_SIZE);
while(NULL!=(duplication = duplicateCheck(winningNumbers, DATA_SIZE))){
for(i=0;i<DATA_SIZE;++i){
if(duplication[i]){
printf("\nyour input numbers : ");
for(j=0;j<DATA_SIZE;++j)
printf("%d ", winningNumbers[j]);
fprintf(stderr, "\nThere is duplicate. Please re-enter.\n");
*duplication[i] = inputNumber();
} else
break;
}
free(duplication);
}
for(i=0;i<DATA_SIZE;++i)
printf("%d ", winningNumbers[i]);
printf("\n");
return 0;
}

Resources