/****************************************************PROJECT OVERVIEW*************************************************** ***************************************************WHITE MOVIE RENTAL APPLICATION*************************************************** White Movie Rental application aims to enable users to record film rental transactions in an easy and secure way. The program includes some special features. One of them is that both administrator and user support is integrated into the programme. The administrator user has the ability to add films. Apart from that, the program has features such as film rental, film return, user registration, rental history, user rating, adding comments and VIP membership. General Features of the Application: 1.Login: It is the authentication phase. A comparison is made with the information previously received from the user and after the information received is compatible, the user becomes the active user.(currentUserIndex) 2.Register: The programme asks the user for a user name and checks if there is a user with the same name in the system. Then the new user is added and the new user is saved in files such as username.txt, password.txt, roles.txt. 3.Authorization: In this phase the program checks what the administrator and normal users can do. The administrator (1) has the ability to add films, while the normal user (0) can rent or return films. 4.Storing User Data: The user's information is saved in .txt files and read operation is performed. usernames.txt -> usernames passwords.txt -> passwords roles.txt -> is admin or not? (1 = admin, 0 = normal user) 5. Security : For security reasons the programme does not accept empty user names. It won't accept the password. The same user name cannot be used and the password is verified. 6.Comment Feature: Add Comment Function (addComment) This function receives a comment from the user about the selected film and transfers this comment to the ‘comment.txt’ file. The user is asked if he/she wants to comment. If the user wants to comment, a comment of maximum 20 words is received. This comment is then saved in the comment.txt file along with the film title and username. Update Menu: Addition of ‘Show Comments’ Option This is the section where the ‘Show Comments’ option is added to the main menu. When the user selects option 5 from the menu, the showComments() function is called to see the comments and the user sees the comments. Adding Comments After the Film Returns In this section, when the user returns a film, it is allowed to add a comment to that film by calling the addComment function directly. In this way, feedback can be given immediately about the film the user is watching. Show Comments Function This function reads and displays all saved comments in the comment.txt file. If there are no comments in the file, or if the file does not exist, the user is notified that there are no comments. If the file is opened successfully, it reads each line and prints it to the screen. This allows users to view comments that have already been made. Related code: * showComments() reads from comment.txt and prints the comments. * It uses fopen() to access the file and fgets() to read it line by line. * Includes error handling if the file cannot be opened. * Closes the file using fclose() after reading 7.VIP Member Features VIP members who register with this feature get the right to rent films longer than other users. When the user enters the system with the username 'vipuser', he/she is accepted as a VIP user. during the registration phase, it is also processed as a VIP user. In other words, the user must be registered in the system with the name 'vipuser'. When renting a VIP member film, the programme rental period must be entered and this period is maximum 60 days for VIP members and maximum 30 days for regular members. When users exceed this period, the system gives an error message *******************************************************************************************************/ /****************************************************GROUP MEMBERS and ROLES*************************************************** 1-)Team Lead(1): BERK MUAMMER KUZU --> *Main code design, system desing, distribution of roles, fix code, code architectre. 2-)Vice Lead (2): MUHAMMED BUCAK --> *Film rental algorithm. *When a user returns a film, get a score, save the score to a file, average the scores and open a new file *Fix deficiencies in the main code. 3-)Team Member: MUSTAFA BERKAY AYDIN --> *Scoring and averaging 4-)Team Member: HATİCE NUR UYANIK --> *Function to Add Comments *Adding Comment Adding to Movie Return Function 5-)Team Member: YAĞMUR MELİSA BAKIR --> *Writing a project description file. *Function to Add Comments *Group members & roles description 6-)Team Member: MURAT DİNÇEL --> *Function to add comments *Add “Show the Comments” option to menü *Solftware Architecture (brief) 7-)Team Member: MUSTAFA ENES ÖZTÜRK --> *Adding VIP member role *Adding VIP subscription system *Creating limitatiton of maximum film number for both VIP (5) and normal member(2) 8-)Team Member: MOHAMED ALIE JALLOH --> 9-)Team Member: TAIMA ADIL ABDALLA --> *Function to Show Comments 10-)Team Member: QUBLAN ALI MOHAMMED NOOR ABBAS --> *******************************************************************************************************/ /****************************************************Code Orginality*************************************************** *The Triple Role System It has three user roles: Normal, Admin and VIP. *The movie's access, addition and rental limits are set by its role. *Moving from a subscription to a VIP membership. *Regular users can choose the 'Subscribe VIP' option from the menu to become a VIP. To do this, they just need to enter a card number in the following format: XXXX XXXX XXXX XXXX. There is a limit on how long you can rent it for. *Members can have a maximum of two at any one time. If you are a VIP member, you can rent five movies. For the admin, there are practically no limits. *Dynamic Menu Flow *There are different menu options depending on the user's role: "Add Movie" is for the administrator, "Subscribe VIP" is for the normal user, and "View Rental History" is for the VIP user. This is a loop that is specific to the user who is logged in. *Managing your data so that it is always there when you need it. *Movies are stored in movies.txt, users in users.txt, passwords in passwords.txt, rental history in rental_history.txt, ratings in rate.txt, averages in average.txt, comments in comments.txt. *Each cycle loads files and then saves them after they have been processed. *Recording with timestamps *Transactions where something is rented and then returned are logged in a file called 'rental_history.txt'. This file also includes the date and time information. *You can see which movies you have rented and returned in the past. *How to calculate scores and the average. You can get between 1 and 5 points. *The average score for each movie is calculated using the calcAverage() function and added to the list as "⭐x.xx". The text always stays the same, and the average.txt file is used to store this information. *A system for commenting that uses 20 words. You can add comments after you have returned. *The maximum limit is 20 words, and the counting is based on spaces. *Comments are stored in a file called 'comments.txt'. Each comment is in a format of 'user;movie;comment'. You can read the comments here. *All the functions (like registration, login, adding movies, renting, refunds, points, comments, VIP, etc.) are managed with one EXE/compilation file. *******************************************************************************************************/ /**************************************************** EVALUATION *************************************************** 1-)Vice Lead (2): MUHAMMED BUCAK --> 100 2-)Team Member: MUSTAFA BERKAY AYDIN --> 100 3-)Team Member: HATİCE NUR UYANIK --> 100 4-)Team Member: YAĞMUR MELİSA BAKIR --> 100 5-)Team Member: MURAT DİNÇEL --> 100 6-)Team Member: MUSTAFA ENES ÖZTÜRK --> 100 7-)Team Member: MOHAMED ALIE JALLOH --> 0 8-)Team Member: TAIMA ADIL ABDALLA --> 100 9-)Team Member: QUBLAN ALI MOHAMMED NOOR ABBAS --> 40 *******************************************************************************************************/ /**************************************************** CODE ***************************************************/ /* ***Movie Rental Console Application*** 1- Team Lead(1): Berk Muammer Kuzu 2- Vice Lead(2): Muhammed Bucak 220202027 3- Team Member: Mustafa Enes Öztürk 220202405 4- Team Member: Hatice Nur Uyanık 230201006 5- Team Member: Mustafa Berkay Aydın 220202007 6- Team Member: Yağmur Melisa Bakır 230201049 7- Team Member: Murat Dinçel 230201064 8- Team Member: Taima Adil Abdalla 230202913 9- Team Member: 10- Team Member: */ #include #include #include #include #include // isdigit için #define MAX_MOVIES 100 #define MAX_USERS 999 #define MAX_NAME 35 #define MAX_PASS 30 #define MAX_MOVIE_NAME 60 typedef struct { char title[MAX_MOVIE_NAME]; int isRented; char rentedBy[MAX_NAME]; // HER KULLANICININ NE KİRALADIĞINI ÖZEL KAYDETMEK İÇİN MUHAMMED BUCAK } Movie; typedef struct { char username[MAX_NAME]; char password[MAX_PASS]; int role; // 0 = Normal, 1 = Admin, 2 = VIP } User; Movie movies[MAX_MOVIES]; int movieCount = 0; User users[MAX_USERS]; int userCount = 0; int currentUserIndex = -1; //////////////Function Declarations/////////////// void saveMovies(); void loadMovies(); void loadUsers(); void saveUsers(); int login(); void registerUser(); void addMovie(); void listMovies(); void viewRentalHistory(); void rentMovie(); void returnMovie(); void subscribeVIP(); void showComments(); void menu(); double calcAverage(const char *title); void updateAverage(const char *title); ////////////////////////////////////////////////// int main() { loadMovies(); loadUsers(); int choice, attempts = 0; puts("***********************************************"); puts("********************Welcome********************"); puts("*********///* WHITE MOVIE RENTAL *///**********"); puts("******************APPLICATION******************"); puts("***********************************************"); do { printf("\n**************\n1. Login\n2. Register\n3. Exit\nYour choice: "); scanf("%d", &choice); printf("**************\n\n"); if (choice == 1 && login()) { if (users[currentUserIndex].role == 1) printf("Welcome, Admin %s.\n", users[currentUserIndex].username); else if (users[currentUserIndex].role == 2) printf("Welcome, VIP %s.\n", users[currentUserIndex].username); else printf("*******---\nWelcome, %s. ---\n*******\n", users[currentUserIndex].username); menu(); } else if (choice == 2) { registerUser(); if (login()) menu(); } else if (choice == 3) { return 0; } else { printf("Invalid input.\n"); } attempts++; } while (attempts < 10); // 10 kere art arda bu kısımda hata yaparsan program kapanıyor return 0; } ////////////////////////////////////////////////// // Registration & Login void registerUser() { if (userCount >= MAX_USERS) { printf("User capacity reached.\n"); return; } getchar(); // leftover newline int isUnique = 0, i; while (!isUnique) { printf("New username: "); fgets(users[userCount].username, MAX_NAME, stdin); users[userCount].username[strcspn(users[userCount].username, "\n")] = '\0'; isUnique = 1; for (i = 0; i < userCount; i++) { if (strcmp(users[i].username, users[userCount].username) == 0) { printf("Username already taken. Please choose another.\n"); isUnique = 0; break; } } } printf("Password: "); fgets(users[userCount].password, MAX_PASS, stdin); users[userCount].password[strcspn(users[userCount].password, "\n")] = '\0'; users[userCount].role = 0; // Normal üye userCount++; saveUsers(); printf("Registration successful.\n"); } int login() { char inputUser[MAX_NAME], inputPass[MAX_PASS]; int i, c; while ((c = getchar()) != '\n' && c != EOF); do { printf("Username: "); fgets(inputUser, MAX_NAME, stdin); inputUser[strcspn(inputUser, "\n")] = '\0'; if (!inputUser[0]) printf("Username cannot be empty.\n"); } while (!inputUser[0]); do { printf("Password: "); fgets(inputPass, MAX_PASS, stdin); inputPass[strcspn(inputPass, "\n")] = '\0'; if (!inputPass[0]) printf("Password cannot be empty.\n"); } while (!inputPass[0]); for (i = 0; i < userCount; i++) { if (!strcmp(inputUser, users[i].username) && !strcmp(inputPass, users[i].password)) { printf("Login successful.\n"); currentUserIndex = i; return 1; } } printf("Login failed.\n"); return 0; } void saveUsers() { FILE *f1 = fopen("usernames.txt", "w"); FILE *f2 = fopen("passwords.txt", "w"); FILE *f3 = fopen("roles.txt", "w"); for (int i = 0; i < userCount; i++) { fprintf(f1, "%s\n", users[i].username); fprintf(f2, "%s\n", users[i].password); fprintf(f3, "%d\n", users[i].role); } fclose(f1); fclose(f2); fclose(f3); } void loadUsers() { FILE *f1 = fopen("usernames.txt", "r"); FILE *f2 = fopen("passwords.txt", "r"); FILE *f3 = fopen("roles.txt", "r"); if (!f1 || !f2 || !f3) return; while (fgets(users[userCount].username, MAX_NAME, f1)) { fgets(users[userCount].password, MAX_PASS, f2); users[userCount].username[strcspn(users[userCount].username, "\n")] = '\0'; users[userCount].password[strcspn(users[userCount].password, "\n")] = '\0'; if (fscanf(f3, "%d\n", &users[userCount].role) != 1) break; userCount++; } fclose(f1); fclose(f2); fclose(f3); } ////////////////////////////////////////////////// // Movie load/save (unchanged) /* MUHAMMED BUCAK HANGİ KULLANICININ HANGİ FİLMİ KİRALADIĞINI KULLANICIYA ÖZEL MOVİE DOSYASINA KAYDEDİYOR RETURN İÇİN*/ void saveMovies() { FILE *f = fopen("movies.txt", "w"); if (!f) return; for (int i = 0; i < movieCount; i++) fprintf(f, "%s;%d;%s\n", movies[i].title, movies[i].isRented, movies[i].rentedBy); fclose(f); } void loadMovies() { FILE *f = fopen("movies.txt", "r"); if (!f) return; char line[200]; while (fgets(line, sizeof(line), f)) { char *tok = strtok(line, ";"); strcpy(movies[movieCount].title, tok); tok = strtok(NULL, ";"); movies[movieCount].isRented = atoi(tok); tok = strtok(NULL, "\n"); strcpy(movies[movieCount].rentedBy, tok ? tok : ""); movieCount++; } fclose(f); printf("Movies loaded successfully. Total: %d\n", movieCount); } //////////// Yorum ekleme fonksiyonu Hatice Nur Uyanık 230201006 - Murat Dinçel 230201064 - Yağmur Melisa Bakır 230201049////////////////////////// void addMovie() { if (users[currentUserIndex].role != 1) { printf("Only admins can add movies.\n"); return; } if (movieCount >= MAX_MOVIES) { printf("Movie capacity reached.\n"); return; } int c; while ((c = getchar()) != '\n' && c != EOF); printf("Movie title: "); fgets(movies[movieCount].title, MAX_MOVIE_NAME, stdin); movies[movieCount].title[strcspn(movies[movieCount].title, "\n")] = '\0'; movies[movieCount].isRented = 0; movieCount++; saveMovies(); printf("Movie added.\n"); } void listMovies(void) { printf("\n--- Movie List ---\n"); for (int i = 0; i < movieCount; i++) { double avg = calcAverage(movies[i].title); printf("%d. %s [%s]", i+1, movies[i].title, movies[i].isRented ? "Rented" : "Available"); if (avg >= 0) printf(" | ⭐ %.2f", avg); /* ortalamanın yıldızlı puanla gösterimi*/ else printf(" | (Unrated)"); putchar('\n'); } } void saveRentalHistory(const char* user, const char* title, const char* action) { FILE *f = fopen("rental_history.txt", "a"); if (!f) return; time_t t = time(NULL); struct tm *lt = localtime(&t); char dt[20]; strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", lt); fprintf(f, "%s;%s;%s;%s\n", user, title, action, dt); fclose(f); } void viewRentalHistory() { FILE *f = fopen("rental_history.txt", "r"); if (!f) { printf("No rental history.\n"); return; } char line[300]; printf("\n--- Your Rental History ---\n"); while (fgets(line, sizeof(line), f)) { char u[MAX_NAME], t[MAX_MOVIE_NAME], a[20], dt[20]; sscanf(line, "%[^;];%[^;];%[^;];%[^\n]\n", u, t, a, dt); if (!strcmp(u, users[currentUserIndex].username)) { printf("Movie: %s\nAction: %s\nDate: %s\n\n", t, a, dt); } } fclose(f); } void rentMovie() { // mevcut kiraladığı film sayısını hesapla int rentedCount = 0; for (int i = 0; i < movieCount; i++) { if (movies[i].isRented && strcmp(movies[i].rentedBy, users[currentUserIndex].username) == 0) rentedCount++; } // role’a göre limit int limit = users[currentUserIndex].role == 0 ? 2 : users[currentUserIndex].role == 2 ? 5 : movieCount; if (rentedCount >= limit) { printf("Üzgünüm, kiralama limiti (%d) doldu. Önce iade etmelisin.\n", limit); return; } listMovies(); printf("Enter the number of the movie you want to rent: "); int choice; scanf("%d", &choice); if (choice < 1 || choice > movieCount) { printf("Invalid selection.\n"); return; } if (movies[choice-1].isRented) { printf("Already rented.\n"); return; } int dur; do { printf("Enter rental duration (1-30 days): "); scanf("%d", &dur); } while (dur < 1 || dur > 30); movies[choice-1].isRented = 1; strcpy(movies[choice-1].rentedBy, users[currentUserIndex].username); saveMovies(); saveRentalHistory(users[currentUserIndex].username, movies[choice-1].title, "Rented"); time_t now = time(NULL); struct tm rd = *localtime(&now); printf("\nMovie '%s' rented.\nDate: %02d-%02d-%04d %02d:%02d:%02d\n", movies[choice-1].title, rd.tm_mday, rd.tm_mon+1, rd.tm_year+1900, rd.tm_hour, rd.tm_min, rd.tm_sec); rd.tm_mday += dur; mktime(&rd); printf("Return: %02d-%02d-%04d %02d:%02d:%02d\n\n", rd.tm_mday, rd.tm_mon+1, rd.tm_year+1900, rd.tm_hour, rd.tm_min, rd.tm_sec); } void returnMovie() { printf("\n--- Your Rented Movies ---\n"); int found = 0; for (int i = 0; i < movieCount; i++) { if (movies[i].isRented && strcmp(movies[i].rentedBy, users[currentUserIndex].username) == 0) { printf("%d. %s\n", i+1, movies[i].title); found = 1; } } if (!found) { printf("You have no rented movies.\n"); return; } printf("Enter the number of the movie you want to return: "); int choice; scanf("%d", &choice); if (choice < 1 || choice > movieCount || strcmp(movies[choice-1].rentedBy, users[currentUserIndex].username) != 0) { printf("Invalid selection.\n"); return; } movies[choice-1].isRented = 0; strcpy(movies[choice-1].rentedBy, ""); saveMovies(); saveRentalHistory(users[currentUserIndex].username, movies[choice-1].title, "Returned"); printf("Movie successfully returned.\n"); // Rating int rating; while (1) { printf("\nWould you like to rate the movie? (1-5, 0 to skip): "); scanf("%d", &rating); if (rating == 0) { printf("No rating given.\n"); break; } if (rating >= 1 && rating <= 5) { // write rating FILE *f = fopen("rate.txt", "a+"); fclose(f); FILE *in = fopen("rate.txt","r"); FILE *out = fopen("temp_rate.txt","w"); char line[200]; int updated = 0; while (fgets(line, sizeof(line), in)) { char u[MAX_NAME], t[MAX_MOVIE_NAME]; int r; sscanf(line, "%[^;];%[^;];%d\n", u, t, &r); if (!strcmp(u, users[currentUserIndex].username) && !strcmp(t, movies[choice-1].title)) { fprintf(out, "%s;%s;%d\n", users[currentUserIndex].username, movies[choice-1].title, rating); updated = 1; } else { fputs(line, out); } } if (!updated) fprintf(out, "%s;%s;%d\n", users[currentUserIndex].username, movies[choice-1].title, rating); fclose(in); fclose(out); remove("rate.txt"); rename("temp_rate.txt","rate.txt"); updateAverage(movies[choice-1].title); printf("Rating recorded.\n"); break; } printf("Invalid rating.\n"); } // Comment char yn; do { printf("Would you like to add a comment? (y/n): "); scanf(" %c", &yn); } while (yn!='y' && yn!='n' && yn!='Y' && yn!='N'); if (yn=='y' || yn=='Y') { char comment[256]; int words; while (getchar()!='\n'); // flush do { printf("Enter your comment (max 20 words): "); fgets(comment, sizeof(comment), stdin); comment[strcspn(comment,"\n")] = '\0'; // count words words = 0; char tmp[256]; strcpy(tmp, comment); char *tok = strtok(tmp, " \t"); while (tok) { words++; tok = strtok(NULL, " \t"); } if (words > 20) printf("Too many words (%d). Please limit to 20.\n", words); } while (words > 20); FILE *cf = fopen("comments.txt","a"); if (cf) { fprintf(cf, "%s;%s;%s\n", users[currentUserIndex].username, movies[choice-1].title, comment); fclose(cf); printf("Comment recorded.\n"); } else { printf("Error opening comments file.\n"); } } } /* Enes Öztürk VIP üye-- kredi kartı abonelik sistemi */ void subscribeVIP() { char card[20]; int valid, c; while ((c = getchar()) != '\n' && c != EOF); do { printf("Enter card number (XXXX XXXX XXXX XXXX): "); /* kredi kartı abonelik sistemi, kullanıcı bu formatta girmeli*/ fgets(card, sizeof(card), stdin); card[strcspn(card,"\n")] = '\0'; valid = (strlen(card)==19); for (int i=0; valid && i<19; i++) { if (i==4||i==9||i==14) { if (card[i]!=' ') valid=0; } else { if (!isdigit(card[i])) valid=0; } } if (!valid) printf("Wrong! Please enter your card in this type XXXX XXXX XXXX XXXX .\n"); } while (!valid); users[currentUserIndex].role = 2; saveUsers(); printf("Congrats! Now you are VIP member.\n"); } void showComments() { if (movieCount == 0) { printf("No movie included, and no comment included yet!.\n"); return; } listMovies(); printf("Which movie's comments? Enter number: "); int choice; scanf("%d", &choice); if (choice<1 || choice>movieCount) { printf("Invalid selection.\n"); return; } char *title = movies[choice-1].title; FILE *f = fopen("comments.txt","r"); if (!f) { printf("No comment yet!.\n"); return; } char line[512]; int found = 0; while (fgets(line, sizeof(line), f)) { char usern[MAX_NAME], mov[MAX_MOVIE_NAME], comm[256]; char *p = strtok(line, ";"); if (!p) continue; strcpy(usern, p); p = strtok(NULL, ";"); if (!p) continue; strcpy(mov, p); p = strtok(NULL, "\n"); if (!p) continue; strcpy(comm, p); if (!strcmp(mov, title)) { if (!found) printf("\n--- Comments for '%s' ---\n", title); found = 1; printf("%s: %s\n", usern, comm); } } fclose(f); if (!found) printf("No comment yet!.\n"); } void menu() { int choice; do { printf("\n*****************\n"); printf("1. List Movies\n"); printf("2. Rent Movie\n"); printf("3. Return Movie\n"); if (users[currentUserIndex].role == 0) { printf("4. Subscribe VIP\n"); /* normal üyede gözüküyor, VIP olunca kayboluyor */ printf("5. View Rental History\n"); printf("6. Show Comments\n"); printf("7. Logout\n"); } else if (users[currentUserIndex].role == 2) { printf("4. View Rental History\n"); printf("5. Show Comments\n"); printf("6. Logout\n"); } else { // admin printf("4. Add Movie (Admin Only)\n"); /* sadece admine açık film ekle kısmı*/ printf("5. View Rental History\n"); printf("6. Show Comments\n"); printf("7. Logout\n"); } printf("\nYour choice: "); scanf("%d", &choice); printf("*****************\n"); int role = users[currentUserIndex].role; if (role == 0) { switch (choice) { case 1: listMovies(); break; case 2: rentMovie(); break; case 3: returnMovie(); break; case 4: subscribeVIP(); break; case 5: viewRentalHistory(); break; case 6: showComments(); break; case 7: printf("Logout\n\n\n"); break; default: printf("Invalid choice.\n"); } } else if (role == 2) { switch (choice) { case 1: listMovies(); break; case 2: rentMovie(); break; case 3: returnMovie(); break; case 4: viewRentalHistory(); break; case 5: showComments(); break; case 6: printf("Logout\n\n\n"); break; default: printf("Invalid choice.\n"); } } else { // admin switch (choice) { case 1: listMovies(); break; case 2: rentMovie(); break; case 3: returnMovie(); break; case 4: addMovie(); break; case 5: viewRentalHistory(); break; case 6: showComments(); break; case 7: printf("Logout\n\n\n"); break; default: printf("Invalid choice.\n"); } } } while ((users[currentUserIndex].role == 0 && choice != 7) || (users[currentUserIndex].role == 2 && choice != 6) || (users[currentUserIndex].role == 1 && choice != 7)); } double calcAverage(const char *title) { FILE *f = fopen("rate.txt","r"); if (!f) return -1; char line[200], u[MAX_NAME], t[MAX_MOVIE_NAME]; int r, sum=0, cnt=0; while (fgets(line,sizeof(line),f)) { if (sscanf(line,"%[^;];%[^;];%d",u,t,&r)==3 && !strcmp(t,title)) { sum+=r; cnt++; } } fclose(f); return cnt ? (double)sum/cnt : -1; } void updateAverage(const char *title) { double avg = calcAverage(title); if (avg<0) return; FILE *in = fopen("average.txt","r"); FILE *out = fopen("temp_avg.txt","w"); char line[256], mv[MAX_MOVIE_NAME]; int done=0; if (in) { while (fgets(line,sizeof(line),in)) { if (sscanf(line,"%[^;];",mv)==1 && !strcmp(mv,title)) { fprintf(out,"%s;%.2f\n",title,avg); done=1; } else fputs(line,out); } fclose(in); } if (!done) fprintf(out,"%s;%.2f\n",title,avg); fclose(out); remove("average.txt"); rename("temp_avg.txt","average.txt"); }