How do I scan in an N number of strings (using structs) and then output that list of strings in reverse? - c++

Using the specific struct below,
struct Student
{
char first[50];
char last[50];
char id[20];
};
How do I scan in an N number of strings consisting of first name, last name and ID number and then output that entire list backwards?
For example:
Input:
3
Dent Arthur 12345ABC
Prefect Ford 54321CBA
McMillan Tricia AB9876
Output:
McMillan Tricia AB9876
Prefect Ford 54321CBA
Dent Arthur 12345ABC
Here's what I have so far
#include <stdio.h>
#include <string.h>
struct Student
{
char first[50];
char last[50];
char id[20];
};
int main( )
{
int N, i;
scanf("%d", &N);
struct Student NAME;
for(i=0; i<N; i++){
scanf("%s %s %s", NAME.first[i], NAME.last[i], NAME.id[i]);
}
/*struct Student prefect;
scanf("%s %s %s", &prefect.first, &prefect.last, &prefect.id);
struct Student mcmillan;
scanf("%s %s %s", &mcmillan.first, &mcmillan.last, &mcmillan.id);*/
printf("\n");
printf("%s %s %s\n", NAME.first[i], NAME.last[i], NAME.id[i]);
printf("%s %s %s\n", NAME.first[i], NAME.last[i], NAME.id[i]);
printf("%s %s %s\n", NAME.first[i], NAME.last[i], NAME.id[i]);
return 0;
}

If you want to print the list (array) in a reverse manner,
for(i=N-1; i>=0; i--){
printf("%s %s %s\n", NAME.first[i], NAME.last[i], NAME.id[i]);
}
This fixes the reversing problem, although there is one more problem in the code. You have declared the members of struct to be of type string, and in the main function, you treat them as an array of strings. This won't work. You probably wanted to have an array of struct objects. This is how to go about it:
#include <stdio.h>
#include <string.h>
struct Student
{
char first[50];
char last[50];
char id[20];
};
int main( )
{
int N, i;
scanf("%d", &N);
struct Student NAME[10];
for(i=0; i<N; i++){
scanf("%s %s %s", NAME[i].first, NAME[i].last, NAME[i].id);
}
/*struct Student prefect;
scanf("%s %s %s", &prefect.first, &prefect.last, &prefect.id);
struct Student mcmillan;
scanf("%s %s %s", &mcmillan.first, &mcmillan.last, &mcmillan.id);*/
printf("\n");
for(i=N-1; i>=0; i--){
printf("%s %s %s\n", NAME[i].first, NAME[i].last, NAME[i].id);
}
return 0;
}
Link to ideone: http://ideone.com/hgPjjn

suggest modifying the struct to include a 'previous' and 'next' pointers
and putting the structs into a linked list.
perhaps by malloc'ing the struct instances, as each data becomes available.
linking the malloc'd struct onto the end of the linked list.
then to output,
walk down to the end of the list
then
printing current value,
step to previous list entry,
print value, etc
until back at the head pointer for the list.
could also insert each struct entry at the beginning of
the linked list,
that would avoid having to walk down the list
to find the last struct, before being able to print

You have made a bit error while tacking the students from console. First of all for taking the all student you have to create a array of struct Student-
struct Student students[100];
Then you may take the input from the user like this -
for(i=0; i<N; i++){
scanf("%s %s %s", students[i].first, students[i].last, students[i].id);
}
And after that all things remain same.When we write the complete code it would be -
#include <stdio.h>
#include <string.h>
struct Student
{
char first[50];
char last[50];
char id[20];
};
int main( )
{
int N, i;
scanf("%d", &N);
struct Student students[100];
for(i=0; i<N; i++){
scanf("%s %s %s", students[i].first, students[i].last, students[i].id);
}
printf("\n");
for(i=N-1; i>=0; i--){
printf("%s %s %s\n", students[i].first, students[i].last, students[i].id);
}
return 0;
}

This will work
#include <stdio.h>
#include <string.h>
struct Student {
char first[50];
char last[50];
char id[20];
};
int main() {
int N, i;
scanf("%d", &N);
struct Student NAME[N];
for (i = 0; i < N; ++i)
scanf("%s %s %s", NAME[i].first, NAME[i].last, NAME[i].id);
printf("\n");
for (i = N - 1; i >= 0; --i)
printf("%s %s %s\n", NAME[i].first, NAME[i].last, NAME[i].id);
return 0;
}

Related

Mapping string to int CPP - Output hangs during execution

I am currently doing a practice problem in hacker rank. The link is : https://www.hackerrank.com/challenges/linkedin-practice-dictionaries-and-maps
#include<cstdio>
#include<map>
#include<vector>
#include<conio.h>
#include<iostream>
#include<string>
using namespace std;
map<std::string, int> dict;
map<std::string, int>::iterator k;
int i, j, temp, n;
long long num;
//char check[100][100];
std::string str, sea;
int main()
{
scanf("%d", &n);
j = n;
while(j--)
{
scanf("%s %d", &str, &num);
dict.insert(make_pair(str, num));
}
printf("finished\n");
printf("%s %d\n", "sam", dict["sam"]);
while(scanf("%s", str))
{
if(str.empty())
break;
//printf("k is %s\n",str);
k = dict.find(str);
if(k != dict.end())
{
printf("%s %d\n", str, dict[str]);
}
else
{
printf("Not found\n");
}
}
getch();
}
The program runs fine until the printf statement "finished". Then in the next output for the dict statement occurs as
finished
sam 0
And in while statement, when it searches for string in map, the application hangs, and closes automatically. While inserting values I tried to use:
dict[str] = num;
dict.insert(pair(str, num));
dict.insert(make_pair(str, num));
Please mention if there is any corrections I need to do in the program. Any help is appreciated. Thanks!
This statement,
scanf("%s %d", &str, &num);
… is not a valid way to input a std::string. It has Undefined Behavior. All bets are off.
You can input to a char buffer, and conveniently std::string provides such a buffer. E.g.
str.resize( max_item_length );
scanf("%s %d", &str[0], &num);
str.resize( strlen( &str[0] ) );
Of course you can just use C++ iostreams instead, throughout the code, e.g.
cin >> str >> num;

Cannot resolve EXC_BAD_ACCESS (code=EXC_I386_GBFLT)

I'm very new at C++, maintaining my M.Sc on Information Systems. I have my first C++ homework announced and have been working on it for a couple of days. The aim of the code is simply to read info from a text file and print it on screen, then make calculation on some of it and print results to a new text file. However when I build, it gives the error:
EXC_BAD_ACCESS (code=EXC_I386_GBFLT)
in the first fscanf in readInfo function.
I know the code I wrote is not completely efficient but I just want it to print on screen and on output file correctly. I would really appreciate if anyone help me to resolve this error. I am about to freak out...
#include <stdio.h>
typedef struct {
char id[10];
char name[40];
float midterm;
float final;
int attendance;
}Student;
void readInfo(Student studentList[], int *count)
{
FILE *fin=fopen("scores.txt","r");
char surname = '\0';
*count=0;
while(!feof(fin))
{
fscanf(fin,"%c %c %c %f %f %d",studentList[*count].id, studentList[*count].name, &surname, &studentList[*count].midterm, &studentList[*count].final, &studentList[*count].attendance);
strcpy(studentList[*count].name, studentList[*count].name);
strcat(studentList[*count].name, " ");
strcat(studentList[*count].name, &surname);
*count++;
}fclose(fin);
printf("%-7s%17s %5.1f %5.1f %-2d\n", studentList[*count].id, studentList[*count].name, studentList[*count].midterm, studentList[*count].final, studentList[*count].attendance);
}
float studentScore(float midterm, float final, int attendance)
{
float score;
int maxAttend=0;
char id[10];
char name[40];
char surname[40];
FILE *fin=fopen("scores.txt","r");
while(!feof(fin))
{
fscanf(fin,"%c %c %c %f %f %d",id, name, surname, &midterm, &final, &attendance);
if(attendance>maxAttend)
maxAttend=attendance;
}fclose(fin);
score=midterm*0.3+final*0.5+(maxAttend/20)*attendance;
return score;
}
float avgScore(Student studentList[])
{
float average;
int count;
int totalScore=0;
readInfo(studentList, &count);
for(int i=0; i<=count; i++)
{
totalScore+=studentScore(studentList[count].midterm, studentList[count].final, studentList[count].attendance);
}
average=totalScore/count;
return average;
}
void courseGradeOutput(Student studentList[])
{
FILE *fout=fopen("output.txt","w");
int count;
int pass=0;
float score;
char letterGrade[2];
float avg;
fprintf(fout,"\tId\tName, Surname = (Score, Letter)\n");
readInfo(studentList, &count);
for(int i=0; i<=count; i++)
{
score=studentScore(studentList[i].midterm, studentList[i].final, studentList[i].attendance);
if(score>=0 && score<=49)
{ letterGrade[0]={'F'};
letterGrade[1]={'F'};}
else if (score>=50 && score<=59)
{letterGrade[0]={'F'};
letterGrade[1]={'D'};}
else if (score>=60 && score<=64)
{letterGrade[0]={'D'};
letterGrade[1]={'D'};}
else if (score>=65 && score<=69)
{letterGrade[0]={'D'};
letterGrade[1]={'C'};}
else if (score>=70 && score<=74)
{letterGrade[0]={'C'};
letterGrade[1]={'C'};}
else if (score>=75 && score<=79)
{letterGrade[0]={'C'};
letterGrade[1]={'B'};}
else if (score>=80 && score<=84)
{letterGrade[0]={'B'};
letterGrade[1]={'B'};}
else if (score>=85 && score<=89)
{letterGrade[0]={'B'};
letterGrade[1]={'A'};}
else if (score>=90 && score<=100)
{letterGrade[0]={'A'};
letterGrade[1]={'A'};}
if(score>=60)
pass++;
fprintf(fout,"%7s %16s = ( %4.1f, %6s\n)", studentList[i].id, studentList[i].name, score, letterGrade);
}
avg=avgScore(studentList);
fprintf(fout,"\nSome statistics:\n\nClass Avg Score: %5.2f \n #Students: %11d \n #Passed Students: %4d \n #Failed Students: %4d",avg,count,pass,(count-pass));
fclose(fout);
}
int main()
{ Student studentList[100];
int count;
readInfo(studentList, &count);
courseGradeOutput(studentList);
}
Screenshot
The crash is most likely caused by either fscanf followed by strcpy and/or by your increment of count inside readInfo.
You write *count++, but this is equivalent to
count = count + 1;
*(count-1);
What you want is (*count)++.
The fscanf scans characters %c where you want to scan strings %s (for id and name). You also want to scan surname as a string, probably, but then you need to change surname to be a character array:
char surname[30];
*count=0;
while(!feof(fin))
{
fscanf(fin,"%s %s %s %f %f %d",studentList[*count].id, studentList[*count].name, surname, &studentList[*count].midterm, &studentList[*count].final, &studentList[*count].attendance);
strcat(studentList[*count].name, " ");
strcat(studentList[*count].name, surname);
(*count)++;
}
fclose(fin);
I also removed the first strcpy as you were copying from a buffer to itself, which is not allowed.
I haven't checked the other functions thoroughly, but I do notice that you do not use the result from your readInfo called from main when you do courseGradeOutput: this function calls readInfo again. You could modify it to take the read student records and the count, so you don't have to read the file again.
You might also want to improve scanf a bit to pass a width, such as %29s for name, to avoid overflowing the buffer when the name inside the file is too long; and the same for the other strings you scan. You should then also look at the return value of fscanf and only use the things you scanned when it succeeded in scanning every argument.

fill Arry function not storing characters and outputting symbols

I wrote this program for class. I have a problem with displaying what in the arry
all i get is symbols instead of a character even though i filled them with char from a file provided by the professor. please help me figure out what is the problem here i need it for tomorrow
// This program grades multiple choice exams1. Each exam consists of 20 questions.
//Each question has one of four possible answers: A, B, C, or D.
#include <stdio.h>
#include<stdlib.h>
#include <math.h>
const int maxsize = 20;
int fillArry (FILE *fi,char arry[],const int maxsize);
double gradeExam (char arry[], char studarry[],const int maxsize);
void desplayResults (double right);
int main ()
{
char arry[maxsize];
char studarry[maxsize];
int num,num1,i,right;
FILE *fi,*sd;
fi = fopen ("CorrectAnswers.txt","r");
if ( fi == NULL )
{
printf( "Error opening input file.\n\n" );
exit(1);
}
sd = fopen ("StudentAnswers.txt", "r");
if ( sd == NULL )
{
printf( "Error opening input file.\n\n" );
exit(1);
}
num = fillArry (fi,arry,maxsize);
num1 = fillArry (sd,studarry,maxsize);
for (i=0;i<maxsize;i++)
{
printf("%c\n",arry);
}
for (i=0;i<maxsize;i++)
{
printf("%c\n",studarry);
}
right = gradeExam (arry, studarry ,maxsize);
printf("you got %i right\n", right);
desplayResults (right);
return 0;
}
int fillArry (FILE *fi,char arry[],const int maxsize)
{
int u = 0;
while((fscanf(fi,"%c",&arry)==1 )&& u< maxsize)
{
u++;
}
return u;
}
double gradeExam (char arry[], char studarry[],const int maxsize)
{
int i, right=0, wrong=0;
for (i=1;i<=maxsize;i++)
{
if (arry[i]==studarry[i])
right++;
else
{
printf ("question number %i :%c is wrong, the correct answer is %c\n\n",i,studarry,arry);
wrong++;
}
}
printf("\nnumber of wrong answers: %i\n",wrong);
return right;
}
void desplayResults (double right)
{
double res;
res = (right/20)*100;
printf("You got %s %.2lf on the exam\n","%",res);
if (res<70)
printf ("You failed the exam\n");
else
printf ("You passed the exam\n");
}
The problem is with your fscanf statement. Try this out.
fscanf(fi,"%s",arry)
Also, for displaying the array contents, you have to do it like this :
for(i=0; i<maxsize; i++)
{
printf("%c",arry[i]);
}
EDIT1 : I have verified the same thing at my end and it is working. Please check the contents of the file CorrectAnswers.txt.
EDIT2 : I got the problem. It is in your print statement :
printf ("question number %i :%c is wrong, the correct answer is %c\n\n",i,studarry,arry);
Please correct it to :
printf ("question number %i :%c is wrong, the correct answer is %c\n\n",i,studarry[i],arry[i]);

structures and files

I have made text file studenti.txt
Gatis Lietnieks 15.06.1993 v
Vizma Kalesnica 20.08.1991 s
Katrina Sabone 06.12.1992 s
Haralds Burkovskis 01.02.1989 v
Jezups Martinovs 02.05.1990 v
Vizma Zigurde 16.09.1988 s
Stasija Balode 12.12.1993 s
Jānis Bērziņš 13.03.1992 v
Zigurds Ritms 16.05.1990 v
Pauls Zirdzins 12.11.1989 v
Zane Skarbule 28.12.1990 s
Aiga Bulle 11.08.1993 s
Andrejs Fomkins 11.06.1989 v
Maikls Dzordans 08.01.1988 v
I want to read file and print it in c program output.
My code is:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <windows.h>
#include <ctype.h>
#define N 16
int main()
{
FILE *fails_st;
struct date
{ int da_year;
int da_month;
int da_day;
};
struct studenti
{
int Nr;
char name[25];
char surname[25];
struct date dzd;
char dzimums[1];
} students[N];
int i, j;
system("cls");
fails_st = fopen("studenti.txt", "r");
for(i=0; i<N; i++)
{
fscanf(fails_st, "%d", &students[i].Nr);
fgets(students[i].name, sizeof students[i].name, fails_st);
fgets(students[i].surname, sizeof students[i].surname, fails_st);
fscanf(fails_st, "%d", &students[i].dzd.da_day);
fscanf(fails_st, "%d", &students[i].dzd.da_month);
fscanf(fails_st, "%d", &students[i].dzd.da_year);
fgets(students[i].dzimums, sizeof students[i].dzimums, fails_st);
}
fclose(fails_st);
system("cls");
printf("Student list\n");
for(i=0; i<N; i++)
printf("%d%s%s%d%d%d%s\n", students[i].Nr,
students[i].name, students[i].surname,
students[i].dzd.da_day,students[i].dzd.da_month,students[i].dzd.da_year,students[i].dzimums);
getch();
return 0;
}
But the program output is like this and i am wondering why
Student list
1. Gatis Lietnieks 15.06.1993 v
202011158932
0. Vizma Kalesnica 20.08.1991 s
342685996
2130567168. Katrina Sabone 06.12.1992 s
48739784137
0. Haralds Burkovskis 01.02.1989 v
587162880
0. Jezups Martinovs 02.05.1990 v
626862441
0. Vizma Zigurde 16.09.1988 s
787397928
0. Stasija Balode 12.12.1993 s
987397848739786
0. JŌnis Bńrzi“­ 13.03.1992 v
1041984004198400
4096. Zigurds Ritms 16.05.1990 v
1126864728741408
....
.................................
.................................
.................................
Start by reading a line by line using fgets().
If the first character is a digit then use strtol to convert to number.
Use strtok to break the line - split the string into tokens delimited by dots and spaces
EDIT: Please find the implementation as described in the above steps to read the file into structure. Idea is to read each line using fgets() and parse it using strtok at required delimiters etc.,
struct date
{ int da_year;
int da_month;
int da_day;
};
struct studenti
{
int Nr;
char name[25];
char surname[25];
struct date dzd;
char dzimums;
} students[N];
int main()
{
FILE *fails_st;
char line[100];
char *ptk; char * end; int i;
fails_st = fopen("studenti.txt", "r");
for(i=0; i < N && fgets(line, sizeof(line), fails_st) != NULL; i++)
{
students[i].Nr = strtol(line, &end, 10);
ptk = strtok(line, " ");
ptk = strtok(NULL, " ");
strcpy(students[i].name, ptk);
ptk = strtok(NULL, " ");
strcpy(students[i].surname, ptk);
ptk = strtok(NULL, ".");
end = (ptk + strlen(ptk));
students[i].dzd.da_day = strtol(ptk, &end, 10);
ptk = strtok(NULL, ".");
end = (ptk + strlen(ptk));
students[i].dzd.da_month = strtol(ptk, &end, 10);
ptk = strtok(NULL, " ");
end = (ptk + strlen(ptk));
students[i].dzd.da_year = strtol(ptk, &end, 10);
ptk = strtok(NULL, " ");
students[i].dzimums = *ptk;
}
fclose(fails_st);
printf("Student list\n");
for(i=0; i<N; i++)
printf("%d. %s %s %d.%d.%d %c\n", students[i].Nr, students[i].name,
students[i].surname, students[i].dzd.da_day,
students[i].dzd.da_month, students[i].dzd.da_year,
students[i].dzimums);
return 0;
}

compare fgets to the user input

can you help me with my code? I want to do a program that will determine if the student id was already used, i can compare them once... but what i want to do is to have a comparison every time the user inputs another student id so... the program will know if the user inputs another used id, i know i need to have a loop before the "Enter student id:".. but still having a hard time to think for the conditions, or if you have a better solutions... i would be happy using it..
guys this is my code:
#include<stdio.h>
#include<stdlib.h>
struct studentinfo{
char id[8];
char name[30];
char course[5];
}s1;
main(){
int i=0;
int count=0;
char arr[50];
FILE *stream = NULL;
stream = fopen("studentinfo.txt", "a+");
struct studentinfo *array[50];
array[i] = (struct studentinfo*) malloc(sizeof(struct studentinfo));
printf("Enter Student ID: ");
scanf("%s", array[i]->id);
fflush(stdin);
while(!feof(stream)){
fgets(arr, 6, stream);
if(strcmp(arr, array[i]->id)==0){
printf("Student ID is used!\n");
free(array[i]);
}
}
printf("Enter Student Name: ");
gets(array[i]->name);
fflush(stdin);
printf("Enter Student Course: ");
scanf("%s", array[i]->course);
fprintf(stream, "\n%s,\t%s,\t%s", array[i]->id, array[i]->name, array[i]->course);
i++;
fclose(stream);
i=0;//for freeing the space
if(array[i] != NULL){
free(array[i]);
}
getch();
}
i was advice to use goto function... and it solve the problem but i was kinda worried because there might have a bug i haven't encountered yet, this is my new code:
#include<stdio.h>
#include<stdlib.h>
struct studentinfo{
char id[8];
char name[30];
char course[5];
}s1;
main(){
int i=0;
int count=0;
char arr[50];
FILE *stream = NULL;
stream = fopen("studentinfo.txt", "a+");
struct studentinfo *array[50];
array[i] = (struct studentinfo*) malloc(sizeof(struct studentinfo));
studid:
printf("Enter Student ID: ");
scanf("%s", array[i]->id);
fflush(stdin);
while(!feof(stream)){
fgets(arr, 6, stream);
if(strcmp(arr, array[i]->id)==0){
printf("Student ID is used!\n");
goto studid;
}
}
printf("Enter Student Name: ");
gets(array[i]->name);
fflush(stdin);
printf("Enter Student Course: ");
scanf("%s", array[i]->course);
fprintf(stream, "\n%s,\t%s,\t%s", array[i]->id, array[i]->name, array[i]->course);
i++;
fclose(stream);
if(array[i] != NULL){
free(array[i]);
}
getch();
}
any other better solutions thnx ^_^