EDIT: New Problem, now I get a totally different output than the one I need. The following is how I have it written, assignment instruction is on the bottom, please and thank you all!
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE * ifp = NULL;
char filename[20];
printf("What is the name of the input file?\n");
scanf(" %s", &filename);
while (ifp == NULL){
/*PROMPT USER FOR INPUT FILENAME*/
printf("What is the name of the input file?\n");
scanf(" %s", &filename);
/*OPEN INPUT FILE*/
ifp = fopen(filename, "r");
}
int totalSize = 0;
fscanf(ifp, "%d", &totalSize);
int id[totalSize];
char category[totalSize];
int handCombatPt[totalSize];
int distCombatPt[totalSize];
int observationPt[totalSize];
int concealPt[totalSize];
int agilityPt[totalSize];
float ranking[totalSize];
int row=0;
for (row=0; row<totalSize; row++) {
fscanf(ifp, "%d %c %d %d %d %d %d\n", id+row, category+row, handCombatPt+row, distCombatPt+row, observationPt+row, concealPt+row, agilityPt+row);
}
for (row=0; row<totalSize; row++) {
if (category[row] == 'A') {
ranking[row] = (handCombatPt[row] + distCombatPt[row]*2 + observationPt[row]*2 + concealPt[row] + agilityPt[row]*5)/10.0;
}
if (category[row] == 'C') {
ranking[row] = (handCombatPt[row]*5 + distCombatPt[row]*5 + observationPt[row] + concealPt[row] + agilityPt[row]*2)/10.0;
}
if (category[row] == 'S') {
ranking[row] = (handCombatPt[row] + distCombatPt[row] + observationPt[row]*5 + concealPt[row]*5 + agilityPt[row]*2)/10.0;
}
}
int firstA, firstS, secondS, firstC, secondC;
for (row=0; row<totalSize; row++) {
if (category[row]=='A' && ranking[firstA] < ranking[row]) {
firstA = row;
}
if (category[row]=='S' && ranking[firstS] < ranking[row]) {
secondS = firstS;
firstS = row;
}
else if (category[row]=='S' && ranking[secondS] < ranking[row]) {
secondS = row;
}
if (category[row]=='C' && ranking[firstC] < ranking[row]) {
secondC = firstC;
firstC = row;
}
else if (category[row]=='C' && ranking[secondC] < ranking[row]) {
secondC = row;
}
}
printf("A : %d %f \n", id[firstA], ranking[firstA]);
printf("C : %d %f \n", id[firstC], ranking[firstC]);
printf("C : %d %f \n", id[secondC], ranking[secondC]);
printf("S : %d %f \n", id[firstS], ranking[firstS]);
printf("S : %d %f \n", id[secondS], ranking[secondS]);
return 0;
}
And here's the input.txt file:
10
14 A 447 252 68 34 978
2 C 230 299 597 180 9
27 A 318 220 97 28 1317
32 C 563 450 547 112 28
8 C 669 260 200 36 171
11 S 179 45 1342 732 174
19 S 74 249 861 1165 6
21 A 757 240 97 119 2032
15 S 275 177 588 577 52
6 C 886 401 327 109 48
The program needs to output the follow:
A: 21 1171.00
C: 6 696.70
C: 32 578.00
S: 11 1094.20
S: 19 1046.50
Any help would be greatly appreciated!
EDIT: Here is the assignment in case it helps anyone understand what I'm trying to do
Problem: Mentorship
It is time for your friend to select their ninja mentors! Ninja students are able to select several mentorsfrom the class of higher level students to learn special skills from. Skills are categorized as Stealth (S),Combat (C), and Agility (A). Your friend will be provided with a file of older students that has their nameand rankings for the different skills. They can then choose 5 mentors to learn from. To assist, your program should read in all of the student’s information and print out the two bestcombat mentors, the two best stealth mentors, and the best agility mentor. If your friend has been adiligent student, they will be able to select these best options! If not, they will need to go down the listand select other mentors.Combat Skills are split into Hand to Hand and Distance. Stealth skills are split into Observation andConcealment. Agility is a singular category.
Input File Format
The first line of the input file will contain a single integer n (5 ≤ n ≤ 100), denoting the number ofpotential mentors, for which information is listed in the file. The following n lines will have all theinformation for all the mentors with one mentor's information on a single line. Each line will have thefollowing format:ID Category HandCombatPts DistanceCombatPts ObservationPts ConcealPts AgilityPtsID will be a positive integer representing the potential mentor.
Category will be a single character, either 'C', 'S' or 'A', for combat, stealth or agility, respectively.HandCombatPts will be an integer representing the number of points that student was given last year bytheir hand to hand combat instructor. DistanceCombatPts will be an integer representing the number of points that student was given lastyear by their distance combat instructor.ObservationPts will be an integer representing the number of points that student was given last year by
their observation and spying skills instructor.
ConcealPts will be an integer representing the number of points that student was given last year by their
concealment and disguise instructor.
AgilityPts will be an integer representing the number of points that student was given last year by theiragility and acrobatics instructor.
How to Compute a Ranking
For each potential mentor, their ranking will be a summation weighted by their category. If they are a potential combat mentor their ranking should be:(HandCombatPts*5 + DistanceCombatPts*5 + ObservationPts + ConcealPts + AgilityPts*2)/10If they are a potential stealth mentor their ranking should be:(HandCombatPts + DistanceCombatPts + ObservationPts*5 + ConcealPts*5 + AgilityPts*2)/10If they are a potential agility mentor their ranking should be:(HandCombatPts + DistanceCombatPts*2 + ObservationPts*2 + ConcealPts + AgilityPts*5)/10
Program Specification
You must use arrays to solve the problem.
Your program should first prompt the user for the name of the input file. Then, your programshould process the input file and write the five best mentors for your friend. Each line shouldlist the category, the ID, and the ranking of the mentor, respectively, separated by spaces.Round the ranking to two decimal places. The mentors must be listed according to category asfollows: agility, followed by the two combat, followed by the two stealth. Both the combat andthe stealth mentors must be listed in descending order of ranking.
First:
'Program compiles but then “program.exe has stopped working'
I'm sorry to have to inform you that this is the usual behaviour. Writing code and getting it to compile is trivial compared with the effort and skill required to get it to do what you want. Testing and debugging is 99% of software development skill. That is why debuggers exist.
Next:
ALWAYS check the result of ALL system calls. In your case, specifically fopen().
...............
[sigh] 'after I set the uninitialized variables to 0, but now I get a completely different output then the one I need'
See above, especially the hint: 'That is why debuggers exist'. It is really MUCH easier for you to fix your problems than to use SO contributors remote-debug by text exchange. You have the actual code, (ie. not what you originally posetd), the environment, test files etc. We have what you are drip-feeding us, both in terms of what you are doing and what you are getting:(
You must learn to debug now, before you write even one more line of code. If you cannot debug, you cannot develop programs and should not try:(
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE * ifp = NULL;
char filename[20];
while (ifp == NULL){
printf("What is the name of the input file?\n");
scanf(" %s", &filename);
ifp = fopen(filename, "r");
}
int totalSize = 0;
fscanf(ifp, "%d", &totalSize);
int id[totalSize];
char category[totalSize];
int handCombatPt[totalSize];
int distCombatPt[totalSize];
int observationPt[totalSize];
int concealPt[totalSize];
int agilityPt[totalSize];
float ranking[totalSize];
int row=0;
for (row=0; row<totalSize; row++) {
fscanf(ifp, "%d %c %d %d %d %d %d\n", id+row, category+row, handCombatPt+row, distCombatPt+row, observationPt+row, concealPt+row, agilityPt+row);
}
for (row=0; row<totalSize; row++) {
if (category[row] == 'A') {
ranking[row] = (handCombatPt[row] + distCombatPt[row]*2 + observationPt[row]*2 + concealPt[row] + agilityPt[row]*5)/10.0;
}
if (category[row] == 'C') {
ranking[row] = (handCombatPt[row]*5 + distCombatPt[row]*5 + observationPt[row] + concealPt[row] + agilityPt[row]*2)/10.0;
}
if (category[row] == 'S') {
ranking[row] = (handCombatPt[row] + distCombatPt[row] + observationPt[row]*5 + concealPt[row]*5 + agilityPt[row]*2)/10.0;
}
}
int firstA=0, firstS=0, secondS=0, firstC=0, secondC=0;
for (row=0; row<totalSize; row++) {
if (category[row]=='A' && ranking[firstA] < ranking[row]) {
firstA = row;
}
if (category[row]=='S' && ranking[firstS] < ranking[row]) {
secondS = firstS;
firstS = row;
}
else if (category[row]=='S' && ranking[secondS] < ranking[row]) {
secondS = row;
}
if (category[row]=='C' && ranking[firstC] < ranking[row]) {
secondC = firstC;
firstC = row;
}
else if (category[row]=='C' && ranking[secondC] < ranking[row]) {
secondC = row;
}
}
printf("A : %d %f \n", id[firstA], ranking[firstA]);
printf("C : %d %f \n", id[firstC], ranking[firstC]);
printf("C : %d %f \n", id[secondC], ranking[secondC]);
printf("S : %d %f \n", id[firstS], ranking[firstS]);
printf("S : %d %f \n", id[secondS], ranking[secondS]);
return 0;
}
This worked, I initialized everything to 0 and made a while loop for the file name, now it outputs corerctly, though more numbers after the decimal than I need but I think i can fix it with a .lf in the variable print part. If anyone can check that and let me know if they see any thing wrong with it please. Thank you all for the help!
Related
I'm stuck on trying to figure out how to take a multiple candidate data from a loop and figure out a winner from them by stating their name, ID, and total percent of votes within the same function. I also need to return the winning candidates ID from the function. For example: candidate 1 - is named Stevens with ID 13.07 and total votes of 1500, candidate 2 - is named George with ID 17.49 and total votes of 2000. I need to output the winner which is George with ID 17.49 and his percent of the total 3500 votes. This is what I have so far but I'm new to programming and have no idea how to figure this out. Any help would be greatly appreciated!
float CandidateData(int N, int X) {
char candName[21];
int i;
double candID;
int candVotes;
int voteSum;
int j = 0;
double max = 0;
double first;
for (i = 0; i < N; i++) { //N is the number of candidates
printf("Enter candidates name (20 characters max): ");
scanf("%s", &candName);
printf("Candidate name: %s\n\n", candName);
printf("Enter candidate ID (float 01.01-52.99): ");
candID = CandidateID(52.99);
printf("Candidate ID is: %g\n\n", candID);
printf("Enter %d precinct votes (int 1-1000): ", X);
voteSum = 0;
for (j = 0; j < X; j++) { //X is number of precincts
candVotes = NumberOfCandidatesAndPrecincts(1000);
printf("Precinct #%d = %d\n", j + 1, candVotes);
voteSum = voteSum + candVotes;
}
printf("Total candidate votes = %d\n", voteSum);
printf("Average votes for county = %d\n\n", voteSum / X);
if (voteSum > max) {
max = voteSum;
}
}
printf("The winning candidate is %s with ID %g with %d% of total votes", candName, candID, )
return (candID);
}
I see few mistakes in your code.
First of all, it should be :
scanf("%s", candName);
not
scanf("%s", &candName);
Because candName is already the address of the first element of the array.
Another issue, suppose a user types Whoever President for candName. Then try this:
printf("Candidate name: %s\n\n", candName);
You will see that only Whoever is printed because scanf("%s",candName) takes input until a white space comes. It can be a blank space (' '), new line (\n) or tab (\t).
Instead, I strongly suggest you to use fgets.
fgets (candName, 21, stdin);
where 21 is the maximum buffer length that you want to have.
Now, you can print candName with printf and observe that fgets puts extra new line ('\n') at the end of your string. You can easily remove it by:
if ((strlen(candName) > 0) && (candName[strlen (candName) - 1] == '\n')){
candName[strlen (candName) - 1] = '\0';}
Keep in mind that using fgets and scanf together is problematic because scanf function leaves \n in the input buffer, after fgets reads input from buffer, you will encounter unexpected results. Use getchar(); after each scanf. It consumes \n. The problem disappears!
The next mistake you made is return_type of CandidateData function. Its return_type is float but type of candID variable is double so make a change for just one of them. In your task, it is sufficient to use float type for candID.
There are also some typos in the last printf function. It should be:
printf("The winning candidate is %s with ID %f with %d of total votes", candName, candID, voteSum);
Let's come to your question. To store the candidate who takes maximum vote, you can declare a struct and fill related fields when number of votes of a candidate exceeds current max value.
I add the final code:
#include <stdio.h>
#include <string.h>
struct President{
char candName[21];
float candID;
int candVotes;
};
float CandidateData(int N, int X) {
struct President winnerCandidate = {.candVotes = 0};
char candName[21];
float candID;
int candVotes;
int voteSum;
int i,j;
for (i = 0; i < N; i++) { //N is the number of candidates
printf("Enter candidates name (20 characters max): ");
fgets (candName, 21, stdin);
if ((strlen(candName) > 0) && (candName[strlen (candName) - 1] == '\n')){
candName[strlen (candName) - 1] = '\0';}
printf("Candidate name: %s\n", candName);
printf("Enter candidate ID (float 01.01-52.99): ");
scanf("%f",&candID);
getchar();
printf("Candidate ID is: %.2f\n", candID);
voteSum = 0;
printf("Enter %d precinct votes (int 1-1000):\n", X);
for (j = 1; j <= X; j++) { //X is number of precincts
scanf("%d",&candVotes);
getchar();
printf("Precinct #%d = %d\n", j , candVotes);
voteSum = voteSum + candVotes;
}
printf("Total candidate votes = %d\n", voteSum);
printf("Average votes for county = %.3f\n\n", voteSum/(float)X);
if(voteSum > winnerCandidate.candVotes){
winnerCandidate.candVotes = voteSum;
winnerCandidate.candID = candID;
strcpy(winnerCandidate.candName,candName);
}
}
printf("The winning candidate is %s with ID %.2f with %d of total votes", winnerCandidate.candName, winnerCandidate.candID, winnerCandidate.candVotes);
return winnerCandidate.candID;
}
int main(){
float winner_candID = CandidateData(3,2);
printf("\nWinner Candidate ID is: %.3f",winner_candID);
return 0;
}
If you have any question, let me know!
So I have the following in my text document:
7
PERSON Sarah 20 5 50
PERSON Jordan 30 10 30
PERSON James 25 42 56.50
GROUP STEEL 2
Martin 21 5 80.50
Martha 25 10 79.75
PERSON Hector 38 10 100.50
PERSON Charles 18 5 35
GROUP LUMBER 3
Jill 19 5 91
Aaron 25 10 98
Mark 28 42 152.80
So I'm trying to get my code to loop through all of the names here and print out info. The name represents the person's name, the first number represents age, the second number represents kilometers ran, and the third number represents amount raised. PERSON represents an individual person, whilst group represents multiple individuals. The 7 in the first line represents the total number of PERSONS and GROUPS; there are 5 people labeled PERSON and 2 groups labeled GROUP.
However, my code is only printing out the information for everyone with the label of PERSON. How can I get my code to print the name of the group along with the information for its members? Here is my code (not completely, but to show what I'm trying to do):
FILE * ifp = fopen("race01.txt", "r");
int numPeople, i, num = 1;
struct person individual;
fscanf(ifp, "%d", &numPeople);
for(i = 0; i < numPeople; i++) {
fscanf(ifp, "%s %s %d %d %f", individual.name, individual.name, &individual.age, &individual.event, &individual.money);
if (individual.event == 42) {
printf("%s registered for the marathon race! They have been assigned the number %d\n", individual.name, num);
}
else {
printf("%s registered for the %dk race! They have been assigned the number %d\n", individual.name, individual.event, num);
}
num++;
}
I've tried all sorts of variations, from a nested for loop to additional scanning line, but nothing seems to cover the "groups".
As Jonathan said you should check if the first string you read is "PERSON" or "GROUP". If it equals "PERSON", you read information (name, age etc...) about this person, if it equals "GROUP", you should read the number of persons in that group and then read information about each person present in that group. Use functions like "strcmp" to compare two strings.
I have a modified version of your code below, it compiles and works fine.
I created a function named "print_raceinfo" which prints information about a person
#include<stdio.h>
#include<math.h>
#define NAME_MAX 25
struct person {
char name[NAME_MAX];
int age;
int event;
float money;
};
void print_raceinfo(struct person individual, int num)
{
if (individual.event == 42) {
printf("%s registered for the marathon race! They have been assigned the number %d\n", individual.name, num);
}
else {
printf("%s registered for the %dk race! They have been assigned the number %d\n", individual.name, individual.event, num);
}
}
int main(){
FILE *fp;
int numPeople, i, num = 1;
struct person individual;
char person_or_group[NAME_MAX];
char group_name[NAME_MAX];
int numpeople_in_group, j;
fp = fopen("F://repoexample/race.txt", "r+");
fscanf(fp, "%d", &numPeople);
for(i = 0; i < numPeople; i++) {
fscanf(fp, "%s", person_or_group);
//Compare the first 6 characters of string person_or_group with "PERSON"
if (strncmp(person_or_group, "PERSON", 6) == 0) {
fscanf(fp, "%s %d %d %f", individual.name, &individual.age, &individual.event, &individual.money);
print_raceinfo(individual, num);
num++;
}
else if (strncmp(person_or_group, "GROUP", 5) == 0){
//Read group name and number of people in that group
fscanf(fp, "%s %d", group_name, &numpeople_in_group);
for (j = 0; j<numpeople_in_group; j++) {
//Extract information for each person in that group
fscanf(fp, "%s %d %d %f", individual.name, &individual.age, &individual.event, &individual.money);
print_raceinfo(individual, num);
num++;
}
}
}
printf("Total number of persons = %d\n", num - 1);
return 0;
}
Output:
I have a very basic idea that I want to implement but somehow my logic for this isn't the best one since the code is not working as I want it to.
I want to have numbers written on screen/in text file in such way that after 20 iterrations there's new line which separates them.
Please take a look.
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE * File = fopen("NUMBERS.txt", "w");
int *a;
int n;
int i;
int j;
int r;
printf("How many numbers do you wish to enter?\n");
scanf("%d", &n);
a = malloc(n*sizeof(int*));
time_t t;
srand((unsigned)time(&t));
fprintf(File, "%d\n", n);
for(i = 0 ; i < n; i++)
{
r = rand() % 100;
a[i]= r;
printf("%d ", r);
fprintf(File, "%d ", r);
if(a[i] % 20 == 0)
{
printf("\n");
fprintf(File, "\n");
}
}
system("pause");
return 0;
}
Lets say that the user enters (21 or any higher number) the output should be:
21
67 24 8 10 27 83 7 89 99 40 69 5 69 12 66 92 99 16 37 22
42
If you want to add a line break after 20 iterations you need to check the i variable used in the iteration instead of the value of the i'th item in the array, so replace
if(a[i] % 20 == 0) with if(i % 20 == 0)
Also, the memory allocation is incorrect as pointed out in another answer (and comment).
I am working on a program to organize a list of numbers from a file and output these numbers in a easier to read format. Such as a file called Counting.txt containing the numbers:
11
1 1 2 3 4 4 4 4 5 5 7
and I want it to output:
1x2 2x1 3x1 4x4 5x2 7x1
The formula for output being vXc, where v is the number and c is the number of times it occurs. But my current program only outputs it as:
1x1 2x1 3x1 4x1 4x1 4x1 4x1 5x1 5x1 7x1
I believe there is a small error in my for loop that doesn't allow me to change my c variable, or the number indicating how many times the actual number occurs. Can anyone help?
My code:
#include <stdio.h>
int main () {
FILE* file = fopen("counting.txt", "r");
int total_num, count = 1, num, num2, i;
if (file == NULL) {
printf("Did not find counting.txt file.\n");
}
fscanf(file, "%d", &total_num);
fscanf(file, "%d", &num);
for (i = 1; i < total_num; i++) {
fscanf(file, "%d", &num);
if (num2 == num) {
count = count + 1;
} else {
printf("%dX%d ", num, count);
count = 1;
}
}
return 0;
}
In the loop you read into num instead of num2. So in general num2 is undefined. You also need at the end of each loop's iteration to assign to num the value of num2.
Also when you print the number of repetitions you should refer to the old value and not the current one, since you don't know if the current number will be followed by other equal numbers.
So you could change your loop to:
for (i=1; i< total_num; i++) {
fscanf(file, "%d", &num2);
if (num2 == num) {
count = count + 1;
}
else {
printf("%dX%d ", num, count);
count = 1;
}
num = num2;
}
printf("%dX%d ", num, count);
I have a file that is organized line by line and the structure of all lines was defined by me but the contents of each line can increase or decrease according to two variables that the same line contains.
Line Example: 1 Andre 2 0 5 13 05 2011 4 13 05 2011
'1' represents the user ID
'Andre' represents the name associated to the ID
'2 0' subdivides: '2' represents how many movies the user as taken home AND '0' represents how many movies reservations the user has.
So far the line is following the pattern %d %s %d %d and they can be stored in the variables I want.
Now the hard part comes. Depending on the '2 0' part, the program knows that has to read the pattern %d %d %d %d ('5 13 05 2011' and '4 13 05 2011' - represent dates of movies taken home) 2 times and also the program knows that after reading 2 times the previous pattern it knows that i doesn't need to read anything else due to the zero part in '2 0'.
Example of line with more data: 1 Andre 2 1 5 13 05 2011 4 13 05 2011 7 14 05 2011
'2 1'
The '2' part tells the program that in that line it should read '5 13 05 2011' and '4 13 05 2011' to variable_one[i][4] (example)
The '1' part tells the program that in that line it should read '7 14 05 2011' to variable_two[i][4] (example)
I'm using fscanf(file, "%d %s %d %d", &id[i],&nomes[i],&livros_num[i][0],&livros_num[i][1]); to read '1 Andre 2 0' but how can i read the rest of the line according to '2 0'?
You can use fscanf.
Here's an example:
int int1;
char char_buf[BUF_SIZE];
fscanf ( file_stream, "%d%s", &int1, char_buf);
After your first call of fscanf, you need to loop depending on the variables you read. You seem to have already realized that the int's you read in your first call determine the number of extra reads you need in the line.
int i;
for ( i=0; i< livros_num[i][0]; i++ ) {
int something, day, month, year; // 'something' is unclear to me in your code
fscanf( file, "%d %d %d %d", &something, &day, &month, &year );
// store these variables wherever
}
// same procedure for second number
for ( i=0; i< livros_num[i][1]; i++ ) {
int something, day, month, year; // 'something' is unclear to me in your code
fscanf( file, "%d %d %d %d", &something, &day, &month, &year );
// store these variables wherever
}
fscanf( file, "%s\n" ); // I'm NOT sure if this is nessecary, to move the file to the next line
fgets(buf,sizeof(buf),f)
p = strtok (buf," ");
p1 = strtok (0," ");
p2 = strtok (0," ");
p3 = strtok (0," ");
n1 = atoi(p1);
n2= atoi(p2);
i=0;
while(n1--)
{
sscanf(p3,"%d %d %d %d", &v1[i],&v2[i],&v3[i],&v4[i] );
strok(0," ");
strok(0," ");
strok(0," ");
p3 = strok(0," ");
i++;
}
i=0;
while(n2--)
{
sscanf(p3,"%d %d %d %d", &v2[i],&v2[i],&v2[i],&v2[i] );
strok(0," ");
strok(0," ");
strok(0," ");
p3 = strok(0," ");
i++;
}
Well, when you read the '2 0' you get two pieces of information: the number times you need to loop for the dates of the movies taken home and the number of times you need to loop to read all the reservations.
int i;
int num_movies_taken, num_movies_reserved;
// read all the dates of the movies taken home
num_movies_taken = livros_num[i][0];
for (i = 0; i < num_movies_taken; i++)
{
fscanf("%d %d %d %d", ...);
}
// read all the reservations
num_movies_reserved = livros_num[i][1];
for (i = 0; i < num_movies_reserved; i++)
{
fscanf("%d %d %d %d", ...);
}
How about
int j;
fscanf(file, "%d %s %d %d", &id[i],&nomes[i],&livros_num[i][0],&livros_num[i][1]);
for (j=0;j<livros_num[i][0];++j)
{
fscanf(file,"%d %d %d %d",&variable_one[0],&variable_one[1],&variable_one[2],&variable_one[3]);
}
etc.