Difficulty reading binary files in c++ [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I have a visual c++ project named Search Elements in which there is a class called PeriodicTable and I have another visual c++ project called Write Elements in which there is this same class and it's description(variable names and their sizes) is same too...
I use the Write Elements project to write the object of the class Periodic Table to a binary file named PeriodicTable.dat but whenever I use the binary file with my Search Elements project(basically just copy-paste from Write Elements to Search Elements) then the output is unexpected(contains garbage value).
In my opinion the file should work with both the projects as both the projects contains the same class decription. But I don't know what is the problem???
Write Elements Code:
#include <iostream>
#include <fstream>
using namespace std;
class PeriodicTable
{
char Name[15], Symbol[3], Block, State[10], Colour[15], Classification[20];
int GroupNo, AtomicNo, PeriodNo;
float Weight;
public:
void GetInfo();
};
int main()
{
PeriodicTable ptele;
ofstream fileout;
fileout.open("PeriodicTable.dat", ios::binary | ios::app);
system("cls");
ptele.GetInfo();
fileout.write((char *)&ptele, sizeof(ptele));
fileout.close();
return 0;
}
void PeriodicTable::GetInfo()
{
cout << "Full Name of the element: ";
cin >> Name;
cout << "Symbol: ";
cin >> Symbol;
cout << "Block: ";
cin >> Block;
cout << "State(at Room Temperature): ";
cin >> State;
cout << "Colour: ";
cin >> Colour;
cout << "Classification: ";
cin >> Classification;
cout << "Group Number: ";
cin >> GroupNo;
cout << "Atomic Number: ";
cin >> AtomicNo;
cout << "Period Number: ";
cin >> PeriodNo;
cout << "Atomic Weight: ";
cin >> Weight;
}

You did not perform class abstraction correctly. And more over, everything in same file? including class definition? That's not how you use VS project structure.
I assume you want to create two separate applications. One would create periodic table and a second application use the file generated by first application.
If above is correct, you need to declare the PeriodicTable class in header, implement constructor, destructor and GetInfo method in a .cpp implementation. Another .cpp implementation should contain your main() function for the first application.
Note that it is generally a good idea to create a universal header file in a shared location by two applications which contain global definitions, like the path to the generated .dat file. In this case, absolute path should be taken as both applications will unlikely have same relative path to the file.
Another thing to notice, instead of letting compiler figure out how the file should be structured, structure it yourself. Follow the structure convention you created in both application. One suggestion is that instead of writing (char *) &ptele, write one line for one element, give a tab between each column, say between Element and Symbol. You'll need to parse it properly before using the value but this avoids any ambiguity of the data.

It perfectly works for me with the following read code:
int Read()
{
ifstream file;
file.open("PeriodicTable.dat", ios::binary | ios::in);
while (0 == file.rdstate())
{
PeriodicTable ptele;
file.read((char *)&ptele, sizeof(ptele));
//if (0 == file.rdstate())
// ptele.PrintInfo();
}
file.close();
return 0;
}

I do not think you use the VS project structure correctly. At the first sight your simple solution should contain one project that would contain one class (PeriodicTable) and this class should have several methods e.g. searchElements, writeElements, readElements etc. What is wrong with this approach? If, for some reason, you cannot use this approach, then I think you should better explain your problem, what you are trying to achieve.

Related

How does inputting a string into an int variable work in C++

this is some code that i have in C++:
#include <iostream>
using namespace std;
int main() {
int num1;
string some;
cout << "enter something";
cin >> num1 >> some;
cout << num1 << endl << some;
return 0;
}
I'm a bit confused about how inputting works exactly in C++. First of all, through observation i figured that when asking for multiple inputs, C++ looks for either space or line separated data and am not sure if that is exactly true as websites i have looked at don't say this explicitly. Also my main problem is what happens when for num1, which is an integer variable, i input 'hello', which is a string, and click enter. In that case, C++ doesn't even ask me for an input for some and instead just outputs 0. I am a beginner in C++ and am very confused why this happens as i would expect an error message instead. I am hoping that someone would explain to me the procedure that C++ goes through when dealing with a situation like this, where a string gets stored in an int variable, to better understand inputting in C++. Thanks!
With "Hello" you are putting the cout and cin into an error state where especially cin doesn't accept any further input.
If you want to prevent the user from writing text instead of numbers, you have to check each input character. There are several functions that can check if a key code equals a number or not.

C++ cin prints the variable without me telling it to do that

Introduction
I am trying to code a converter for bin/oct/dec/hex numbers in c++. At first I print a message in a console asking the user to insert the type of conversion he wants to do and, followed by the cin that allows him to enter the conversion and then i ask him for the number followed by the cin that allows him to enter the number.
My problem
My problem is that after the user inserts the conversion, the variable gets printed on the console without me telling it that.
What I've Tried
I looked on the docs and in their example they do it like this:
cout << "Please enter an integer value: ";
cin >> i;
cout << "The value you entered is " << i;
cout << " and its double is " << i*2 << ".\n";
And that is similar to my code(which you will see below).
I also tried to do getline(cin, type) but still the variables would get printed without me coding that.
My code
Faulty code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string type;
int n;
cout << "Insert what type of conversion you want to make(binoct, bindec, binhex, octbin, octdec, octhex, decbin, decoct, dechex, hexbin, hexoct, hexdec): ";
cin >> type;
cout << "Insert the number you want to convert: ";
cin >> n;
return 0;
}
Input
binoct
1001
Output
Insert what type of conversion you want to make(binoct, bindec, binhex,octbin, octdec, octhex, decbin, decoct, dechex,hexbin, hexoct, hexdec):binoct
binoct
Insert the number you want to convert:1001
1001
Expected output:
Insert what type of conversion you want to make(binoct, bindec, binhex,octbin, octdec, octhex, decbin, decoct, dechex,hexbin, hexoct, hexdec):binoct
Insert the number you want to convert:1001
Additional notes
I should mention that before this version of the code I did use cout to print my variables to see if it works but i re-built the code a few times and now there's no cout << type or cout << n inside my code
I looked on stackoverflow and I didn't seem to see anything similar, if this is a duplicate I apologize.
The code is fine, either clean and rebuild your project, or it has something to do with your project / debug settings, that print out the value.
Try Building and Running the Program in release mode.

Can't understand what's wrong with litlle code (getline())

I am a bit ashamed with this, but really I can't see what's not working properly with this code. For now it should only store some book names (hence the array and the getline()), and the first cin indicates how many of them I am going to store. But I don't know why, if I enter a number N for nbBooks, I am only able to enter N-1 book names, and library[0] (last book entered) is just a space.
#include <iostream>
using namespace std;
int main()
{
int nbBooks;
cin >> nbBooks;
string library[nbBooks];
while(nbBooks--) {
getline(cin, library[nbBooks]);
}
cout << library[0];
return 0;
}
I know there must be something with getline(), but even though I did search answers about this I couldn't find any.
arrays must has a Specific size at compile time not at runtime.
this code will issue an error flag: "error C2133: 'library' : unknown size"
if you want to allocate an array with a size assigned at runtime then:
use the memory HEAP:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int nbBooks;
cout << "nBooks: ";
cin >> nbBooks; // nBooks is not defined until runtime
cout << endl;
cin.sync(); // flushing the input buffer
string* library = new string [nbBooks]; // allocating pointer to array on the heap memory not the stack
int i = 0;
while(nbBooks--)
{
cout << "library[" << i << "]: ";
getline(cin, library[i]);
i++;
cin.sync(); // flushing again the buffer remeber "safe programming is the purpose of any programmer"
}
cout << "library[0]: " << library[0] << endl;
// now remember memory of heap is not unallocated by the compiler so it must be fred by the programmer
delete[]library; //dont forget "[]"
return 0;
}
now compile the code and everything will work correctly.
I use cin.sync() right after cin>> nbooks; to ensure FLUSHING the input buffer.
and once again inside the loop after any assignment to the elements I used another to ensure flushing the buffer.
as I know there's an error in getline which doesn't flush the input buffer totally so some data will affect other variable, to overcome this problem we use cin.sync() to ensure emptying the buffer.
Alright, I am a bit confused : a simple cin.ignore() before the getline() function made it work now, while the same thing wasn't working 10 minutes ago (eventhough I was rebuilding and recompiling each time)(and I swear to god I am not idiot enough to forget that ;) )... So sorry for my pretty useless question...
Oh by the way :
while(nbBooks--) {...}
It evaluates the value nbBooks, then decrement it, so no problem here.
Well, the problem is with the \n character which is staying in the buffer after this cin >> nbBooks; line gets executed. The operatot>> method of cin does not accept \n by default thus the newline character is not pulled out from the buffer. So, you have to pull it out, right?. Just add cin.get(); after cin >> nbBooks;. The get() method will extract the \n character. Rest of the code is fine.

new structure crashing in console, why? [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
This will crash console only if I ask the user to input pizza diameter before name.
If i ask for pizza name and then ask for pizza diameter and weight it seems to work fine - this i dont get why.
#include <iostream>
using namespace std;
struct pizza_structure
{
double diameter;
char name[100];
double weight;
};
int main()
{
pizza_structure * ps = new pizza_structure;
cout << "Enter pizza diameter: ";
cin >> ps->diameter;
cout << "Enter pizza name: ";
cin.get(ps->name, 100);
cout << "Enter pizza weight: ";
cin >> ps->weight;
cout << "Name: " << ps->name << ", diameter: " << ps->diameter << ", weight: " << ps->weight;
delete[] ps;
cin.get();
cin.get();
return 0;
}
You are mixing types of input between formatted using cin >> ... and unformatted using cin.get(...)
This goes "wrong" because the formatted input leaves the newline in the input buffer, which is then read as the first character for cin.get(...) - meaning the string is empty, and then when you read weight, it fails to read properly.
You will need to either read the extra newline with a spare cin.get() [and hope the user didn't add a some non-digit character to the input] or manually parse the input using getline and splitting the line yourself [e.g. using stringstream to read out the digits from the line].
Commercial grade UIs will certainly use custom read functions that are more meaningful when it comes to input errors too.
As others have said delete [] is wrong - and in fact there is no reason to use new in the first place for such a small structure.

count specific things within a code in c++

can anyone help me make this more generalised and more pro?
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
// open text file for input:
string file_name;
cout << "please enter file name: ";
cin >> file_name;
// associate the input file stream with a text file
ifstream infile(file_name.c_str());
// error checking for a valid filename
if ( !infile )
{
cerr << "Unable to open file "
<< file_name << " -- quitting!\n";
return( -1 );
}
else cout << "\n";
// some data structures to perform the function
vector<string> lines_of_text;
string textline;
// read in text file, line by
while (getline( infile, textline, '\n' ))
{
// add the new element to the vector
lines_of_text.push_back( textline );
// print the 'back' vector element - see the STL documentation
cout << lines_of_text.back() << "\n";
}
cout<<"OUTPUT BEGINS HERE: "<<endl<<endl;
cout<<"the total capacity of vector: lines_of_text is: "<<lines_of_text.capacity()<<endl;
int PLOC = (lines_of_text.size()+1);
int numbComments =0;
int numbClasses =0;
cout<<"\nThe total number of physical lines of code is: "<<PLOC<<endl;
for (int i=0; i<(PLOC-1); i++)
//reads through each part of the vector string line-by-line and triggers if the
//it registers the "//" which will output a number lower than 100 (since no line is 100 char long and if the function does not
//register that character within the string, it outputs a public status constant that is found in the class string and has a huge value
//alot more than 100.
{
string temp(lines_of_text [i]);
if (temp.find("//")<100)
numbComments +=1;
}
cout<<"The total number of comment lines is: "<<numbComments<<endl;
for (int j=0; j<(PLOC-1); j++)
{
string temp(lines_of_text [j]);
if (temp.find("};")<100)
numbClasses +=1;
}
cout<<"The total number of classes is: "<<numbClasses<<endl;
Format the code properly, use consistent style and nomenclature and throw out the utterly redundant comments and empty lines. The resulting code should be fine. Or “pro”.
Here, I’ve taken the efford (along with some stylistic things that are purely subjective):
Notice that the output is actually wrong (just run it on the program code itself to see that …).
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string file_name;
cout << "please enter file name: ";
cin >> file_name;
ifstream infile(file_name.c_str());
if (not infile) {
cerr << "Unable to open file " << file_name << " -- quitting!" << endl;
return -1;
}
else cout << endl;
vector<string> lines_of_text;
string textline;
while (getline(infile, textline)) {
lines_of_text.push_back(textline);
cout << lines_of_text.back() << endl;
}
cout << "OUTPUT BEGINS HERE: " << endl << endl;
cout << "the total capacity of vector: lines_of_text is: "
<< lines_of_text.capacity() << endl << endl;
int ploc = lines_of_text.size() + 1;
cout << "The total number of physical lines of code is: " << ploc << endl;
// Look for comments `//` and count them.
int num_comments = 0;
for (vector<string>::iterator i = lines_of_text.begin();
i != lines_of_text.end();
++i) {
if (i->find("//") != string::npos)
++num_comments;
}
cout << "The total number of comment lines is: " << num_comments << endl;
// Same for number of classes ...
}
I'm not really sure what you're asking, but I can point out some things that can be improved in this code. I'll focus on the actual statements and leave stylistic comments to others.
cin >> file_name;
To handle file names with spaces, better write
getline(cin, file_name);
int PLOC = (lines_of_text.size()+1);
Why do you claim that there's one more line than there actually is?
if (temp.find("//")<100)
with some complicated comment explaining this. Better write
if (temp.find("//")<temp.npos)
to work correctly on all line lengths.
cout<<"The total number of comment lines is: "<<numbComments<<endl;
Actually, you counted the number of end-of-line comments. I wouldn't call a comment at the end of a statement a "comment line".
You don't count /* */ style comments.
Counting the number of classes as };? Really? How about structs, enums, and plain superfluous semicolons? Simply count the number of occurences of the class keyword. It should have no alphanumeric character or underscore on either side.
Use proper indentation, your code is very difficult to read in its current form. Here is a list of styles.
Prefer ++variable instead of variable += 1 when possible; the ++ operator exists for a reason.
Be consistent in your coding style. If you're going to leave spaces between things like cout and <<, function arguments and the function parantheses do it, otherwise don't, but be consistent. Pick one naming convention for your variables and stick to it. There is a lot about styles you can find on google, for example here and here.
Don't use the entire std namespace, only what you need. User either using std::cout; or prefix all of your cout statements with std::
Avoid needless comments. Everyone knows what ifstream infile(file_name.c_str()); does for example, what I don't know is what your program does as a whole, because I don't really care to understand what it does due to the indentation. It's a short program, so rather than explaning every statement on its own, why not explain what the program's purpose is, and how to use it?
These are all stylistic points. Your program doesn't work in its current form, assuming your goal is to count comments and classes. Doing that is a lot more difficult than you are considering. What if I have a "};" as part of a string for example? What if I have comments in strings?
Don't import the whole std namespace, only things you need from it:
using std::string;
Use a consistent naming convention: decide whether you prefer name_for_a_variable or nameforavariable or nameForAVariable. And use meaningful names: numbComments makes me associate to very different things than would numberOfComments, numComments or commentCount.
If your original code looks like this, I strongly recommend to select a single consistent indentation style: either
if ( ... )
{
...
}
or
if ( ... )
{
...
}
bot not both in the same source file.
Also remove the useless comments like
// add the new element to the vector
This is "only" about the readability of your code, not even touching its functionality... (which, as others have already pointed out, is incorrect). Note that any piece of code is likely to be read many more times than edited. I am fairly sure that you will have trouble reading (and understanding) your own code in this shape, if you need to read it even a couple of months after.
"More professional" would be not doing it at all. Use an existing SLOC counter, so you don't reinvent the wheel.
This discussion lists a few:
http://discuss.techinterview.org/default.asp?joel.3.207012.14
Another tip: Don't use "temp.find("};}) < 100)", use "temp.find("};") != temp.npos;"
Edit: s/end()/npos. Ugh.