0

I'm having an error with my code when executed about the variable 's' being corrupted. I believe it's something with saving the bin or the text. I've tried editing more with the text, but can't figure it out thinking it might be the bin or something I must have mistyped or added on accident.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 4

struct Person
{
    char name[16], dep[16];
    float cyi, ra, rp, npa, tyi, tra, tpa;
};

void load(struct Person s[], int n)
{
    for (int i = 0; i < n; i++)
    {
        printf("Enter your name   ");
        gets(s[i].name);
        printf("Enter your department   ");
        gets(s[i].dep);
        printf("Enter your current yearly income   $");
        scanf("%f", &s[i].cyi);
        printf("Enter your raise percentage   ");
        scanf("%f", &s[i].rp);
        s[i].ra = (s[i].cyi * s[i].rp) / (float)100;
        s[i].npa = (s[i].cyi) + (s[i].ra);
        printf("\n");

        fflush(stdin);
    }
}

void sort(struct Person s[], int n)
{
    int i, j;
    Person t;
    for (i = 0; i < n - 1; i++)
        for (j = 0; j < n - 1; j++)
            if (strcmp(s[j].name, s[j + 1].name) > 0)
            {
        t = s[j];
        s[j] = s[j + 1];
        s[j + 1] = t;
            }
}

void print(struct Person s[], int n)
{
    printf("\n\n");
    for (int i = 0; i < n; i++)
    {
        printf("%s in department %s\n", s[i].name, s[i].dep);
        printf("The current yearly income is $%0.2f the raise percentage is %0.2f%%\n", s[i].cyi, s[i].rp);
        printf("The raise amount is $%0.2f, the new pay amount is $%0.2f\n\n", s[i].ra, s[i].npa);
    }
}

void calc(struct Person s[], int n)
{
    float tyi = 0, tra = 0, tpa = 0;
    for (int i = 0; i < n; i++)
    {
        tyi += s[i].cyi;
        tra += s[i].ra;
        tpa += s[i].npa;
    }
    printf("The total current yearly income is $%0.2f\n", tyi);
    printf("The total raise amount is $%0.2f\n", tra);
    printf("The total new pay amount is $%0.2f\n", tpa);
}

void savetext(struct Person s[], int n)
{
    int i;
    FILE *f;
    f = fopen("G:\\College\\CS 36\\Projects\\Final Program\\FinalHomework\\info.txt", "w");
    for (i = 0; i < n; i++)
    {
        fprintf(f, "%s\n", s[i].name);
        fprintf(f, "%s\n", s[i].dep);
        fprintf(f, "%f %f %f\n", s[i].cyi, s[i].rp, s[i].npa);
    }
    fclose(f);
}

void retrievetext(struct Person s[], int n)
{
    int i;
    FILE *f;
    f = fopen("G:\\College\\CS 36\\Projects\\Final Program\\FinalHomework\\info.txt", "r");
    for (i = 0; i < n; i++);
    {
        fgets(s[i].name, sizeof(s[i].name), f);
        fgets(s[i].dep, sizeof(s[i].dep), f);
        fscanf(f, "%f%f%f\n", &s[i].cyi, &s[i].rp, &s[i].npa);
    }
    fclose(f);
}

void savebin(struct Person s[], int n)
{
    FILE *f;
    f = fopen("G:\\College\\CS 36\\Projects\\Final Program\\FinalHomework\\info.bin", "wb");
    fwrite(&s, sizeof(s[0]), n, f);
    fclose(f);
}

void retrievebin(struct Person s[], int n)
{
    FILE *f;
    f = fopen("G:\\College\\CS 36\\Projects\\Final Program\\FinalHomework\\info.bin", "rb");
    fread(&s, sizeof(s[0]), n, f);
    fclose(f);
}

void main()
{
    Person s[SIZE];
    load(s, SIZE);
    sort(s, SIZE);
    print(s, SIZE);
    calc(s, SIZE);
    savetext(s, SIZE);
    retrievetext(s, SIZE);
    printf("\nAfter the text file is retrieved\n");
    print(s, SIZE);
    savebin(s, SIZE);
    retrievebin(s, SIZE);
    printf("\nAfter the binary file is retrieved\n");
    print(s, SIZE);
    system("PAUSE");
}

This is for a homework assignment of mine for class.

Error Received is screenshotted here

AirWick
  • 11
  • 4
  • 2
    Using [`gets()`](http://stackoverflow.com/questions/1694036/why-is-the-gets-function-dangerous-why-should-it-not-be-used) is a very bad idea! You've not shown the data that causes the trouble. Given that you're using `gets()`, there are many ways faulty data could be causing trouble. – Jonathan Leffler Dec 15 '14 at 04:39
  • Updated with a screenshot. @JonathanLeffler I'm using gets() due to my programming class teaching it like this. This class is an intro to C, so this is basics. – AirWick Dec 15 '14 at 05:05
  • 1) you did not check for the success of `fopen()`. 2) don't put a link to third-party website. write down the error message or add the image here. – Sourav Ghosh Dec 15 '14 at 05:08
  • Break your program down into smaller parts until you find which line is causing the corruption – M.M Dec 15 '14 at 05:09
  • The input function could have a lot more validation (as well as taking out `fflush(stdin)` which causes undefined behaviour). It seems likely that the error comes from buffer overflow due to `gets`. – M.M Dec 15 '14 at 05:10
  • 1
    *"This class is an intro to C, so this is basics"* - One of the basics of C is to learn to not use functions which have been deprecated and/or are inherently dangerous. `gets` satisfies both of those conditions. Let your teacher know that he is doing you a disservice. – Ed S. Dec 15 '14 at 05:25
  • 1
    @AirWick: your teacher is not teaching you good C programming. You cannot use `gets()` safely; period, full stop, end of story. The program cannot defend itself against bad input if you use `gets()`. Use `fgets()` or `getline()` or `gets_s()` instead; indeed, since you're on Windows, use `gets_s()`. That can be used safely, and preserves the newline-removing semantics of `gets()`, unlike the other two options I mentioned. – Jonathan Leffler Dec 15 '14 at 05:26
  • @EdS. My professor already explained to us about the gets and how it does cause errors and is a dangerous thing to learn. He has taught us the proper way to use fgets in previous programs, but WANTS us to use gets. – AirWick Dec 15 '14 at 05:30
  • @JonathanLeffler Like I stated in this same comment to Ed S, I was taught how to use fgets, but for these programs he wants us to use gets, Sorry for the confusion. – AirWick Dec 15 '14 at 05:31
  • @AirWick: remember to forget all about `gets()` just as soon as you possibly can. Your professor needs to update his knowledge of, or thinking about, C; using `gets()` has been a bad idea for decades. The original Internet worm (which was unleashed in November 1988) exploited `gets()`, for example. (Google search terms 'Morris internet worm'.) – Jonathan Leffler Dec 15 '14 at 08:33

2 Answers2

1

Few things to correct in your Code.

  1. Structure variable Declaration.

    struct Person
    {
        char name[16], dep[16];
        float cyi, ra, rp, npa, tyi, tra, tpa; 
    }; 
    

    You cannot initialize a structure variable as follow:

    void sort(struct Person s[], int n)
    {   
        ...
        Person t;
        ...
    }
    

    Change the above to

    `struct Person t;` or use typedefs.
    
  2. Avoid using gets,
    see here : warning:gets function is dangerous

    Instead use fgets:
    char* fgets(char *string, int length, FILE * stream);

  3. I'm using __fpurge(stdin) to flush the stdin.
    Define in #include <stdio_ext.h>

  4. Change return type of main

    int main
    {
        ...
        return 0;
    }
    

Changes in your code:

void load(struct Person s[], int n)                                             
{ 
    int i;                                                                      
    for (i = 0; i < n; i++)                                                     
    {                                                                           
    printf("Enter your name   ");                                           
    fgets(s[i].name, 16, stdin);                                            
    printf("Enter your department   ");                                     
    fgets(s[i].dep, 16, stdin);
    ...
    ...                                                 
    __fpurge(stdin);    
    }                   
}       

Your Code should pretty much look like this:
http://pastebin.com/STtDLdT4

Community
  • 1
  • 1
Saurabh Meshram
  • 8,106
  • 3
  • 23
  • 32
  • On Windows, a better replacement for `gets()` is `gets_s()`. It is in Annex K of the C11 standard, as part of an optional set of functions, but Microsoft has implemented them (not completely matching the standard, though — see [Do you use the TR-24731 'safe' functions?](http://stackoverflow.com/questions/372980/do-you-use-the-tr-24731-safe-functions); but `gets_s()` is OK). – Jonathan Leffler Dec 15 '14 at 05:31
-2

The problem is here.You need to use strcpy to copy

 if (strcmp(s[j].name, s[j + 1].name) > 0)
 {
         t = s[j];
         s[j] = s[j + 1];
         s[j + 1] = t;
 }

Change this to this-

char temp[Str_len];  //any length suitable for you ;)
strcpy(temp,s[j].name);
strcpy(s[j+1].name,s[j].name);
strcpy(temp,s[j+1].name);
Ankur
  • 3,584
  • 1
  • 24
  • 32
  • 2
    That is not correct. You can assign `struct`s the way the OP has done without any problems. – R Sahu Dec 15 '14 at 04:47
  • @r sahu the problem will become with character array used.the safe way to do is to use strcpy. – Ankur Dec 15 '14 at 04:49
  • Not true. When you assign `struct`s the entire array gets assigned. See working code: http://ideone.com/YIov9f – R Sahu Dec 15 '14 at 04:53