error in reading and writing in files [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
This program works but prints garbage values at the beginning (ch=2) and prints the same output twice.
I am using this for my project.It contains more data and there i used a single object instead of array of objects.It didnt work.Each object of array stores a set of data.
#include<iostream>
#include<fstream>
using namespace std;
class rw //a class containing some data
{
public:
int n;
char a;
};
int main()
{
int i;
rw r[2]; //an array of objects
int ch;
fstream f1;
f1.open("file1.txt",ios::in|ios::out|ios::ate);
cout<<"1-read,2-write";
cin>>ch;
f1.seekp(0,ios::beg);
if(ch==1)//for saving
{
r[0].n=1;
r[0].a='a';
f1.write((char*) &r[0],sizeof(r[0]));
r[1].n=2;
r[1].a='b';
f1.write((char*)&r[1],sizeof(r[1]));
}
if(ch==2)//for reading
{
f1.seekg(0,ios::beg);
while(!f1.eof())
{
i=0;
cout<<r[i].n<<r[i].a;
cout<<"\n";
f1.read((char*)&r[i],sizeof(r[i]));
i++;
}
}
system("pause");
return 0;
}

Change following code
cout<<r[i].n<<r[i].a;
cout<<"\n";
f1.read((char*)&r[i],sizeof(r[i]));
to
f1.read((char*)&r[i],sizeof(r[i])); // Moved before printing
cout<<r[i].n<<r[i].a;
cout<<"\n";
You are outputting data then reading from the file, instead you should read and then print. Printing before reading is the reason for getting garbage in first run of loop. I think you moved the reading below to avoid double printing of last record. Continue reading to understand how to avoid double reading.
You should avoid using while (!f1.eof()), as it will print last data twice.
Better use while(f1.read((char*)&r[i],sizeof(r[i])));
Unrolling the eof version of loop for 2 inputs
while(!eof) // true
read first data
print first data
while(!eof) // true
read second data // read all, but was succesful and eof not set
print second data
while(!eof) // true
Try to read // Could not read, eof set
print data // Reprinting second data
while(!eof) // false

Don't use while (!f1.eof()), it will not work as you expect it to, because the eofbit flag isn't set until after you try to read from beyond the file. Instead do e.g. while (f1.read(...)).
Also be careful with a loop like this without bounds checking. If the file is not correct you might write out of bounds of the array r.

Related

How does file pointer shifts when fread() function is called? [duplicate]

This question already has answers here:
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed 5 years ago.
//Libraries are called accordingly
struct std
{
int a;
char b;
}// a structure with 2 objects
void main()
{
std h[5]; // structure array with 5 elements
int rec_size; // Size of single record to be accessed from the file
rec_size=sizeof(structure std); // stores the size in bytes
while (true)
{
fread(&h,rec_size,2,fptr); //fptr is a file pointer to some file
/*Assume that the file pointer(fptr)has covered the last two record
blocks and stored
them in "h". Then the shouldn't the position pointer proceed to end of
file and the next statement "if(feof(fptr)" then becomes true to exit
the loop and in essence miss out on the processing of those last two
record blocks?*/
if(feof(fptr))
/* Here, if the fptr has reached the end of file after fread(),
then this should execute*/
break;
//else additional code to process the content stored in "h"
}
}
My doubt is that when fread() function returns and in the next statement feof() checks for the EOF, shouldn't feof() return true if fread() processed the last two record blocks in the file? Could someone fully explain the functioning?
feof() is used to know what kind of error you hit, not to detect one. The correct way is to check the valued return by fread() which will be 0 at the end of the file. Then if feof() is true, you know that you've reached EOF, otherwise there was an IO error.
So with your current code, you're processing twice the last readable records. Also, you mean &h[0] instead of &h.

How do i set a function to a constant variable? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
It's been a while since I have worked in C++, I am helping a friend.
Is there a way without pointers return number of lines to a const int for use in a for loop?
I know I can do it with pointers but he has not learned them in class yet and I am not morally allowed to teach him anything the professor hasn't.
Example:
int numLines = sizeOfFile(inputFile);
for(int i = 0, i < numLines; i++){
//code here
}
EDIT: my fault I was moving fast to code this thing. I am helping him today I want to have a finished project so I can work off of it while helping him. The reason I need a constant int is so I can set array to that size not just for a for loop. the array is the problem.
You can initialize a const int just the same as you would initialize a regular int. The difference with a const int is that you cannot re-assign after initialization.
const int numLines = sizeOfFile(inputFile);
for(int i = 0, i < numLines; i++){
//code here
}
In the simplest case you're just looking for the number of '\n' characters in the file.
So let's say that you've successfully opened the file to: ifstream pFile then you can use an istreambuf_iterator to count those:
const auto numLines = count(istreambuf_iterator<char>(pFile), istreambuf_iterator<char>(), '\n')
A couple comments here:
The this count operation will consume everything in pFile's buffer, meaning you'll need to call pFile.seekg(0, ios_base::beg)
Picking and choosing values to read from an ifstream indicates a bad smell in code. It's likely that the file format was improperly conceived, or that the program will subsequently need to re-stream the remainder of file contents. The 2nd option seems to be true in your case, as you seek to illegally set the size of an array with a value found at runtime:
The reason I need a constant int is so I can set array to that size
EDIT:
When you say you want to use numLines to "right an array"[sic], my assumption is that the only reason that you would have needed your array to be that size is that you're going to stream each line from a file into your container, that is you're going to stream the entire file once to calculate the size then stream the entire file again to populate your container. Here's what you should do instead:
vector<string> lines;
for(string line; getline(pFiles, line);) {
lines.push_back(line);
}
Now lines will contain your entire file, with each element being a line. If numLines would have been important to you, instead you can use size(lines).

Queries on a string [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
It's a B problem in codeforces
http://www.codeforces.com/problemset/problem/598/B
and i submit this code, but i get Wrong Answer.
It's brute force nothing special, but iam new at problem solving.
#include <iostream>
#include<string>
using namespace std;
int main()
{
char x[10000];
scanf_s("%s",x);
int num;
scanf_s("%d",&num);
int *l = new int[num];
int *r = new int[num];
int *k = new int[num];
for(int i =0;i<num;i++)
{
scanf_s("%d,%d,$d",&l[i],&r[i],&k[i]);
}
char temp;
for(int i =0; i<num;i++)
{
for (int j =0;j<k[i];i++)
{
temp= x[l[i]-1];
x[l[i]-1]=x[r[i]-1];
x[r[i]-1]=temp;
}
}
printf("%s",x);
return 0;
}
Any idea what is wrong or does it need to be optimized ?Is there better way to handle with case of many queries entered ?
scanf is a C function. string is a C++ data type. C++ can often use C datatypes, but it is very rare that C can use C++ datatypes. scanf was written about 20 years before C++ existed and has no clue what a string is.
Next, scanf takes a variable arguments list. It has no clue if the parameter types are correct and cannot easily check. It assumes that the programmer knows what they are doing.
End result, it tries to place char data as specified by the %s format option into a string. The string is written over with incompatible data and undefined behaviour occurs.
Replace the scanf with
cin >> x;
and go all C++. Alternative is to eschew C++ and go C style:
char x[appropriate size goes here];
scanf("%s",x);
Don't know the appropriate size? That's going to be a problem. string resizes to fit. The char array expected by scanf cannot. If you read more data than you can fit, Undefined Behaviour.
In
scanf("%d",num);
%d says the programmer passed in a pointer to an integer, in this case it would be the location of num so that scanf can update the value stored at num with whatever was read. The value of num was passed in. scanf assumes this is a pointer and Undefined Behaviour results. Most likely whatever uninitialized garbage value that is in num is used as a memory location and some unsuspecting block of memory gets overwritten. This will cause problems at some point in the future when you actually need the data that was at that memory.
scanf("%d",&num);
or in C++
cin >> num;
The remaining problems are variations on the preceding two problems.
scanf("%d,%d,%d",l[i],r[i],k[i]);
needs pointers
scanf("%d,%d,%d",&l[i],&r[i],&k[i]);
and
printf("%s",x);
wants a char array, not a string.
printf("%s",x.c_str());
gets the char array equivalent to the string.
Recommendation: Compile with a higher level of intolerance to errors that the compiler can survive. In g++ I use at least -pedantic -pedantic-errors -Wall -Wextra -Werror.
On a logical front, your input is all unchecked. A user could type in "rutabaga" for num with possibly comical results as your program tries to deal with non-numeric input. Again Undefined Behaviour. The program could crash. It could lock up. It could impregnate a male Llama.
In C++
if (cin >> num)
will catch some but not all forms of bad input. If this test fails, the contents of num are undefined and should not be used. Further, the stream will be in an error state and unreadable until the error is acknowledged and cleared. In C the equivalent is
if (scanf("%d",&num) == 1)
if scanf read exactly one value, num, all is good. Any other number of values read means scanf did not succeed and the contents of num are undefined.

Array data lost when returned from function in C++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm sure this is a novice question but the book I'm studying from shows how to encode structurs into a buffer. However the examples are for simple types only. I'm trying to take this one step further by using a dynamic array.
My problem is that after calling encode(), the calling function can see the value of bodyLen but the value of "body" is lost. What am I doing wrong?
The pseudo code:
struct outData
{
uint32_t bodyLen; // Length of body
uint32_t *body; // Array of body elements
};
int encode(uint8_t *buffer, int size)
{
// Set the buffer to the data structure layout
outData *myData = (outData *)buffer;
// Junk data (a nice 10101010...)
uint32_t junk = 2863311530;
// Populate body
uint32_t bodyData[size];
for (int i=0; i<size; i++)
{
bodyData[i] = htonl(junk);
}
// Set the buffer
myData->bodyLen = size; // This works perfectly
myData->body = bodyData; // This is blank to calling function
...
}
Thanks!
bodyData is a local variable, but you are setting myData->body to point to it. After encode returns, bodyData is destroyed and *myData->body is now undefined.
To fix, you need to do a deep copy of the contents of bodyData into myData->body after properly allocating the space (with new[]). And then you need to be sure to delete[] it later.

Array of classes won't hold new value [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
Okay so I'm trying to parse information from a file and I have this loop that reads in an unknown amount of 5 number strings that are separated by new lines. ProfDB is simply an array that holds objects of a class Professor. That class has a method (addPrevCourse()) that adds a Course object to an array of courses within that class. CRNDictionary is a function that takes a string and returns a course object, based on that string. Here are the code snippets:
Main:
ifstream in;
in.open("File.txt");
string CRNHash = "";
while (CRNHash != "!ENDLIST"){
in >> CRNHash;
(*ProfDB[used]).addPrevCourse(CRNDictionary(CRNHash));
addPrevCourse:
void Professor::addPrevCourse(const Course& newCourse)
{
int i = 0;
while (i < 8){
if (Courses_Taught[i].getCRN() == "0"){
Courses_Taught[i] = newCourse;
}
i++;
}
}
CRNDictionary:
Course CRNDictionary(string CRN){
//search course list for the crn passed, temp implementation
if (CRN == "12345")
return Course("Test", "12344");
else if (CRN == "13254")
return Course("Test2", "13254");
else
return Course("Test2", "BLAH");
}
The problem is that when I run the program, and print the Professor's array (Which holds the 5 char strings), all the values are shown as 12344 (The first object from CRNDictionary), even though the file has 5 different values. I have verified that CRNHash is getting scanned in correctly, but can't figure out why the value won't change that gets added to the array.
It's because after the first pass of addPrevCourse all the array items are filled with the first input causing the if inside that function to always be false on following passes. What you need to do is either add a break in the while when the condition is true, or keep a member counter in Professor to know which is the next empty array cell.