Creating a program in C that saves and shows data - c

I'm new with C, and on the university they are making us create a program that can save data introduced by the user, read the data and check if it’s well introduced. After that it must save that data in each free space, you have 10 empty spaces for saving the data. With all the data saved it must show also the data and compare it with all the data introduced. I made the part of reading the data introduced and cheking if its ok. The problem that I have is that I don’t know how I could make the data base and show that data. Here is the code that I have till now.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char name[30];
int num_sample;
char section;
int cabin;
int day;
int month;
int year;
}Species;
int menu() {
int op = 0;
printf ("\nPrototype Nature Reserve.\n");
printf ("1. Insert a new species.\n");
printf ("2. List the species housed.\n");
printf ("3. Show stadistics.\n");
printf ("4. Exit.\n");
printf ("\nIntroduce an option: ");
scanf ("%d", &op);
return op;
}
void New_species() {
Species e;
int i, j;
char species[100];
char aux[10];
printf("Enter data:\n");
//A fflush is made to not have a problem with the number entered in the menu
fflush(stdin);
gets (species);
//While it is different from - read the text
for (i = 0; species[i] != '-'; i++) {
e.name[i] = species[i];
}
e.name[i] = '\0';
i++;
//We add 1 to the position i because is ending in - and should start reading from the following
for (j = 0; species[i] != '-'; i++,j++) {
aux[j] = species[i];
}
aux[j] = '\0';
e.num_sample = My_atoi(aux);
// Check that the sample is a number and not a character
if (e.num_sample <= 0 || e.num_sample >= 100) {
printf ("--> Error in data format.\n");
}
i++;
//Reads the day introduced
for (j = 0; species[i] != '/'; i++, j++) {
aux[j] = species[i];
}
aux[j] = '\0';
e.day = My_atoi(aux);
//Controls the format of the day
if (e.day <= 0 || e.day > 31) {
printf ("--> Error in data format.\n");
}
i++;
//Reads the month introduced
for (j = 0; species[i] != '/'; i++, j++) {
aux[j] = species[i];
}
aux[j] = '\0';
e.month = My_atoi(aux);
//Controls the format of the month
if (e.month <= 0 || e.month > 12) {
printf ("--> Error in data format.\n");
}
i++;
//Reads the year introduced
for (j = 0; species[i] != '-'; i++, j++) {
aux[j] = species[i];
}
aux[j] = '\0';
e.year = My_atoi(aux);
//Controls the format of the year
if (e.year < 1970 || e.year > 2060) {
printf ("--> Error in data format.\n");
}
i++;
//Reads the section introduced
e.section = species[i];
//Controls that the section is in capital letters
if (e.section < 'A' || e.section > 'Z') {
printf ("--> Error in data format.\n");
}
i+= 2;
//As the cabin is at the end it must reach the \0
for (j = 0; species[i] != '\0'; i++, j++) {
aux[j] = species[i];
}
aux[j] = '\0';
e.cabin = My_atoi(aux);
if (e.cabin < 0 || e.cabin > 20) {
printf ("--> Error in data format.\n");
}
printf ("Species stored successfully (%d/10 free).");
//This printf is just to ensure that the data entered was read correctly
printf ("\n%s", species);
}
int My_atoi(char cad[10]) {
int r = 0;
int i;
for (i = 0; cad[i] != '\0'; i++) {
r = r * 10;
r += cad[i] - '0';
}
return r;
}
void list_species() {
}
void stadistics() {
}
void executeOption(int op) {
switch (op) {
case 1:
New_species();
break;
case 2:
list_species();
break;
case 3:
stadistics();
break;
default:
break;
}
}
int main() {
int op = 0;
do {
op = menu();
executeOption(op);
} while (op != 4);
return 0;
}
I’ve seen that you can use files* so it can create a .txt file for storing but I don’t know how to use it and I don't think that it's allowed in this program.
I'll leave a photo of how it should work
Thanks.

ok u need to save data to a file and load from a file.
here a short code of my and read and write:
#include<stdio.h>
#include<stdlib.h>
typedef struct worker
{
int sal;
char name[25];
}W;
void main()
{
FILE *f;
int i,j=4;
W a[3];
while(j!=3)
{
printf("\nEnter\n[1]write\n[2]read\n[3]exit\n");
scanf("%d",&j);
if(j==1)
{
if (f==NULL)
{
printf("Error!!\n");
exit(0);
}
f=fopen("workers.txt","w");
for(i=0;i<3;i++)
{
printf("\nEnter worker name: ");
scanf("%s",&a[i].name);
printf("\nEnter worker sal: ");
scanf("%d",&a[i].sal);
fprintf(f,"%s %d",a[i].name,a[i].sal);
}
if(j==2)
{
if (f==NULL)
{
printf("Error!!\n");
exit(0);
}
f=fopen("workers.txt","r");
for(i=0;i<3;i++)
{
fscanf(f,"%s %d",a[i].name,&a[i].sal);
printf("\n%s %d",a[i].name,a[i].sal);
}
}
}
fclose(f);}

and I don't think that it's allowed in this program
why wouldn't you be allowed? Yes indeed you can go through two alternatives
To text file
This is the one proposed by dor in his answer where he shows you the way of writing text through fprintf.
To binary file
You can also write to a file using fwrite/fseek like this example I found surfing around you can check it out here -> c-tutorial-binary-file-io
#include<stdio.h>
/* Our structure */
struct rec
{
int x,y,z;
};
int main()
{
int counter;
FILE *ptr_myfile;
struct rec my_record;
ptr_myfile=fopen("test.bin","wb");
if (!ptr_myfile)
{
printf("Unable to open file!");
return 1;
}
for ( counter=1; counter <= 10; counter++)
{
my_record.x= counter;
fwrite(&my_record, sizeof(struct rec), 1, ptr_myfile);
}
fclose(ptr_myfile);
return 0;
}
and retrieving back the data from the binary may go this way as the tutorial shows
#include<stdio.h>
/* Our structure */
struct rec
{
int x,y,z;
};
int main()
{
int counter;
FILE *ptr_myfile;
struct rec my_record;
ptr_myfile=fopen("test.bin","rb");
if (!ptr_myfile)
{
printf("Unable to open file!");
return 1;
}
for ( counter=1; counter <= 10; counter++)
{
fread(&my_record,sizeof(struct rec),1,ptr_myfile);
printf("%d\n",my_record.x);
}
fclose(ptr_myfile);
return 0;
}

If you are looking for a solution in a .txt file I have a proposal,
#include <stdio.h>
int main(){
FILE *in;
FILE *OUT = fopen("read_at.txt", "w");
char name[20];
char capture[80];
int age = 0;
float grade = 0;
puts("introduce your name:");
scanf("%19s", name);
puts("introduce your age:");
scanf("%i", &age);
puts("introduce your Math grade(0-10):");
scanf("%f", &grade);
fprintf(OUT, "Age %i, Grade %f, Name %s\r\n", age, grade, name);
fclose(OUT);
if(!(in = fopen("read_at.txt","r"))){
fprintf(stderr, "The file could not be opened. \n");
return 1;
}
while (fscanf(in, "Age %i, Grade %f, Name %20[^\n]\n", &age, &grade, name)==3){
printf("A %i years old student has achieved a %f mark in last math exam, that student is: %s", age,grade, name);
}
fclose(in);
}
In this code that I have just created you can see how you can just create one file and read and get its data if it has a concrete format. If you are looking for a database you can just put values separated by “;” and new lines (\n). With that if you save it as .csv you would obtain an excel sheet and quite a good database.
If you are interested in this solution, just let me know if you need any additional help.
Regards,

Related

How to detect duplicate string using strcmp()

#include<stdio.h>
#include<stdio.h>
#include<string.h>
struct stud
{
char nam[20];
int num;
char letter[5];
};
int main()
{
struct stud s[5];
int i, j;
for(i = 0; i < 5; i++){
printf("Enter the name of student #%d: ", i+1);
scanf("%s", s[i].nam);
printf("Enter the number grade of student #%d: ", i+1);
scanf("%d", &s[i].num);
}
for (j = 0; j < i; j++) {
if (strcmp(s[i].nam, s[j].nam) == 0)
printf("Error. Duplicate name detected.");
}
for(i = 0; i < 5; i++){
if(s[i].num >= 90 )
strcpy(s[i].letter, "A");
else if(s[i].num >= 80)
strcpy(s[i].letter, "B");
else if(s[i].num >= 70)
strcpy(s[i].letter, "C");
else if(s[i].num >= 60)
strcpy(s[i].letter, "D");
else
strcpy(s[i].letter, "F");
}
for(i = 0; i < 5; i++)
printf("\n%s has a %s ", s[i].nam, s[i].letter);
return 0;
}
This program has the user enter 5 names and 5 numeric grades, which will then result in the output of their respective letter grades for that student. I'm trying to make it so if the user enters a duplicate name, and message will print saying they can't do that. My attempt in trying to do this is as follows:
for (j = 0; j < i; j++) {
if (strcmp(s[i].nam, s[j].nam) == 0)
printf("Error. Duplicate name detected.");
}
Where I believe that s[j] is the previous string, and compare to see if it equals 0(duplicate) and prints a message. This obviously doesn't work however so I would like to know how to fix this so it can correctly detect duplicate names. Thank you.
Also I have posted this question before but the person that provided an explanation deleted their response before I could provide further questions and ask for clarification. So I am posting this again with an attempt in seeking further aid in what I did wrong in my code.
At the start of the detection loop, i is already 5, so using s[i] is undefined behavior
In your detection loop, i is invariant. you are just comparing a name against the last one [except for the UB, of course].
You need two loops to compare all names against one another.
Also, using 5 everywhere is a "magic number". Better to use a #define (e.g. SMAX)
In the code below, I use cpp conditionals to denote old vs. new code:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
Here is the corrected code. It is annotated with the bugs and fixes:
#include <stdio.h>
#include <stdio.h>
#include <string.h>
struct stud {
char nam[20];
int num;
char letter[5];
};
#define SMAX 5 // maximum number of students
int
main()
{
struct stud s[SMAX];
int i, j;
for (i = 0; i < SMAX; i++) {
printf("Enter the name of student #%d: ", i + 1);
scanf("%s", s[i].nam);
printf("Enter the number grade of student #%d: ", i + 1);
scanf("%d", &s[i].num);
}
// NOTE/BUG: i is already SMAX, so using s[i] is UB (undefined behavior)
// NOTE/BUG: i never changes
#if 0
for (j = 0; j < i; j++) {
if (strcmp(s[i].nam, s[j].nam) == 0)
printf("Error. Duplicate name detected.");
}
#else
for (i = 0; i < (SMAX - 1); i++) {
for (j = i + 1; j < SMAX; j++) {
if (strcmp(s[i].nam, s[j].nam) == 0)
printf("Error. Duplicate name detected -- %s\n",s[j].nam);
}
}
#endif
for (i = 0; i < SMAX; i++) {
if (s[i].num >= 90)
strcpy(s[i].letter, "A");
else if (s[i].num >= 80)
strcpy(s[i].letter, "B");
else if (s[i].num >= 70)
strcpy(s[i].letter, "C");
else if (s[i].num >= 60)
strcpy(s[i].letter, "D");
else
strcpy(s[i].letter, "F");
}
// NOTE/BUG: newline should go at the end of the printf to prevent a hanging
// last line
#if 0
for (i = 0; i < SMAX; i++)
printf("\n%s has a %s ", s[i].nam, s[i].letter);
#else
for (i = 0; i < SMAX; i++)
printf("%s has a %s\n", s[i].nam, s[i].letter);
#endif
return 0;
}
UPDATE:
Thanks for the tip! On a side note, how would I make it so while the user is entering the duplicate names, the error message appears and the program ends right there.For example: Enter the name of student 1: dan Enter grade: 87 Enter the name of student 2: dan Enter the grade: 78 Error. No duplicate names allowed. And then the program ends there. –
User234567
Easy enough. I put the duplication detection code into functions.
But, I've added a few more enhancements so this may help you with your learning ;-)
I added reprompting the user if they enter a duplicate.
I hate scanf ;-) I reworked the prompting code by putting it into two functions. It will work better if input is a file. This is useful during testing
I changed the conversion from grade number to grade letter to use a table.
Anyway, here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
struct stud {
char nam[20];
int num;
char letter[5];
};
struct letter {
int num;
const char *letter;
};
#define LET(_num,_let) \
{ .num = _num, .letter = _let }
struct letter letters[] = {
LET(90,"A"),
LET(80,"B"),
LET(70,"C"),
LET(60,"D"),
LET(0,"F"),
LET(0,NULL)
};
#define SMAX 5 // maximum number of students
// chkall -- check entire array for duplicates
int
chkall(const struct stud *s,int smax)
{
int i;
int j;
int dup = 0;
for (i = 0; i < (smax - 1); i++) {
for (j = i + 1; j < smax; j++) {
if (strcmp(s[i].nam, s[j].nam) == 0) {
printf("Error. Duplicate name detected -- %s\n",s[j].nam);
dup += 1;
}
}
}
return dup;
}
// chkone -- check a given entry for duplicate (as they are added)
int
chkone(const struct stud *s,int i)
{
int j;
int dup = 0;
for (j = 0; j < i; j++) {
if (strcmp(s[i].nam, s[j].nam) == 0) {
printf("Error. Duplicate name detected -- %s\n",s[j].nam);
dup += 1;
}
}
return dup;
}
// prompt_string -- prompt user for a string
char *
prompt_string(const char *what,int i,char *buf,size_t siz)
{
static int tty = -1;
// decide if our input is tty or file
if (tty < 0) {
struct winsize ws;
tty = ioctl(0,TIOCGWINSZ,&ws);
tty = (tty >= 0);
}
printf("Enter the %s of student #%d: ", what, i + 1);
fflush(stdout);
char *cp = fgets(buf,siz,stdin);
do {
// handle EOF
if (cp == NULL)
break;
buf[strcspn(buf,"\n")] = 0;
// echo the data if input is _not_ a tty
if (! tty)
printf("%s\n",buf);
} while (0);
return cp;
}
// prompt_number -- prompt user for a number
long long
prompt_number(const char *what,int i)
{
char *cp;
char buf[100];
long long val;
while (1) {
cp = prompt_string(what,i,buf,sizeof(buf));
// handle EOF
if (cp == NULL) {
val = -1;
break;
}
// decode the number
val = strtoll(buf,&cp,10);
if (*cp == 0)
break;
printf("invalid number syntax -- '%s'\n",cp);
}
return val;
}
int
main(void)
{
struct stud s[SMAX];
int i;
for (i = 0; i < SMAX; i++) {
while (1) {
prompt_string("name",i,s[i].nam,sizeof(s[i].nam));
if (! chkone(s,i))
break;
}
s[i].num = prompt_number("number grade",i);
}
// recheck all entries
// this will _never_ report a duplicate because of the chkone above
chkall(s,SMAX);
for (i = 0; i < SMAX; i++) {
for (struct letter *let = letters; let->letter != NULL; ++let) {
if (s[i].num >= let->num) {
strcpy(s[i].letter,let->letter);
break;
}
}
}
for (i = 0; i < SMAX; i++)
printf("%s has a %s\n", s[i].nam, s[i].letter);
return 0;
}

Write data in files from array of structures using pointers

I am trying to rewrite text in files, changing first line by +1(that holds number of struct saved in igraci.txt) This part is working fine. Then rewrite all text that was there before(This is also working fine) and in the end add 2 new lines in text. Problem is in the last code i wrote here
These are some global variables that I am having problem with and strcture
int RijeciBroj = 0;
int IgraciBroj = 0;
typedef struct Igrac
{
char ime[20];
int brojPoena;
};
This is method for allocating memmory for structures having in mind that one strcture is going to be added
struct Igrac* napraviProstor(int n) {
IgraciBroj = n; //here I try to give global new value
printf("U NAPRAVI PROSTOR : %d", IgraciBroj); // Here i get -9282928
return (struct Igrac*) malloc((n + 1) * sizeof(struct Igrac));
}
This is method that is reading text from file and storing it in allocated memory
void ucitajIgrace(struct Igrac *arr) {
static const char filename[] = "igraci.txt";
FILE *file;
file = fopen(filename, "r");
if (file != NULL)
{
char line[20];
int n;
fscanf(file, "%d", &n);
int i = -1;
int k = 0;
fgets(line, 20, file);
while (fgets(line, 20, file) != NULL) /* read a line */
{
line[strcspn(line, "\n")] = '\0';
i++;
if (i == 0) {
strcpy((arr + k)->ime, line);
}
if (i == 1) {
(arr + k)->brojPoena = atol(line);
k++;
i = -1;
}
}
printf("Igraca: %d", IgraciBroj); //here i get -9892827280
fclose(file);
}
else
{
perror(filename);
}
}
Main method
int main()
{
int o;
Igrac *igr;
FILE *file1;
file1 = fopen("igraci.txt", "r");
if (file1 != NULL)
{
char line[20];
fscanf(file1, "%d", &o); //first line is number of structs
igr = napraviProstor(o);
ucitajIgrace(igr);
}
pocniIgru(rijeci,igr); //ignore rijeci that is another array that is working perfect and has nothing to do with my problem
return 0;
}
This is method where I have problem
void pocniIgru(char** rijeci, struct Igrac *igraci) {
int dobijeni[5] = {}; //array that is saving random numbers so they don't repeat
int brojac1 = 0; //used for index of dobijeni[5]
char srpska[30]; // for user input
char ime[20]; //for users name that we are going to store in igraci.txt
int poeni = 0; //number of points
bool moze; //boolean for loop control
printf("Pocinje igra\n");
printf("\n\n\n\n");
int pitanje; // for random number that we are going to get
for (int i = 0; i < 5; i++) {
moze = true;
LOOP:do {
srand(time(NULL));
pitanje = rand() % RijeciBroj-1; //random number between 0 - global variable here global variable is working fine!
if (pitanje % 2 != 0) {
pitanje++; // I need even number and 0 is accepted
}
for (int k = 0; k < 5; k++) {
if (dobijeni[k] == pitanje) { //checking if we arleay had that number
goto LOOP; // goto LOOP if we had that number so we pick another
}
}
dobijeni[brojac1] = pitanje; //storing that number in loop for later check so it won't repeat
moze = false; // do-while stops
brojac1++;
} while (moze);
printf("Engleska rijec je: %s", rijeci[pitanje]); //get word from array
printf("Unesite rijec na srpskom jeziku: ");
scanf("%30s", srpska); //user input for comparing
strtok(rijeci[pitanje + 1], "\n"); //we need to remove newline
if (strcmp(rijeci[pitanje+1], srpska) == 0) { //cheking if next word is same with user input
poeni += 2;
printf("Tacno! Vas broj peona je %d\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", poeni);
}
else {
poeni -= 1;
if (brojac != 5) {
printf("Greska! Vas broj peona je %d\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", poeni);
}
}
}
printf("Ukupan broj poena je: %d\n", poeni);
printf("Unesite svoje ime: "); //Enter your name
scanf("%s", ime); //get name
if (strcmp(ime, "")) { //check if it's empty
IgraciBroj += 1; //global variable +1 for rewriting in file
strcpy((igraci + IgraciBroj)->ime, ime); //save name in char* struct in last place that is empty
(igraci + IgraciBroj)->brojPoena = poeni; //save points in char* struct in last place that is empty
printf("%s osvojili ste %d poena", (igraci + IgraciBroj)->ime, (igraci + IgraciBroj)->brojPoena); //Here i get normal result and name
FILE *file1;
file1 = fopen("igraci.txt", "w");
if (file1 != NULL)
{
fprintf(file1, "%d\n", IgraciBroj);
for (int broj = 0; broj < IgraciBroj; broj++) {
fprintf(file1, "%s\n", (igraci + broj)->ime); //Problem !! I get some lines before name in file example(----------Name)
fprintf(file1, "%d\n", (igraci + broj)->brojPoena); //Problem !! I get some number like -9899887
}
}
}

junk output in the array of structs

This is my project in the sortstudents() function I try to read from file the data is on one row or one line contentiously when I try to print the array I got junk data
this is example about how data look like in the file (2 records):
1 mohamed talaat €#A
2 ahmed mohamed #A
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <stdlib.h>
#include <windows.h>
///////////////////////////////////////////////////////////////////////////
struct student
{
char id[5];
char name[30];
int term;
float gpa;
char grade;
};
struct student stu;
typedef struct student stud;
//////////////////////////////////////////////////////////////////////////
//set the cordinate to 0, 0 (top-left corner of window)
//<windows.h> is needed
COORD coord = {0,0};
//////////////////////////////////////////////////////////////////////////
//need cordinate struct to use it
//gotoxy to set coordinate x,y
void gotoxy(int x, int y)
{
//X and Y coordinates
coord.X = x; coord.Y = y;
// ew3a tensa Microsoft
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
//////////////////////////////////////////////////////////////////////////
//print regtangle shape Ascii table www.asciitable.com
// window width = 80 character window hight = 25 character
void drawRectangle()
{
int i, j;
//print the corner rear top left
gotoxy(0,0);
printf("%c",201);
// print 78 line shape = starts from rear top left ended at the top rear right
for(i = 1; i < 78; i++)
{
gotoxy(i, 0);
printf("%c",205);
}
//print the corner rear top right
gotoxy(78,0);
printf("%c",187);
//print the corner rear right side with width = 25
for(i = 1; i < 25; i++)
{
gotoxy(78, i);
//print T-shape at width 6 and after 6 proceed until 25 printing right side
if(i == 6)
{
printf("%c",185);
}
else
{
printf("%c",186);
}
}
//print the corner rear bottom right
gotoxy(78, 25);
printf("%c",188);
// -i- already = 78
// print bottom side pf the regtangle
for(i = 77; i > 0; i--)
{
gotoxy(i,25);
// print T-shape at width 35 and after that proceed until 78 printing rgt base side
if(i == 35)
{
printf("%c",202);
}
else
{
printf("%c",205);
}
}
//print the corner rear bottom left
gotoxy(0,25);
printf("%c",200);
// print T-shape at width 6 and after 6 proceed until 25 printing left side
for(i = 24; i > 0; i--)
{
gotoxy(0,i);
if(i == 6)
{
printf("%c",204);
}
else
{
printf("%c",186);
}
}
// print T-shape at width 36 and connect left side to right side
for(i = 1; i < 78; i++)
{
gotoxy(i,6);
if(i == 35)
{
printf("%c",203);
}
else
{
printf("%c",205);
}
}
// connect middle T-shape at the middle of the regtangle to the base
for(i = 7; i < 25; i++)
{
gotoxy(35,i);
printf("%c",186);
}
}
//////////////////////////////////////////////////////////////////////////
// Build Program window interface using functions --drawRectangle
// with color 1 = Blue & Font color 7 = White
void swindow()
{
int i;
drawRectangle();
gotoxy(28,1);
system("color 17");
printf("STUDENT GRADE SYSTEM");
gotoxy(28,2);
for(i=1;i<21;i++)
{
printf("%c",205);
}
gotoxy(15,3);
printf("College of Computing and Information Technology");
gotoxy(10,4);
printf(" ");
gotoxy(10,5);
printf("Arab Academy for Science, Technology & Maritime Transport");
gotoxy(25,24);
}
//////////////////////////////////////////////////////////////////////////
void print_heading(const char st[])
{
gotoxy(50,8);
printf("%s",st);
}
//////////////////////////////////////////////////////////////////////////
void clearWindow()
{
int i,j;
for(i = 37; i < 78; i++)
{
for(j = 7; j < 25; j++)
{
gotoxy(i,j);
printf(" ");
}
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void add()
{
clearWindow();
print_heading("Add Record");
int print = 37;
char ans;
int i;
FILE *fp;
fp = fopen("record.txt","ab+");
if(fp == NULL)
{
MessageBox(0,"Error in Opening file\nMake sure your file is not write protected","Warning",0);
}
else
{
fflush(stdin);
//here i can Add Records ...
////////////////////////////////////////////////////////////////////////////////
gotoxy(print,10);printf("ID: ");gets(stu.id);
gotoxy(print,12);printf("Name: ");gets(stu.name);
gotoxy(print,14);printf("Term: ");scanf("%d",&stu.term);
gotoxy(print,16);printf("Score % : ");scanf("%f",&stu.gpa);
if (stu.gpa>=3.40)
{
stu.grade='A';
}
else {
if (stu.gpa>=2.80)
{stu.grade='B';}
else
{
if (stu.gpa>=2.20)
{stu.grade='C';}
else
{
if (stu.gpa>=2.00)
{stu.grade='D';}
else
{stu.grade='F';}
}
}
}
gotoxy(print,18);printf("GPA: %c",stu.grade);printf("\n");
gotoxy(print,20);printf("Press(Y) to Save (N) for Cancel... ");//scanf("%c",&ans);
ans = getche();
if (ans=='y' || ans=='Y')
{
fwrite(&stu, sizeof(stu), 1, fp);
gotoxy(40,22); printf("The record is sucessfully added");
}
else
{
gotoxy(40,22); printf("Entry process cancelled");
}
}
fclose(fp);
}
//////////////////////////////////////////////////////////////////////////
void search(){
clearWindow();
print_heading("Search Record");
char s_id[5];
int isFound = 0;
gotoxy(37,10);
printf("Enter ID to Search: ");
fflush(stdin);
gets(s_id);
//Read the record file from File
FILE *fp;
fp = fopen("record.txt","ab+");
while(fread(&stu,sizeof(stu),1,fp) == 1)
{
if(strcmp(s_id,stu.id) == 0)
{
isFound = 1;
break;
}
}
if(isFound == 1){
gotoxy(37,12);printf("The record is Found");
gotoxy(37,13);printf("--------------------");
gotoxy(37,14);printf("ID: %s",stu.id);
gotoxy(37,16);printf("Name: %s",stu.name);
gotoxy(37,18);printf("Term: %d",stu.term);
gotoxy(37,20);printf("Score %: %0.1f",stu.gpa);
gotoxy(37,22);printf("GPA: %c",stu.grade);
}else
{
gotoxy(37,12);printf("Sory, No record found in the database");
}
fclose(fp);
}
//////////////////////////////////////////////////////////////////////////
void sortstudents()
{
clearWindow();
FILE *fp;
fp = fopen("record.txt","r");
//////// detect number of characters ////////
char nextChar = getc(fp);
int numCharacters = 0;
while (nextChar != EOF)
{
//Do something else, like collect statistics
numCharacters++;
nextChar = getc(fp);
}
//////// detect number of characters ////////
int chunck = numCharacters/sizeof(stu);
//stud *arr = (stud *)malloc(chunck);
stud starray[25];
int d;
int numStudents = 0;
while( fscanf(fp,"%s%s%d%f%c",stu.id,stu.name,&stu.term,&stu.gpa,&stu.grade) > 0)
{
starray[numStudents++] = stu;
}
gotoxy(37,12);printf("The record is Found");
gotoxy(37,13);printf("--------------------");
gotoxy(37,14);printf("ID: %s",starray[0].id);
gotoxy(37,16);printf("Name: %s",starray[0].name);
gotoxy(37,18);printf("Term: %d",starray[0].term);
gotoxy(37,20);printf("Score %: %0.1f",starray[0].gpa);
gotoxy(37,22);printf("GPA: %c",starray[0].grade);
/*"ID: %s",stu.id);
"Name: %s",stu.name);
"Term: %d",stu.term);
Score %: %0.1f",stu.gpa);
"GPA: %c",stu.grade);*/
fclose(fp);
}
//////////////////////////////////////////////////////////////////////////
void menu(){
int choice;
int x = 2;
while(1)
{
gotoxy(x,10);
printf("1. Add Student");
gotoxy(x,12);
printf("2. Search Student");
gotoxy(x,14);
printf("3. Statistics");
gotoxy(x,16);
printf("4. Close");
gotoxy(x,20);
printf("Please enter your choice :");
scanf("%d",&choice);
switch(choice)
{
case 1:
add();
break;
case 2:
search();
break;
case 3:
sortstudents();
break;
case 4:
exit(0);
break;
default:
break;
}
}
}
//////////////////////////////////////////////////////////////////////////
int main()
{
// draw entry window
//drawRectangle();
swindow();
menu();
//clearWindow();
system("PAUSE");
return 0;
}
In the sortStudents you have a loop in the beginning that will read all characters in the file. Then you attempt to read the files as a kind of records. This usage of fscanf will return EOF as you are attempting to read beyond the end of the file.
And even when you don't read any records into your starray array, you still print values from starray[0] which will be all uninitialized (and therefore contain indeterminate (e.g. seemingly random) values).

Program errors due to strcmp and strcpy in C

No matter how I edit my program there seems to be overflow errors and mismatching type errors. Can someone help me to make this run without errors.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int choice;
int i;
int j;
char type;
int amount;
int don_count = 0;
int req_count = 0;
int flag;
char donations_inv_type[100][20];
int donations_amount[100];
char requests_inv_type[100][20];
int req_amount[100];
printf("Welcome to the Food Bank Program\n\n 1. Add a donation\n 2. Add a request\n 3. Fulfill a request\n 4. Print status report\n 5. Exit\n\nEnter your choice: ");
scanf("%d", &choice);
while (choice != 5) {
if (choice == 1) {
printf("\nEnter inventory type: ");
scanf("%s", &type);
printf("Enter the amount: ");
scanf("%d", &amount);
printf("\nDonation Added!\n\n");
flag = -99;
for (i = 0; i < don_count; i++) {
if (strcmp(donations_inv_type[i], type) == 0)
flag = i;
}
if (flag == -99) {
strcpy(donations_inv_type[i], type);
donations_amount[i] = amount;
don_count++;
}
else
donations_amount[flag] += amount;
printf("Donation Added!\n");
printf("Press any key to continue . . .\n\n");
}
else if (choice == 2) {
printf("\nEnter inventory type: ");
scanf("%s", &type);
printf("Enter the amount: ");
scanf("%d", &amount);
strcpy(requests_inv_type[req_count], type);
req_amount[req_count] = amount;
req_count++;
}
else if (choice == 3) {
printf("\n\n-------- Fulfilling Requests--------");
flag = -99;
for (i = 0; i < don_count; i++) {
if (strcmp(donations_inv_type[i], requests_inv_type[0]) == 0)
flag = i;
}
if (flag == -99)
printf("Cannot be Fulfilled\n\n");
else if (donations_amount[flag] > req_amount[0]) {
donations_amount[flag] -= req_amount[0];
printf("Request Fulfilled");
req_amount[0] = 0;
}
else if (donations_amount[flag] == req_amount[0]) {
printf("Request Fulfilled");
for (i = flag; i < don_count; i++) {
strcpy(donations_inv_type[i], donations_inv_type[i + 1]);
strcpy(donations_amount[i], donations_amount[i + 1]);
}
don_count--;
for (i = flag; i < req_count; i++) {
strcpy(requests_inv_type[i], requests_inv_type[i + 1]);
strcpy(req_amount[i], req_amount[i + 1]);
}
req_count--;
}
else if (donations_amount[flag] < req_amount[0]) {
printf("Partially Fulfilled");
req_amount[0] -= donations_amount[flag];
for (i = flag; i < don_count; i++) {
strcpy(donations_inv_type[i], donations_inv_type[i + 1]);
strcpy(donations_amount[i], donations_amount[i + 1]);
don_count--;
}
}
}
else if (choice == 4) {
printf("Printing the Donations Table\n\n");
for (i = 0; i < don_count; i++) {
printf("%s %d", donations_inv_type[i], donations_amount[i]);
}
printf("Printing the Requests Table\n\n");
for (i = 0; i < req_count; i++) {
printf("%s %d", requests_inv_type[i], req_amount[i]);
}
}
printf("Welcome to the Food Bank Program\n\n 1. Add a donation\n 2. Add a request\n 3. Fulfill a request\n 4. Print status report\n 5. Exit\n\nEnter your choice: ");
}
}
Any help is greatly appreciated and I would love an explanation as to what I did wrong so that I can learn and not make the same mistakes next time.
Declare type as character array.
char type[50];
Remove & in scanf(). You should not use & while reading string.
scanf("%s", &type); ==> scanf("%s", type);
^
Here you want to copy integers not strings
strcpy(donations_amount[i], donations_amount[i + 1]);
strcpy(req_amount[i], req_amount[i + 1]);
Modify like this
donations_amount[i]=donations_amount[i + 1];
req_amount[i]= req_amount[i + 1];
Instead of char type you need char type[100]
Error in your code:
if (strcmp(donations_inv_type[i], type) == 0)
// ^^^^ should be char*
Note: Functions strcmp() and strcpy() should be passed \0 nul-terminated array of char (or say string).
Your scanf should look like scanf("%s", type);

Task using .txt file and phonebook program in C

Below is my code for a phonebook program in C. I'm having trouble modifying it. I need to modify it so that after adding entries to the phonebook , the contents will be written to a .txt file. After deleting an entry I need the contents to be written to the same .txt file and have the entire contents printed. Am I supposed to use the fopen () function? I'm a beginner...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Phonebook_Contacts
{
char FirstName[20];
char LastName[20];
char PhoneNumber[20];
} phone;
void AddEntry(phone * );
void DeleteEntry(phone * );
void PrintEntry(phone * );
void SearchForNumber(phone * );
void RandomName(phone * );
void DeleteAll(phone * );
void FreeContacts (phone * );
int counter = 0;
char FileName[256];
FILE *pRead;
FILE *pWrite;
int main (void)
{
phone *phonebook;
phonebook = (phone*) malloc(sizeof(phone)*100);
int iSelection = 0;
if (phonebook == NULL)
{
printf("Out of Memory. The program will now exit");
return 1;
}
else {}
do
{
printf("\n\t\t\tPhonebook Menu");
printf("\n\n\t(1)\tAdd Friend");
printf("\n\t(2)\tDelete Friend");
printf("\n\t(3)\tDisplay Phonebook Entries");
printf("\n\t(4)\tSearch for Phone Number");
printf("\n\t(5)\tFind a Random Friend");
printf("\n\t(6)\tDelete All Entries");
printf("\n\t(7)\tExit Phonebook");
printf("\n\nWhat would you like to do? ");
scanf("%d", &iSelection);
if (iSelection == 1)
{
AddEntry(phonebook);
}
if (iSelection == 2)
{
DeleteEntry(phonebook);
}
if (iSelection == 3)
{
PrintEntry(phonebook);
}
if (iSelection == 4)
{
SearchForNumber(phonebook);
}
if (iSelection == 5)
{
RandomName(phonebook);
}
if (iSelection == 6)
{
DeleteAll(phonebook);
}
if (iSelection == 7)
{
printf("\nYou have chosen to exit the Phonebook.\n");
system("pause");
FreeContacts(phonebook);
return 0;
}
} while (iSelection <= 9);
}
void AddEntry (phone * phonebook)
{
pWrite = fopen("phonebook_contacts.dat", "a");
if ( pWrite == NULL )
{
perror("The following error occurred ");
exit(EXIT_FAILURE);
}
else
{
counter++;
realloc(phonebook, sizeof(phone));
printf("\nFirst Name: ");
scanf("%s", phonebook[counter-1].FirstName);
printf("Last Name: ");
scanf("%s", phonebook[counter-1].LastName);
printf("Phone Number (XXX-XXX-XXXX): ");
scanf("%s", phonebook[counter-1].PhoneNumber);
printf("\n\tFriend successfully added to Phonebook\n");
fprintf(pWrite, "%s\t%s\t%s\n", phonebook[counter-1].FirstName, phonebook[counter-1].LastName, phonebook[counter-1].PhoneNumber);
fclose(pWrite);
}
}
void DeleteEntry (phone * phonebook)
{
int x = 0;
int i = 0;
char deleteFirstName[20]; //
char deleteLastName[20];
printf("\nFirst name: ");
scanf("%s", deleteFirstName);
printf("Last name: ");
scanf("%s", deleteLastName);
for (x = 0; x < counter; x++)
{
if (strcmp(deleteFirstName, phonebook[x].FirstName) == 0)
{
if (strcmp(deleteLastName, phonebook[x].LastName) == 0)
{
for ( i = x; i < counter - 1; i++ )
{
strcpy(phonebook[i].FirstName, phonebook[i+1].FirstName);
strcpy(phonebook[i].LastName, phonebook[i+1].LastName);
strcpy(phonebook[i].PhoneNumber, phonebook[i+1].PhoneNumber);
}
printf("Record deleted from the phonebook.\n\n");
--counter;
return;
}
}
}
printf("That contact was not found, please try again.");
}
void PrintEntry (phone * phonebook)
{
int x = 0;
printf("\nPhonebook Entries:\n\n ");
pRead = fopen("phonebook_contacts.dat", "r");
if ( pRead == NULL)
{
perror("The following error occurred: ");
exit(EXIT_FAILURE);
}
else
{
for( x = 0; x < counter; x++)
{
printf("\n(%d)\n", x+1);
printf("Name: %s %s\n", phonebook[x].FirstName, phonebook[x].LastName);
printf("Number: %s\n", phonebook[x].PhoneNumber);
}
}
fclose(pRead);
}
void SortByFirstName (phone * phonebook)
{
int i = 0;
int x = 0;
int swap;
int TempCounter = counter;
phone Temp;
do
{
swap = 0;
for(i = 1; i < TempCounter; i++)
{
if(strcmp(phonebook[i-1].FirstName, phonebook[i].FirstName) > 0)
{
Temp = phonebook[i];
phonebook[i] = phonebook[i-1];
phonebook[i-1] = Temp;
strcpy(Temp.FirstName, phonebook[i].FirstName);
strcpy(Temp.LastName, phonebook[i].LastName);
strcpy(Temp.PhoneNumber, phonebook[i].PhoneNumber);
swap = 1;
}
}
TempCounter--;
} while (swap);
printf("\nYour friends in Alphabetical Order by First Name:\n\n");
for( x = 0; x < counter; x++ )
{
printf("\n(%d)\n", x+1);
printf("Name: %s %s\n", phonebook[x].FirstName, phonebook[x].LastName);
printf("Number: %s\n", phonebook[x].PhoneNumber);
}
}
void SortByLastName (phone * phonebook)
{
int i = 0;
int x = 0;
int swap;
int TempCounter = counter;
phone Temp;
do
{
swap = 0;
for(i = 1; i < TempCounter; i++)
{
if(strcmp(phonebook[i-1].LastName, phonebook[i].LastName) > 0)
{
Temp = phonebook[i];
phonebook[i] = phonebook[i-1];
phonebook[i-1] = Temp;
strcpy(Temp.FirstName, phonebook[i].FirstName);
strcpy(Temp.LastName, phonebook[i].LastName);
strcpy(Temp.PhoneNumber, phonebook[i].PhoneNumber);
swap = 1;
}
}
TempCounter--;
} while (swap);
printf("\nYour friends in Alphabetical Order by First Name:\n\n");
for( x = 0; x < counter; x++ )
{
printf("\n(%d)\n", x+1);
printf("Name: %s %s\n", phonebook[x].FirstName, phonebook[x].LastName);
printf("Number: %s\n", phonebook[x].PhoneNumber);
}
}
void SearchForNumber (phone * phonebook)
{
int x = 0;
char TempFirstName[20];
char TempLastName[20];
printf("\nPlease type the name of the friend you wish to find a number for.");
printf("\n\nFirst Name: ");
scanf("%s", TempFirstName);
printf("Last Name: ");
scanf("%s", TempLastName);
for (x = 0; x < counter; x++)
{
if (strcmp(TempFirstName, phonebook[x].FirstName) == 0)
{
if (strcmp(TempLastName, phonebook[x].LastName) == 0)
{
printf("\n%s %s's phone number is %s\n", phonebook[x].FirstName, phonebook[x].LastName, phonebook[x].PhoneNumber);
}
}
}
}
void RandomName (phone * phonebook)
{
int iRandom = 0;
srand(time(NULL));
iRandom = rand() % counter;
int x = iRandom;
printf("\nYour random friend is: %s %s\n", phonebook[x].FirstName, phonebook[x].LastName);
printf("Their phone number is: %s\n", phonebook[x].PhoneNumber);
}
void DeleteAll (phone * phonebook)
{
int x = 0;
char nullStr[20] = {'\0'};
for ( x = 0; x < counter; x++ )
{
strcpy(phonebook[x].FirstName, nullStr);
strcpy(phonebook[x].LastName, nullStr);
strcpy(phonebook[x].PhoneNumber, nullStr);
--counter;
}
printf("All Contacts have been deleted.\n");
}
void FreeContacts (phone * phonebook)
{
--counter;
for ( ; counter > 0; --counter)
{
free(phonebook[counter].FirstName);
free(phonebook[counter].LastName);
free(phonebook[counter].PhoneNumber);
free(phonebook);
counter = 0;
return;
}
}
Are you sure you want to be doing "realloc(phonebook, sizeof(phone));" in your AddEntry() function? That's almost certainly not doing what you think it is.
Pretty much all the code you need is already here in this program. I would recommend you start by looking up tutorials or reading the file I/O chapter of books. An additional resource for you is the man pages for the C functions. If you're on a *NIX system you can type man fopen or you can type that into Google to get the same results on a windows system.
Here's the man page for fopen(). As you can see there are two parameters, the name of the file you want to open and the mode.
Clearly there are options to open a file for writing there as well as appending a file that already exists.
You mentioned a requirement to write to a .txt file, in your code you're opening a .dat file phonebook_contacts.dat is this the file you were talking about?
One of the easiest options is to read the entire file into memory then change it there and write it back to the file (over write the existing file), but it's not efficent as you'll have to loop over each existing element and copy them into you phonebook variable. You might want to check with your instructor to see if this is an acceptable solution. Something like:
while( more to read){
read fname line
strcpy(phonebook[i].first_name, fname)
read lname line
strcpy(phonebook[i].last_name, fname)
read num line
strcpy(phonebook[i].number, num)
increment i
}

Resources