C++ reading/writing binary mode - c++

I'm learning C++ at school and in my opinion it's a beautiful language, but I have this annoying problem. In the text book it's written with FILE *text and scanf and printf, and I personally don't like it; I got used to cin and cout or with the << >> better say with the fstream.
So here is my problem:
I have to make an application that writes data in binary mode (I have done it on half of it but it doesn't write in binary mode for some reason)
After I write the city (orasul) the coordinates (x and y) I have to search for them and get those values. (Here I tried to use string.find) but I have to use seekg to search in "binary mode" and get those values separate in a structure.
If you guys can guide me somehow cause I am pretty lost here. And is there a way I can get the sizeof(struct) ?
#include <iostream>
#include <conio.h>
#include <fstream>
#include <string>
#include <limits>
using namespace std;
struct oras {
std::string orasul;
int x;
int y;
} ora;
void functiaPrincipala();
void calculator(float coordonate_x1, float coordonate_y1, float coordonate_x2, float coordonate_y2);
void adaugaOras();
void stergeLocatie();
void repetare();
void main() {
functiaPrincipala();
}
void functiaPrincipala() {
// variabile
int obtiune;
// ofstream fisierOut;
// ifstream fisierIn;
cout << "1) Adauga localitate: " << endl;
cout << "2) Stergerea unei localitati existente: " << endl;
cout << "3) Stergerea tuturor localitatilor existente: " << endl;
cout << "4) Afisarea tuturor localitatilor existente: " << endl;
cout << "5) Calculul distantei a doua localitati: " << endl;
cout << "Introduceti obtiunea: " << endl;
cin >> obtiune;
switch (obtiune) {
case 1:
adaugaOras();
break;
case 2:
stergeLocatie();
break;
case 3:
break;
case 4:
break;
case 5:
break;
}
getch();
}
void calculator(float coordonate_x1, float coordonate_y1, float coordonate_x2, float coordonate_y2) {
float rezultat;
rezultat = sqrt((coordonate_x2 * coordonate_x1) - (coordonate_x2 * coordonate_x1) + (coordonate_y2 * coordonate_y1) - (coordonate_y2 * coordonate_y1));
cout << "Distanta de la orasul 1 la orasul 2 este de: " << rezultat;
}
void adaugaOras() {
int n;
ofstream fisierOutt("textttt.txt", ios::app | ios::binary);
// fisierOutt.open("textttt.txt");
cout << "Cate orase doresti sa introduci: ";
cin >> n;
if (fisierOutt.is_open()) {
for (int i = 0; i < n; i++) {
cout << "Introdu numele orasului: ";
cin >> ora.orasul;
cout << "Introdu coordonatele x: ";
cin >> ora.x;
cout << "Introdu coordonatele y: ";
cin >> ora.y;
fisierOutt << ora.orasul << " " << ora.x << " " << ora.y << endl;
cout << endl << endl;
}
} else {
cout << "Nu am putut deschide fisierul";
}
fisierOutt.close();
cout << endl;
// repetare();
}
void stergeLocatie() {
}
void repetare() {
char obtiune;
cout << "Doriti sa mai adaugati ceva sau sa iesiti?(d/n)";
cin >> obtiune;
if (obtiune == 'd') {
functiaPrincipala();
} else {
exit;
}
}

Like I said in my comment, you can't really seek to a specific entry as all entries are of different sizes.
It can be solved by having a separate index file, where each index entry contains of the position of the entry in the real file. This way, when you need entry X you first seek in the index file to the correct position, read the position, and then use that to seek in the real data file.
This is how many DBM database-managers handle their data.
The entries in the index-file has to be fixed size, for example each entry in the index is of type std::ostream::pos_type, and you use write to write the index, and read to read it.

Check https://stackoverflow.com/a/15452958/2156678 . There asker wanted a way to do search (and update) on binary file and I proposed a simple way to achieve the same.

Related

How to code in C++ mutiple return values to main from mutiple modules and display each modules totals?

I must write a program where the user can choose to practice with topic addition or topic multiplication that starts with a self-driven menu.
It must keep track of questions answered right, wrong and the number of questioned asked.
Which my current program is doing within each module(topic). Example Addition keeps track of the questions while the user is practicing Addition only and Multiplication does the same.
However, they are not being feedback to main, so they are not being added or displayed before the user can select another topic to practice or to exit the program.
Currently it is only to keeping track of the question (right /wrong/ total of questions) for each module (topic).
My goal is for the values to be passed to main and display the total number (right /wrong/ total of questions) before the user exits the program, but at the same time I must display the number of question in the Additional Topic and the Multiplication topic and provide a total.
Example Table of Addition, Multiplication and Totals ?
This is the code I have to start with. Can someone help me in how to code to return values of the (right /wrong/ total of questions) of the two topics and accomplish to display something like the table information.
******************************************************************************* /
#include <stdio.h> /* printf, scanf, puts, NULL */
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <string> // String managment funtions.
#include <iostream> // For input and output
#include <cmath> // For math functions.
#include <math.h>
#include <cstdlib>
using namespace std;
////////////////////////////////////////////////////////////////////////
// Implementing menu driven programs.
// Function Prototypes.
int menu();
void sums();
void products();
int main()
{
srand(time(0));
int option;
do {
option = menu();
switch (option) {
case 1: {
sums();
break;
}
case 2: {
products();
break;
}
default:
cout << "Program exit" << endl;
}
} while (option != 6);
return 0;
}
int menu()
{
cout << "Please select an option" << endl;
cout << "1) Practice with Addition " << endl;
cout << "2) Pratice with Multiplication " << endl;
cout << "3) Exit the program " << endl;
int option;
cin >> option;
return option;
}
void sums()
{
string keepgoing;
unsigned int quantity_total_questions = 0U;
unsigned int quantity_wrong_answers = 0U;
unsigned int quantity_correct_answers = 0U;
do {
const int minValue = 10;
const int maxValue = 99;
int y = (rand() % (maxValue - minValue + 1)) + minValue;
// cout<< " the random number is y "<< y << endl;
int x = (rand() % (maxValue - minValue + 1)) + minValue;
// cout<< " the random number is x "<< x << endl;
cout << "What is " << x << " + " << y << " =" << endl;
int answer;
cin >> answer;
if (answer == (x + y)) {
cout << "Great!! You are really smart!!" << endl;
++quantity_correct_answers;
++quantity_total_questions;
}
else {
cout << "Oh Sorry Try Again." << endl;
++quantity_wrong_answers;
++quantity_total_questions;
}
cout << "Right: " << quantity_correct_answers;
cout << " Wrong: " << quantity_wrong_answers;
cout << " Total Questions: " << quantity_total_questions << endl;
cout << "Do you want to play again? [enter y for yes or n for no]" << endl;
cin >> keepgoing;
} while (keepgoing == "y");
}
void products()
{
{
string keepgoing;
unsigned int quantity_total_questions = 0U;
unsigned int quantity_wrong_answers = 0U;
unsigned int quantity_correct_answers = 0U;
do {
const int minValueOne = 0;
const int maxValueOne = 9;
const int minValueTwo = 10;
const int maxValueTwo = 99;
int y = (rand() % (maxValueOne - minValueOne + 1)) + minValueOne;
// cout<< " the random number is y "<< y << endl;
int x = (rand() % (maxValueTwo - minValueTwo + 1)) + minValueTwo;
// cout<< " the random number is x "<< x << endl;
cout << " What is " << x << " x " << y << " =" << endl;
int answer;
cin >> answer;
if (answer == (x * y)) {
cout << "Great!! You are really smart!!" << endl;
++quantity_correct_answers;
++quantity_total_questions;
}
else {
cout << "Oh Sorry Try Again." << endl;
++quantity_wrong_answers;
++quantity_total_questions;
}
cout << "Right: " << quantity_correct_answers;
cout << " Wrong: " << quantity_wrong_answers;
cout << " Total Questions: " << quantity_total_questions << endl;
cout << "Do you want to play again? [enter y for yes or n for no]" << endl;
cin >> keepgoing;
} while (keepgoing == "y");
}
}
I would create a structure that contains the number of total answers and number of correct answers—the incorrect ones can be inferred—and then pass a reference to an instance of the structure to the respective sums() and products() functions.
Those functions can then populate the structure elements and when they return, your main function can read them out, knowing exactly how many questions were asked, how many were answered, or whatever other information you want to record and retrieve.

Cant seem to work a second for loop with a pointer for an array

I have a simple program that calculates for mpg using arrays and pointers
When I input miles, it works perfectly but when i input gallons I can only input until 5th. any advice?
At first when it was still a for loop it was until 3rd only but when i used try and catch it was until 5th
I tried changing ctr value after the first for loop where i inputted miles but it didnt change. I tried using do while and while loop and still
const int size = 10;
typedef double *pointers;
void Mperg();
void MilesPerrGallon(double *ptr1, double *ptr2);
char displayMenu(char *pt);
int main()
{
char sagot;
char *ptr;
ptr =& sagot;
displayMenu(ptr);
switch(sagot){
case '1':
Mperg();
break;
case '2':
cout << "toit";
break;
default:
cout << sagot << " is invalid";
break;
}
}
void Mperg(){
double miles[size], gallons[size];
int ctr;
pointers milPtr, galPtr;
system("cls");
cout<<"COMPUTING FOR MPG : miles per gallon...\n";
cout<<"MILES\n";
galPtr = &gallons[size];
milPtr = &miles[size];
for(ctr = 0; ctr<size; ctr++){
try{
cout << "miles[" << ctr << "]: ";
cin >> milPtr[ctr];
if(milPtr[ctr] < 100 || milPtr[ctr] > 250){
throw milPtr[ctr];
}
}
catch(double xmilPtr){
cout << milPtr[ctr] << " is invalid!.. 100-250 only\nreenter new value\n";
ctr--;
}
}
system("cls");
do{
for(ctr = 0; ctr<size; ctr++){
try{
cout << "gallons[" << ctr << "]: ";
cin >> galPtr[ctr];
if(galPtr[ctr] < 5 || galPtr[ctr] > 25){
throw galPtr[ctr];
}
}
catch(double xgalPtr){
cout << galPtr[ctr] << " is invalid!.. 5-25 only\nreenter new value\n";
ctr--;
}
}
}while(ctr<size);
}
char displayMenu(char *pt)
{
//add code here
cout << "---------O P T I O N S---------\n";
cout << "[1] Compute Miles Per Gallon" << endl;
cout << "[2] Sorting of Numbers" << endl;
cout << "[3] EXIT" << endl;
cout << "-------------------------------\n";
cout << "Enter your choice: ";
cin >> *pt;
return *pt;
}
Miles
Gallons
galPtr = &gallons[size];
milPtr = &miles[size];
Since size is 10, this:
Sets galPtr to point to the 11th element of gallons.
Set milPtr to point to the 11th element of miles.
That's what the above code means in C++.
Of course, both arrays have only ten values, and attempting to obtain a pointer and using the pointer to modify the 11th, and subsequent, values in both arrays is undefined behavior.
You obviously meant to implement galPtr=gallons and milPtr=miles, here, although there is no real reason to use pointers this way, it doesn't accomplish anything.

C++ Erase-Remove Idiom not working properly?

This post is a continuation on my post from yesterday: How to output a vector.
So I am in the process of writing a short program that will take a list of strings into a vector, export them to a file, view them before outputting them and lastly remove them if possible. I have managed to get all of the functions working properly except for case 3 (remove a book from the list). The errors I am getting in visual studio as follows:
1.) "No instance of the overloaded function "remove" matches the argument list. [LN 76]
2.) "'Remove': function does not take 2 arguments". [LN 76]
As you can probably tell, I am trying to remove by value instead of index. I am still learning here so be gentle, but why exactly am I getting these errors?
Here is my full code:
#include <iostream>
#include <cctype>
#include <ctype.h>
#include <algorithm>
#include <string>
#include <math.h>
#include <windows.h>
#include <iomanip>
#include <vector>
#include <iostream>
#include <sstream>
#include <fstream>
#include <istream>
// common namespace
using namespace std;
int main()
{
int option;
bool iWannaLeave = false;
vector<string> bookCollection;
string entryVal = " ";
int anotherOption;
do
{
cout << "Welcome to MyBook! - A text recorder framework application." << endl;
cout << "-----------------------------------------------------------" << endl;
cout << "Main Menu:" << endl;
cout << "1 - Add a book to the collection." << endl;
cout << "2 - Display all books currently in the collection." << endl;
cout << "3 - Remove books from the collection." << endl;
cout << "4 - Write stored collection to file." << endl;
cout << "5 - Quit" << endl;
cout << "Make your selection: ";
cin >> option;
cin.ignore();
switch (option)
{
case 1:
{
bool wannaMoreBooks = false;
// the next loop will execute at least one time so you could enter a book
do
{
wannaMoreBooks = false;
cout << "Add a book title to the collection: ";
getline(cin, entryVal);
bookCollection.push_back(entryVal);
cout << "Would you like to enter another book?(1 - yes, 0 - no): ";
cin >> anotherOption;
cin.ignore();
if (anotherOption == 1) wannaMoreBooks = true;
} while (wannaMoreBooks == true);
}
break;
case 2:
{
for (int i = 0; i < bookCollection.size(); i++)
cout << bookCollection[i] << " | ";
cout << endl;
break;
}
case 3:
{
string vecVal;
cout << "Enter the value you would like to remove: " << endl;
cin >> vecVal;
bookCollection.erase(remove(bookCollection.begin(), vecVal), bookCollection.end());
}
// remove a book from the collection
break;
case 4:
{
ofstream fileOut("Collection.txt");
fileOut << "Your MyBook Collection: [Begin] - | ";
auto first = true;
for (string x : bookCollection)
{
if (!first) { fileOut << " | "; }
first = false;
fileOut << x;
}
fileOut << " | - [End]" << endl;
cout << "Collection.txt has been successfully written." << endl;
break;
}
case 5:
{
//Nested IF to kill program properly
int quitVar;
cout << "Are you sure you want to exit the program?: ";
cin >> quitVar;
cin.ignore();
if (quitVar == 1)
{
cout << "The program will now be terminated." << endl;
iWannaLeave = true;
}
else if (quitVar == 0) cout << "Returning to the main menu." << endl;
}
break;
}
} while (iWannaLeave == false);
return 0;
}
I am aware that this is no where near perfect code so in addition to finding out why I am getting these errors I would also like some constructive criticism as to how I can improve.
Additionally: If I wanted to go about using functions in a header file as opposed to a switch, would I just move the case contents to a header file?
Thanks in advance! :)
Virtually all STL-functions take one or more pairs of iterators. Since you just pass begin, there is no viable overload. You need to call
remove(bookCollection.begin(), bookCollection.end(), vecVal)
It is always a good idea to check the reference, which typically also contains a basic usage example.

get string array from text list c++

my text file was like
123456123456
Jason
uk
012456788
1000
456789456789
david
uk
012456788
1000
i'm trying to get the data from a text file and save it into arrays
however when i want to store the data from the text file into array it loop non-stop.
what should i do ?
the problem exiting in looping or the method i get the data from text file ?
code:
#include <iostream>
#include <fstream>
using namespace std;
typedef struct {
char acc_no[12];
char name[30];
char address[50];
char phone_no[12];
double balance;
} ACCOUNT;
//function prototype
void menu();
void read_data(ACCOUNT record[]);
int main() {
ACCOUNT record[31]; //Define array 'record' which have maximum size of 30
read_data(record);
}
//--------------------------------------------------------------------
void read_data(ACCOUNT record[]) {
ifstream openfile("list.txt"); //open text file
if (!openfile) {
cout << "Error opening input file\n";
return 0;
} else {
int loop = -1; //size of array
cout << "--------------Data From File--------------"<<endl;
while (!openfile.eof()) {
if (openfile.peek() == '\n')
openfile.ignore(256, '\n');
openfile.getline(record[++loop].acc_no, 12);
openfile.getline(record[loop].name, 30);
openfile.getline(record[loop].address, 50);
openfile.getline(record[loop].phone_no, 12);
openfile >> record[loop].balance;
}
openfile.close(); //close text file
for (int i = 0; i <= loop + 1; i++) {
cout << "Account " << endl;
cout << "Account No. : " << record[i].acc_no << endl;
cout << "Name : " << record[i].name << endl;
cout << "Address : " << record[i].address << endl;
cout << "Phone Number : " << record[i].phone_no << endl;
cout << "Balance : " << record[i].balance << endl;
}
}
}
UPDATE:
The OP didn't properly cite the correct format in his data file. This answer is only valid up until the last iteration.
Don't use .eof() - that's more applicable to when you want to open the file and read it by characters.
A better way would be to use the insertion operator >> as follows:
#define ARR_SIZE 31
ACCOUNT temp;
ACCOUNT record[ARR_SIZE];
int i=0;
while(i < ARR_SIZE) {
openfile >> temp.acc_no >> temp.name >> temp.address >> temp.phone_no >> temp.balance;
record[i] = temp;
i++;
}
Of course, even better is to use std::string to hold the values from the input file, in addition to using std::vectors instead of arrays.

How to use a dynamically sized array of structs?

I have to make my homework. It is console application which uses an array of structs that keep information about a computer(brand, year of manufactoring, weight and inventory number). So I wrote a completely working program, but I want to use a dynamic array, because I dont know how many records the user will input.
Is there way to do this. To add new records in array until the user say n/N? Any suggestions?
This is my version of program:
#include "stdafx.h"
#include <iostream>
using namespace std;
struct ComputerInfo
{
char computerMark[20], invertarNumber[6];
unsigned int year;
float weight;
};
ComputerInfo computerArray[300];
ComputerInfo AddComputers(ComputerInfo compterArray[], int counter)
{
cout << "Enter mark of the computer: ";
cin >> computerArray[counter].computerMark;
cout << "Enter year of establish: ";
cin>> computerArray[counter].year;
while ((computerArray[counter].year < 1973)
|| (computerArray[counter].year > 2013))
{
cout << "INVALID YEAR!!!" << endl;
cout << "Enter year of establish: ";
cin>> computerArray[counter].year;
}
cout << "Enter computer weidth: ";
cin >> computerArray[counter].weight;
cout << "Enter computer invertar number(up to six digits): ";
cin >> computerArray[counter].invertarNumber;
return computerArray[counter];
}
void ShowRecords()
{
int counter = 0;
while (computerArray[counter].year != 0)
{
cout << "Mark: " << computerArray[counter].computerMark << endl;
cout << "Year: " << computerArray[counter].year << endl;
cout << "Weidth: " << computerArray[counter].weight << endl;
cout << "Inv. number: " << computerArray[counter].invertarNumber << endl << endl;
counter++;
}
}
void MoreThanTenYearsOld(ComputerInfo computerArray[])
{
int counter = 0;
float counterOldComputers = 0;
float computerPer = 0;
while (computerArray[counter].year == 0)
{
if (computerArray[counter].year <= 2003)
{
counterOldComputers++;
}
counter++;
}
computerPer = counterOldComputers / 3;
cout << endl;
cout << "Percantage of old computers is: " << computerPer << endl;
}
int main()
{
int counter = 0;
float computerPer = 0;
char answer = 'y';
for (int i = 0; i <= 299; i++)
{
strcpy(computerArray[i].computerMark,"");
}
while((answer == 'Y') || (answer == 'y'))
{
computerArray[counter] = AddComputers(computerArray, counter);
cout << endl;
cout << "Do you want to enter more records (Y/N): ";
cin >> answer;
cout << endl;
counter++;
}
MoreThanTenYearsOld(computerArray);
return 0;
}
Yes. Instead of your array, use
std::vector<ComputerInfo> computerArray;
and you can add as many objects as you want:
ComputerInfo c;
// read the data
computerArray.push_back(c);
now, computerArray[0] will have the info in c.
You'll need to #include <vector>.
Also, instead of char computerMark[20] you can use a std::string.
You have two options:
1) Use std::vector instead of an array. This is a very powerful tool and certainly worth learning how to use.
2) Dynamically allocate the array and resize it as you add more items. Basically this means writing your own version of std::vector. This is a good way to strengthen your programming skills. You will learn what goes into writing standard classes and functions. However, I advise using std::vector in more serious programming because it has already been thoroughly tested and debugged.