简体   繁体   中英

fread is reading garbage in file

I am working on my assignment and faced a problem with fread() in C++. When I modify the name in my file it modifies it perfectly as I want but the problem occurs when I try to read the file after that, it reads the whole file but it does not stop after that it's running total 146 times whereas there are only 3 names.

My code:-

#include <bits/stdc++.h>
using namespace std;

struct person{
    int id; 
    string fname; 

}s;

void write(){
    FILE *outfile;
    struct person input; 
    int num,ident;
    string sname[] = {"a","b","c"};

    outfile = fopen ("C:\\Users\\Amritesh\\Desktop\\students.txt","wb");

    if (outfile == NULL) 
    { 
        fprintf(stderr, "\nError opend file\n"); 
        exit (1); 
    } 

    scanf("%d",&num);

    for(int i=0;i<num;i++){

        s.fname = sname[i];
        cin >> s.id;

        fwrite (&s, sizeof(s), 1, outfile);
    }
    fclose(outfile);
}

void read(){

    FILE *file1;
    int i=0;
    file1 = fopen ("C:\\Users\\Amritesh\\Desktop\\students.txt","r");

    while(fread(&s, sizeof(s), 1, file1) == 1) {    

        cout << "ID " << s.id << "  Name " <<s.fname << endl;
    }

    fclose (file1); 


} 

void modify(){
    FILE *file;
    file = fopen ("C:\\Users\\Amritesh\\Desktop\\students.txt","r+");

    while(fread(&s, sizeof(s), 1, file)) {

        if(s.fname == "a"){
            s.fname = "d";
            fseek(file,-sizeof(s),SEEK_CUR);
            fwrite (&s, sizeof(s), 1,file);
        }
    }

    fclose (file); 
}

int main(){
    write();
    modify();
    read();
}

Edited code:-

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

struct person 
{ 
    int id; 
    string fname; 
}s,temp; 



void read() 
{ 
    int num;
    
    ifstream fin;
    fin.open("C:\\Users\\Amritesh\\Desktop\\student.txt",ios::in);
    fin.seekg(0,ios::beg);
    

    //scanf("%d",&num);

    while(fin){

        cout << s.fname << s.id << endl;
    }

    fin.close();
}

void write(){

    int i=0;
    ofstream fout;

    fout.open("C:\\Users\\Amritesh\\Desktop\\student.txt");
    
    
    while(i!=2) {   
        cin >> s.id >> s.fname;
        fout << "ID " << s.id << "  Name " <<s.fname << endl;
        i++;
    }

    
    fout.close();
    
} 

void modify(){

    fstream mod;
    mod.open ("C:\\Users\\Amritesh\\Desktop\\student.txt");
    
    while(mod) {

        if(s.fname == "a"){
            s.fname = "d";
            mod.seekg(-sizeof(s),ios::cur);
            mod << s.fname;
        }
    }

    
    mod.close();
}

int main(){
    
    write();
    read();
    modify();
    
}

Thanks for any answer!

Here are three ideas based on our discussion. I'll start with free functions for reading and writing a person object since it looks like you're at that stage right now. I'll move on to adding member functions in your person class and end with adding stream operators for convenience.

An example of free (non-member) read and write functions:

#include <iostream>
#include <string>
#include <fstream>

struct person {
    int id; 
    std::string fname; 
};

std::ostream& write(std::ostream& os, const person& p) {
    os << p.id << ',' << p.fname << '\n'; // stream out the properties of a person
    return os; // look at the next example for an alternative doing the same thing
}

std::istream& read(std::istream& is, person& p) {
    // extract "id" and if it succeeds, check if the next char is a , char
    if(is >> p.id && is.peek() == ',') { 
        is.ignore();               // step over the , char
        std::getline(is, p.fname); // read the rest of the line into p.fname
    } else {
        // we didn't get id or the , char, so set the stream in a failed state
        is.setstate(is.failbit);       
    }
    return is;
}

int main() {
    // write to file
    {
        std::ofstream file("C:\\Users\\Amritesh\\Desktop\\student.txt");
        person test1{10, "Foo Bar"};
        person test2{20, "Apa Bepa"};
        write(file, test1);
        write(file, test2);
    }
    // read from file
    {
        std::ifstream file("C:\\Users\\Amritesh\\Desktop\\student.txt");
        person test;

        while(read(file, test)) {
            std::cout << test.fname << '\n';
        }
    }
}

An example of making read and write member functions in person :

#include <iostream>
#include <string>
#include <fstream>

struct person {
    int id; 
    std::string fname;

    std::ostream& write(std::ostream& os) const {
        // this does the same thing as in the first example
        return os << id << ',' << fname << '\n';        
    }

    std::istream& read(std::istream& is) {
        if(is >> id && is.peek() == ',') {
            is.ignore(); // step over the , char
            std::getline(is, fname);
        } else {
            is.setstate(is.failbit); // we didn't get id or the , char
        }
        return is;
    }    
};

int main() {
    // write to file
    {
        std::ofstream file("C:\\Users\\Amritesh\\Desktop\\student.txt");
        person test1{10, "Foo Bar"};
        person test2{20, "Apa Bepa"};
        test1.write(file);
        test2.write(file);
    }
    // read from file
    {
        std::ifstream file("C:\\Users\\Amritesh\\Desktop\\student.txt");
        person test;

        while(test.read(file)) {
            std::cout << test.fname << '\n';
        }
    }
}

Member functions supported by stream operators:

#include <iostream>
#include <string>
#include <fstream>

struct person {
    int id; 
    std::string fname;

    std::ostream& write(std::ostream& os) const {
        return os << id << ',' << fname << '\n';        
    }

    std::istream& read(std::istream& is) {
        if(is >> id && is.peek() == ',') {
            is.ignore(); // step over the , char
            std::getline(is, fname);
        } else {
            is.setstate(is.failbit); // we didn't get id or the , char
        }
        return is;
    }    
};

// stream operators calling member functions
std::ostream& operator<<(std::ostream& os, const person& p) { return p.write(os); }
std::istream& operator>>(std::istream& is, person& p) { return p.read(is); }

int main() {
    // write to file
    {
        std::ofstream file("C:\\Users\\Amritesh\\Desktop\\student.txt");
        person test1{10, "Foo Bar"};
        person test2{20, "Apa Bepa"};
        file << test1 << test2;  // calling operator<< for each person object
    }
    // read from file
    {
        std::ifstream file("C:\\Users\\Amritesh\\Desktop\\student.txt");
        person test;

        while(file >> test) {    // extract one person at a time using operator>>
            std::cout << test.fname << '\n';
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM