2

Why fputs() or fprintf() are not writing into the file.txt for %s? I tried both functions but they don't seem to write into the file. However, when using the same functions for %d, it does work currently. As for the expected output versus what currently happens, please find below an example when choosing option 1 in the program, and entering a square side of 2.

Currently happening:

1
2
4
8

Expected output:

You have chosen option: 1
The side of the square is: 2
The square area is: 4
The square perimeter is: 8

Any ideas as to what may be causing this? Thank you!

N.b. This code is for learning purposes, so you may find inconsistencies in the way I work with variables (i.e. passing by reference or value). Please disregard that.

#include <stdio.h> 
#include <locale.h>
#include <string.h>
#define PI 3.14

void square_functions (int side, int *square_perimeter, int *square_area);
float circle_functions (float radius, float * area_circle, float * circumference, FILE *fich);

int main() 
{ 

    float radius, area_circle, circumference;
    int side, square_area, square_perimeter, choice;
    FILE *fich; /* esto como variable global penaliza! */
    fich=fopen("file.txt","w");

    while (1) 
    {
    printf("Enter 1 to calculate the square\n"); 
    printf("Enter 2 to calculate the circumference\n");
    printf("Enter your option:\n"); 
    scanf("%d",&choice);
    fprintf(fich,"%s\n", "You have chosen option:");
    fprintf(fich,"%d\n",choice);

    switch (choice) 
        { 
        case 1: 
            printf("Please enter the side of the square: ");
            scanf("%d", &side);
            fprintf(fich,"%s\n", "The side of the square is:");
            fprintf(fich,"%d\n",side);
            if(side > 0)
            {
                square_functions (side, &square_perimeter, &square_area);
                printf("\nSquare area: %d", square_area);
                printf("\nSquare perimeter: %d\n", square_perimeter);
                fprintf(fich,"%s\n", "The square area is:");
                fprintf(fich,"%d\n", square_area);
                fputs("The square perimeter is",fich);
                fprintf(fich,"%d\n", square_perimeter);
            }
            else
            {
                printf("The value is invalid, the operation has been cancelled");
            } 
        break;

        case 2: 
            printf("\n\nPlease enter the radius fo the circle: ");
            scanf("%f", &radius);

            if(radius > 0)
            {
                circle_functions (radius, &area_circle, &circumference, fich);  
                printf("Circle area: %f", area_circle);
                printf("circumference: %f", circumference);
            }
            else
            {
                printf("The value is invalid, the operation has been cancelled");
            }
        break;
        }
    }
fclose(fich);
return 0;
}

void square_functions (int side, int *square_perimeter, int *square_area)
{       
        *square_perimeter = side * 4;
        *square_area = side * side;
}

float circle_functions (float radius, float * area_circle, float * circumference, FILE *fich) 
{
        *area_circle = PI * radius * radius;
        *circumference = 2 * PI * radius;
        fputs("The area of the circle is",fich); 
        fprintf(fich,"%f\n",*area_circle);
        fputs("The circumference is",fich);
        fprintf(fich,"%f\n",*circumference);
        return 0;       
}
Henry
  • 617
  • 1
  • 5
  • 12
  • Please specify the expected output and actual output of **both** output streams (`stdout` and `fich`). Also, please specify the exact input that was entered. – Andreas Wenzel Jun 12 '20 at 19:50

5 Answers5

3

The problem is you're not closing the file. Note: You have fclose(fich);, but it's unreachable. Add a third condition, such as the following, at it should work:

case 3:
    fclose(fich);
    return 0;

An alternative would be to not use an infinite loop (while(1)) and use a condition instead. For example:

bool run = true;
while(run)
{
    ...
    case 3:
        run = false;
        break;
    ...
}
Fiddling Bits
  • 8,362
  • 3
  • 24
  • 41
  • thank you for your quick answer @Fiddling Bits! :-) What I don't understand is why it wasn't an issue when printing integers but now it is for strings. Thank you! – Henry Jun 12 '20 at 19:33
  • 1
    When you call `fprintf` it may stay in a buffer until flushed. `\n` will flush the buffer but it looks like you may be using it incorrectly (`fprintf(fich,"%s\n", "You have chosen option:");`) as pointed out by @PiGuy. I'm not entirely sure. – Fiddling Bits Jun 12 '20 at 19:35
  • 1
    @FiddlingBits: With me, `stdout` is **line buffered** whereas `fich` (the file stream) is **fully buffered**. However, I believe that is platform-dependant. I guess that is why `\n` has no effect on buffering. – Andreas Wenzel Jun 14 '20 at 20:43
1

Why not try fprintf(fich,"The square area is:\n");

  • thank you @PiGuy thank you for your quick answer. I am not really getting it to work either with the above suggestion. Any other ideas? – Henry Jun 12 '20 at 19:40
  • Although `fprintf(fich,"The square area is:\n");` may be simpler and more efficient than writing `fprintf(fich,"%s\n", "The square area is:");`, it seems just as correct to me. – Andreas Wenzel Jun 12 '20 at 19:44
1

Your code as is, is fairly complete, but requires a few adjustments

  • Requires a way to exit,

  • In the second case (circles) the function printf() is used as opposed to fprintf().

  • fclose() is never accessed due to infinite loop

The following addresses these, by using a boolean variable running as a flag to run, and a third case to access it to exit, and adds the fprintf function in the second case, and opens/closes file each iteration:

#define FILENAME "file.txt" 

int main(void) 
{ 
    float radius, area_circle, circumference;
    int side, square_area, square_perimeter, choice;
    BOOL running = TRUE;
    FILE *fich; /* esto como variable global penaliza! */
    //create file for write:
    fich=fopen(FILENAME,"w");//test before using
    if(fich)
    {
        fprintf(fich, "Beginning of file:\n\n");
        fclose(fich);
    }

    while (running) 
    {
        printf("Enter 1 to calculate the square\n"); 
        printf("Enter 2 to calculate the circumference\n");
        printf("Enter 3 to quit program\n");        
        printf("Enter your option:\n"); 
        scanf("%d",&choice);
        fprintf(fich,"%d\n",choice);

        switch (choice) 
        { 
        case 1: 
            fich=fopen(FILENAME,"a");//test before using
            if(fich)
            {
                printf("Please enter the side of the square: ");
                scanf("%d", &side);
                fprintf(fich,"%d\n",side);
                if(side > 0)
                {
                    square_functions (side, &square_perimeter, &square_area);
                    printf("\nSquare area: %d", square_area);
                    printf("\nSquare perimeter: %d\n", square_perimeter);
                    fprintf(fich,"%s\n", "The square area is: %d\n");
                    fprintf(fich,"The perimeter is: %d\n", square_perimeter);
                }               
                else
                {
                    printf("The value is invalid, the operation has been cancelled");
                }
                fclose(fich);
            }
            break;

        case 2: 
            fich=fopen(FILENAME,"a");//test before using
            if(fich)
            {
                printf("\n\nPlease enter the radius of the circle: ");
                scanf("%f", &radius);

                if(radius > 0)
                {
                    circle_functions (radius, &area_circle, &circumference, fich);  
                    printf("Circle area: %f", area_circle);
                    printf("circumference: %f", circumference);
                    fprintf(fich, "Circle area: %f", area_circle);
                    fprintf(fich, "circumference: %f", circumference);
                }
                else
                {
                    printf("The value is invalid, the operation has been cancelled");
                }
                fclose(fich);
            }
            break;
        case 3:
            running = FALSE;
            break;
        }
    }
    return 0;
}
ryyker
  • 20,437
  • 3
  • 35
  • 78
  • 1
    thank you for your anwer @ryyker! :-) I am getting these errors: https://screencast.com/t/yb6DUWeBU Could you maybe give it another go to complete this? Thank you!! – Henry Jun 12 '20 at 20:12
  • @Henry - I did not add in the code that you already had working :) All the changes are in the `main()` function. So you need to include your header includes, the function prototypes, and `#defines`. Also, my BOOL may need to be changed to `bool` for your environment, same for `TRUE` – ryyker Jun 12 '20 at 20:17
  • Understood. Thank you, Ryyker! – Henry Jun 12 '20 at 20:18
1

When I run the program on Microsoft Windows, the output to stdout works, but not the output to fich. The problem is that (at least with me), stdout is line buffered, whereas fich is fully buffered. Since you never call fclose (because it is outside the infinite loop), the buffer of fich never gets flushed.

To fix this problem, you can either explicitly flush the buffer with fflush( fich ); or you can implicitly flush the buffer, by ensuring that fclose gets called (for example by exiting the loop).

Alternatively, you can disable buffering completely, by calling setbuf( fich, NULL); Please note that this line must appear immediately after the call to fopen. See the documentation on the function setbuf for further information. However, this should normally not be done, because buffering can be important for performance.

Andreas Wenzel
  • 4,984
  • 2
  • 7
  • 24
  • Thank you for your answer @Andreas Wenzel. This helped to achieve the final code that worked! :) – Henry Jun 12 '20 at 20:17
0

Thanks to @AndreasWenzel comments I have added below the final pieces of code that work; first version using fclose(fich); and second one using fflush(fich);.

fclose(fich); version: the file is being closed every time is opened to write in it.

#include <stdio.h> 
#include <locale.h>
#include <string.h>

#define PI 3.14

void square_functions (double side, double *square_perimeter, double *square_area);
void circle_functions (double radius, double *area_circle, double *circumference);

int main() 
{ 

    double radius, area_circle, circumference, side, square_area, square_perimeter;
    int choice;
    FILE *fich;

    while (1) 
    {
    printf("\nEnter 1 to calculate the square"); 
    printf("\nEnter 2 to calculate the circumference");
    printf("\nEnter your option:"); 
    scanf("%d",&choice);
    fich = fopen("file.txt","a+");
    fprintf(fich,"%s", "\n\nThe option chosen is: ");
    fprintf(fich,"%d\n",choice);
    fclose(fich);

    switch (choice) 
        { 
        case 1:
            printf("Please enter the side of the square: ");
            scanf("%lf", &side);
            fich = fopen("file.txt","a+");
            fprintf(fich,"%s", "\nThe side of the square is: ");
            fprintf(fich,"%lf",side);
            if(side > 0)
            {
            square_functions (side, &square_perimeter, &square_area);
            printf("\nSquare area: %lf", square_area);
            printf("\nSquare perimeter: %lf\n", square_perimeter);  
            fprintf(fich,"%s", "\nThe square area is: ");
            fprintf(fich,"%lf", square_area);
            fprintf(fich,"%s", "\nThe square perimeter is: ");
            fprintf(fich,"%lf", square_perimeter);
            fclose(fich);
            }
            else
            {
            printf("The value is invalid, the operation has been cancelled");
            } 
        break;

        case 2:
            printf("\n\nPlease enter the radius fo the circle: ");
            scanf("%lf", &radius);
            fich = fopen("file.txt","a+");
            fprintf(fich,"%s", "\nThe radius of the circle is: ");
            fprintf(fich,"%lf",radius);         
            if(radius > 0)
            {
            circle_functions (radius, &area_circle, &circumference);       
            printf("\nCircle area: %lf\n", area_circle);
            printf("\nCircumference: %lf\n", circumference);
            fprintf(fich,"%s", "\nThe circle area is: ");
            fprintf(fich,"%lf",area_circle);
            fprintf(fich,"%s", "\nThe circumference is: ");
            fprintf(fich,"%lf",circumference);
            fclose(fich);
            }
            else
            {
            printf("The value is invalid, the operation has been cancelled");
            }
        break;
        }
    }
return 0;
}

void square_functions (double side, double *square_perimeter, double *square_area)
{       
        *square_perimeter = side * 4;
        *square_area = side * side;
}

void circle_functions (double radius, double *area_circle, double *circumference) 
{
        *area_circle = PI * radius * radius;
        *circumference = 2 * PI * radius;   
}

fflush(fich); version: the buffer is flushed immediately before the switch statement and once immediately after the switch statement (as the last statement of the while loop).

#include <stdio.h> 
#include <locale.h>
#include <string.h>

#define PI 3.14

void square_functions (double side, double *square_perimeter, double *square_area);
void circle_functions (double radius, double *area_circle, double *circumference);

int main() 
{ 

    double radius, area_circle, circumference, side, square_area, square_perimeter;
    int choice;
    FILE *fich;
    fich = fopen("file.txt","a+");

    while (1) 
    {
    printf("\nEnter 1 to calculate the square"); 
    printf("\nEnter 2 to calculate the circumference");
    printf("\nEnter your option:"); 
    scanf("%d",&choice);
    fprintf(fich,"%s", "\n\nThe option chosen is: ");
    fprintf(fich,"%d\n",choice);
    fflush( fich );

    switch (choice) 
        { 
        case 1:
            printf("Please enter the side of the square: ");
            scanf("%lf", &side);
            fprintf(fich,"%s", "\nThe side of the square is: ");
            fprintf(fich,"%lf",side);
            if(side > 0)
            {
            square_functions (side, &square_perimeter, &square_area);
            printf("\nSquare area: %lf", square_area);
            printf("\nSquare perimeter: %lf\n", square_perimeter);  
            fprintf(fich,"%s", "\nThe square area is: ");
            fprintf(fich,"%lf", square_area);
            fprintf(fich,"%s", "\nThe square perimeter is: ");
            fprintf(fich,"%lf", square_perimeter);
            }
            else
            {
            printf("The value is invalid, the operation has been cancelled");
            } 
        break;

        case 2:
            printf("\n\nPlease enter the radius fo the circle: ");
            scanf("%lf", &radius);
            fprintf(fich,"%s", "\nThe radius of the circle is: ");
            fprintf(fich,"%lf",radius);         
            if(radius > 0)
            {
            circle_functions (radius, &area_circle, &circumference);       
            printf("\nCircle area: %lf\n", area_circle);
            printf("\nCircumference: %lf\n", circumference);
            fprintf(fich,"%s", "\nThe circle area is: ");
            fprintf(fich,"%lf",area_circle);
            fprintf(fich,"%s", "\nThe circumference is: ");
            fprintf(fich,"%lf",circumference);
            }
            else
            {
            printf("The value is invalid, the operation has been cancelled");
            }
        break;
        }
    fflush( fich );
    }
return 0;
}

void square_functions (double side, double *square_perimeter, double *square_area)
{       
        *square_perimeter = side * 4;
        *square_area = side * side;
}

void circle_functions (double radius, double *area_circle, double *circumference) 
{
        *area_circle = PI * radius * radius;
        *circumference = 2 * PI * radius;   
}
Henry
  • 617
  • 1
  • 5
  • 12
  • It looks like this code still has an infinite loop, and the calls to `fopen()` and `fclose()` must match. (they do not here.) After your first time in the loop, `fich` will be closed, and not accessible until re-opened. Also, `case 2:` still does not write to the file. Is this your updated working code? – ryyker Jun 12 '20 at 20:24
  • @ryyker: Actually, `case2` does write to the file, but only inside the function call `circle_functions`. – Andreas Wenzel Jun 12 '20 at 20:26
  • If you really want to keep your infinite loop, I suggest you use `fflush` instead of `fclose`. That way, your will be still able to write to the file afterwards. – Andreas Wenzel Jun 12 '20 at 20:27
  • Hi @AndreasWenzel! After reviewing your comments I have cleaned up the above answer. I am opening and closing the file every time I write on it. Not sure if it is very efficient, resources wise but at least it does work properly now. Please let me know what you think! Thank you! – Henry Jun 14 '20 at 20:10
  • Hi @ryyker just FYI for you too. Check above last comment I made. Thank you! – Henry Jun 14 '20 at 20:26
  • @Henry: Using `fflush` would be cleaner and better for performance. But if you don't mind opening and closing a file every time, then you can of course do it that way, too. – Andreas Wenzel Jun 14 '20 at 20:52
  • @Henry: I like it that you removed the output from inside the function `circle_functions`. It was inconsistent that the function `square_functions` had no direct output whereas the function `circle_functions` was calling output functions directly. – Andreas Wenzel Jun 14 '20 at 20:56
  • @AndreasWenzel Thank you for your answer! :-) Would you mind showing me how the code would end up being if `fflush` was used? Thank you again for all your help! :-) – Henry Jun 14 '20 at 21:03
  • @Henry: You could call `fflush( fich );` after every call to `fprintf( fitch, ... );` in order to always be sure that the latest output gets flushed immediately. However, that would be inefficient. Therefore, it would be best to only call `fflush` immediately after the last call to `fprintf` before a longer period of no more output occuring, for example because the program is waiting for input from `scanf`. I think it would be best to call `fflush` twice, once immediately before the `switch` statement and once immediately after the `switch` statement (as the last statement of the while loop). – Andreas Wenzel Jun 14 '20 at 21:37
  • Awesome @AndreasWenzel Just added the version with `fflush( fich );` in the above answer. Thanks very much for all your help on this one man!! :-) – Henry Jun 14 '20 at 21:56
  • @Henry: It seems that you removed all calls to `fclose`, but not the calls to `fopen`. This means you are calling `fopen` three times on the same file, without ever closing it. This may cause `fich` to be `NULL` if the first call to `fopen` succeeds, but a subsequent call fails, because the file is already open. Therefore, I suggest you call `fopen` only once at the start of your program. – Andreas Wenzel Jun 14 '20 at 22:03
  • @Henry: Opening the same file several times without ever closing them may work on your operating system. However, it may fail on other operating systems. Therefore, I don't recommend it. – Andreas Wenzel Jun 15 '20 at 14:52
  • hey @AndreasWenzel just corrected the code according to your comments. Thank you very much for your effort in ensuring this was done properly. Very much appreciated man!! :-) – Henry Jun 15 '20 at 18:25
  • @Henry: Yes, the code looks good now. Of course, normally, you should always have a matching `fclose` for every call to `fopen`. But that doesn't make sense when you have an infinite loop. The cleanest solution to this would be to provide a menu option for the user to end the program, which exits the loop. That way, the loop would no longer be infinite. After exiting the loop, you could then call `fclose`. – Andreas Wenzel Jun 16 '20 at 03:47
  • Understood @AndreasWenzel Thank you for all your help!! :-) – Henry Jun 16 '20 at 14:38