I have to create a school library as an OOP assignment. I'm finding it very difficult to understand, my question here is:
int RANGE = total_books;
the total_books should represent the current books in the text file.
The formatting makes it read 3 parts of info (title, author, genre). How can I point to this between functions?
I want to load the program and read the file in order to see how many there are currently (lets say 7 books, so the variable should be 7 * 3 = 21). Then when the user views the file, it will display the 7 books.
Currently it's static: I have it set to 21. if I add another book it will only read the first 7 books. If I set it to 24 and there are 7 books (not 8 as needed) it will crash. I've tried looking on these forums and other places online, got the "C++ Programming in easy steps" book, it's where I got this formatting code but it's not very useful.
#include "stdio.h"
#include "malloc.h"
#include "stdlib.h"
#include "string.h"
#include "conio.h"
#include "fstream"
#include "iostream"
using namespace std;
unsigned int number_of_books = 0; //this is based on the number of books *3
int total_books = number_of_books * 3; //*3 to read 1 more book
class Book
{
private: // properties
char Title[16];
char Author[16];
char Genre[16];
public: // methods
int iDetailsGet(void);
int iDetailsShow(void);
int iRecordWrite(void);
};
int Book::iDetailsGet(void)
{
// prompt for the data
fflush(stdout);
puts("\n \t !USE_UNDERSCORE_FOR_SPACE!");
puts("\n \t Please enter the Book name: ");
fflush(stdin);
scanf("%s", Title, 16);
fflush(stdout);
puts("\n \t Please enter the Author: ");
fflush(stdin);
scanf("%s", Author, 16);
fflush(stdout);
puts("\n \t Please enter the Genre: ");
fflush(stdin);
scanf("%s", Genre, 16);
// Get total number of lines(books)
FILE *infile = fopen("books.txt", "r");
int ch;
while (EOF != (ch = getc(infile)))
if ('\n' == ch)
++number_of_books; // read from variable above but static.
printf("%u\n", number_of_books);
//return to menu
int main();
} // end method definition
int Book::iDetailsShow()
{
system("CLS");
int RANGE = total_books; // should be dynamically read on start up
string tab[RANGE];
int i = 0, j = 0;
ifstream reader("books.txt");
if(!reader)
{
cout << "Error Opening input file" << endl;
return -1;
}
while(!reader.eof())
{
if((i + 1) % 3 == 0) // the 3 read title,author,genre then adds new line
getline(reader, tab[i++], '\n');
else
getline(reader, tab[i++], '\t');
}
reader.close();
i = 0;
while (i < RANGE)
{
cout << endl << "Record Number: " << ++j << endl;
cout << "Title: " << tab[i++] << endl;
cout << "Author: " << tab[i++] << endl;
cout << "Genre: " << tab[i++] << endl;
}
int main();
} // end method definition
// code for the method: iRecordWrite(void)
int Book::iRecordWrite(void)
{
ofstream NewBook("books.txt", ios::app);
if (!NewBook)
{
printf("Error Recording Book");
return -1;
}
NewBook << " " << Title << " " << Author << " " << Genre << endl;
NewBook.close();
int main();
} // end of method deinition
Thanks!
Instead of initialising total_books based on number_of_books when it's declared, you should probably set it after actually reading number_of_books. Variables, whether global or in a scope, don't update themselves dynamically. So, you could have something like this:
int number_of_books = 0;
void read_number_of_books() {
// parse input file for value
total_books = number_of_books * 3;
}
Is that what you're looking for?
Related
The only part of my code that has issue is the part that compares a string that has up to 2000 lines of data with a string that has 1 piece of data (input from the user). I added the else statement to show that the if statement is never true. My teacher was unable to figure out why it would evaluate to false. Can anyone tell me why that statement is always false, and how to fix it?
//
// main.cpp
// Assignment 5
//
//
#include <iostream>
#include <string>
#include <stdlib.h>
#include <iomanip>
#include <fstream>//for fin and fout
#include <string>
using namespace std;
int main()
{
//declare input and output file stream
ifstream fin;//in_s, inStream, input...
string name[2000], inName;//name is the string for the file, inName is the users name
string number[2000];
char again;
cout << "Welcome to the automated phone directory! " << endl << endl;
//Open the file streams and associate with the actual files
fin.open("/Users/ryoncook/Documents/School/Comp Sci/Assignments/Assignment 5/Asn Five_M/phoneNames.txt");
if (fin.fail())
{
cout << "Input file opening failed" << endl;
exit(1);//indicates 1 error occured
}
for(int i=0; i < 2000; i++)//loops until desired maximum size
{
getline(fin,name[i]);//stores the values of the file in the string array
}
fin.close();
//open number file
fin.open("/Users/ryoncook/Documents/School/Comp Sci/Assignments/Assignment 5/Asn Five_M/phoneNums.txt");
if (fin.fail())
{
cout << "Input file opening failed" << endl;
exit(1);//indicates 1 error occured
}
for(int i=0; i < 2000; i++)//loops until desired maximum size
{
getline(fin,number[i]);//stores the values of the file in the string array
}
//Close all open files
fin.close();
do{
cout << "Enter the name of the person you wish to look up: " << endl;
inName.clear();
getline(cin,inName);//reads the name desired as a string
for (int i=0; i < 2000; i++)
{
if (name[i] == inName)//compares input name with file name
{
cout << name[i] << "'s phone number is " << number[i] << endl;//prints result
}
else
{
cout << name[i] << inName;//i ran an else statement to confirm. The out if statement is never evaluated to be true
}
}
cout << "Would you like to find another phone number? (Y or N) " << endl;
cin >> again;
}while (again=='y' || again=='Y');
return 0;
}
//array for phone numbers and array for names that are both strings
//compare the 2 arrays and if they are equal, print
The for loop should find the name that the user entered, and if its in the file, it should select the correct name and phone number.
What actually happens is that even if the name entered is in the file, the statement is never true.
I know that the if statement is the issue because I printed out a few of the name and number strings with different numbers (number[12], name[6], etc.) and they all printed the correct name/number.
This question already has answers here:
Read file line by line using ifstream in C++
(8 answers)
Closed 6 years ago.
I have the following text file from which I am attempting to read each line and then store the integer component and the string component separately. Here is the text file:
RUID Name
4325 name1
RUID Name
5432 name2
6530 name3
RUID Name
1034 name4
2309 name5
Here is the code I attempting to read with:
int main()
{
// Initialize Lists
LinkedList list1, list2, list3;
// Initialize Counter
int counter = 0;
// Entry containers
const int size = 12;
char entry[size];
string name[size];
string RUID[size];
// BEGIN: "read.txt"
// Open
ifstream studDir;
studDir.open("read.txt");
// Read
while (studDir.is_open())
{
if (studDir.eof())
{
cout << "Reading finished" << endl;
break;
}
else if (!studDir)
{
cout << "Reading failed" << endl;
break;
}
studDir.getline(entry, size);
if (entry != "RUID Name")
{
cout << entry << " " << endl;
}
}
return 0;
}
Could anyone recommend a method that would allow me to ignore the "RUID Name" line as well as separate the integer and string portion of the relevant lines. I've tried several strategies with little success. Also I wish to then write the output of the sorted list to a text file.
You should rewrite your loop like this:
// Entry containers
const size_t size = 12;
std::string entry;
string name[size];
string RUID[size];
size_t index = 0;
// ...
while (index < size && std::getline(studDir,entry)) {
if (entry != "RUID Name") {
cout << entry << " " << endl;
std::istringstream iss(entry);
if(!(iss >> RUID[index] >> name[index])) {
std::cout << "Reading failed" << endl;
break;
}
++index;
}
}
#include <iostream>
#include <string.h>
#include <string>
#include <fstream>
using namespace std;
int get_ascii_int(char ch);
int get_offset_ascii(char ch2, int offset);
//int print_string_ints(string test_string);
int method3_substitution_abc();
//above are the function declarations
int main()
{
string test_string;//input of string
char ch = 0;//used in method1
char ch2 = 0;//used in method2
int index1 = 0;//used in for loop method1
int index2 = 0;//used in for loop method2
int offset = 0;//input of how much to offset
int new_ascii = 0;//the new ascii with offset
int ascii_value1 = 0;//the ascii value of the char
int option;//the menu choice of encryption method
int decision;//the decision to save or display
ofstream method1;//method 1 text file
ofstream method2;//method 2 text file
ofstream method3;//method 3 text file
string test_string_copy;//copy of string method 2
//Below is a description of the methods of encryption
cout << "There are three methods of encryption, listed below, to choose from: " << endl;
cout << "1. Converting characters into the corresponding ASCII values. " << endl;
cout << "2. Shifting characters right/left using the ASCII value of the characters ";
cout << "and a set offset amount. " << endl;
cout << "3. Using a reverse alphabet, so each letter will be replaced with the letter ";
cout << "on the opposite end of the alphabet. For example, A would become Z. " << endl;
cout << "Which encryption method would you like to use, 1, 2, 3? ";
cin >> option;
switch (option)
{
case '1':
method1.open("method1.txt");
cout << "Input a word or name: ";
getline(cin, test_string);
for (; index1 < test_string.size(); index1++);
{
ascii_value1 = get_ascii_int(test_string[index1]);
}
cout << "Would you like to display the file or save it, enter 1 for display or 2 for save?";
cin >> decision;
if (decision == '1')
{
cout << "The encrypted code is " << ascii_value1 << endl;
}
else
{
if (method1.is_open())
{
method1 << "The encrpyted code is " << ascii_value1 << endl;
method1.close();
}
else
cout << "Unable to open file." << endl;
}
break;
case '2':
method2.open("method2.txt");
cout << "Input a word or name: ";
getline(cin, test_string);
test_string_copy = test_string;
for (; index2 < test_string_copy.size(); index2++);
{
new_ascii = get_offset_ascii(test_string_copy[index2], ch2);
}
cout << "Would you like to display the file or save it, enter 1 for display or 2 for save?";
cin >> decision;
if (decision == '1')
{
cout << "The encrypted code is " << new_ascii << endl;
}
else
{
if (method2.is_open())
{
method2 << "The encrypted code is " << new_ascii << endl;
method2.close();
}
else
cout << "Unable to open file." << endl;
}
break;
case '3':
method3.open("method3.txt");
method3_substitution_abc();
break;
}
return 0;
}
//listed below are the function definitions
int get_ascii_int(char ch)
{
return ((int)ch);
}
int get_offset_ascii(char ch2, int offset)
{
int new_offset_value;//the value after adding the determined offset to the ascii value of the letter
new_offset_value = (int)ch2 + offset;
(char)new_offset_value;
return (new_offset_value);
}
//int print_string_ints(string test_string)
//{
//for (int i = 0; i < test_string.size(); i++)
//{
//(int)test_string[i++];
//}
//return 0;
//}
int method3_substitution_abc()
{
char test_string[100];
cout << "Enter a name or phrase: ";
cin >> test_string;
if (isupper((int)test_string))
{
int stalpha = 65;//start of alphabet
int endalpha = 90;//end of alphabet
char b[100];//array to reverse the alphabet
for (int i = 0; test_string[i] != '\0'; i++)
{
b[i] = endalpha - (test_string[i] - 65);
}
}
else if (islower((int)test_string))
int stalpha = 97;//start of alphabet
int endalpha = 122;//end of alphabet
char b[100];//array to reverse the alphabet
for (int i = 0; test_string[i] != '\0'; i++)
{
b[i] = endalpha - (test_string[i] - 97);
}
return 0;
}
I am trying to write this encryption program. And I am just getting really confused on why it won't run.
For example the switch statement is not running correctly, it will go to the correct case and then skip the input of the string?
This is my first experience with C++ so I struggle to debug.
I am having issues with saving the file to a text file after the user chooses to save or display? It has to be done after every case in the switch statement.
I also know the for loops I am using are not correct for method 1 and 2? Could someone check those out and tell me what the issue is. I am pretty sure it has to do with the parameters for the for loop.
And I don't know if I should use a string or an array for this? (In the part where the user inputs a string
At least the first problem you've identified (with the switch statement) is pretty simple and clear.
You've defined option as an int, so when you read it it's read as an integer. That means if the user enters 1, it'll have the value 1, which is different from the value '1'. '1' is a character that will (for example) print as 1, but its value is actually 49 in most character sets.
You have two obvious choices: either change option to be a char, so it'll be read as a character instead of an integer, or else change the values in the switch statement from '1', '2', etc., to just 1, 2, etc.
At a guess, the problem you're seeing from getline is a fairly common one when you mix a string extractor (e.g., cin >> my_string;) with std::getline. The string extractor extracts a string from the stream, but leaves the new-line character in the stream buffer. Then when you call std::getline, it reads that new-line as an empty string, so it doesn't wait for you to enter more input.
If you really have to mix the two this way, you probably want to add a call to std::cin.ignore to read and ignore any data up to and including the new-line character. Then when you call std::getline, it'll actually read some data.
What I am trying to do is create a (seemingly) random fact generator, by selecting a random .txt file, containing the fact, and outputting it to the screen. Here is the code:
#include <fstream>
#include <iomanip>
#include <iostream>
#include <cmath>
#include <ctime>
#include <string>
#include <vector>
#include "getQuestion.h"
using namespace std;
int main() {
int mainMenuChoice;
ifstream Bibliography;
//string easyBib;
char randomQuestion;
string easyBib;
string Questions /*[15]*/;
string Answers /*[15]*/;
ifstream inputFile;
//char newline = '\n';
//char chars;
//int linenum = 1;
string line;
char randomQ;
//cout << "%s by Noah" << endl;
cout << "Quiz Menu\n\n";
cout << "1. Play Game!\n";
cout << "2. Bibliography\n";
cout << "3. Developer Info\n";
//cout << "4. Admin Menu\n";
cout << "4. Exit\n";
cout << "Menu Choice: ";
cin >> mainMenuChoice;
switch (mainMenuChoice) {
case 1: {
srand ( time(NULL) );
randomQuestion = rand() % 10 + 1;
randomQ = '0' + randomQuestion;
randomQ = randomQ + '.txt';
inputFile.open(randomQ);
getline(inputFile, line);
vector<string> lines;
for( string line; getline(inputFile,line); )
{
lines.push_back(line);
}
size_t iRandLine = rand() % lines.size();
string randomLine = lines[iRandLine];
cout << "Line " << (iRandLine+1) << ": " << randomLine << endl;
break;
}
case 2: {
inputFile.open("Bib.txt");
//istream& getline (char* s, streamsize n, char \n )
inputFile >> easyBib;
cout << easyBib << endl;;
return(0);
}
case 3: {
cout << "Program made by: XXXX XXXXXXXX" << endl;
cout << "Mrs. XXXXXXX's Period 4 Social Studies Class" << endl;
break;
}
case 4: {
cout << "Thank you for playing!" << endl;
return(0);
}
default: {
cout << "Sorry, Invalid Choice!\n";
return(2);
}
}
return(0);
}
i am also getting this compiler error:
52: error: invalid conversion from 'char' to 'const char*'
52: error: initializing argument 1 of 'void std::basic_ifstream<_CharT, _Traits>::open(const char*, std::_Ios_Openmode) [with _CharT = char, _Traits = std::char_traits<char>]'
Thank you so much everyone.
If it is applicable I am using XCode 3.2.6, and Mac OS X 10.6.8
Please don't ask me to upgrade or download anything, it is a school laptop, and I don't have sudo privileges.
If you know any scripting languages like Python or Perl, you should probably use those instead of C++ for what you're trying to do; they have much more intuitive facilities for what you want to do, and the syntax is much cleaner.
If you're gonna stick with C++, this is what you might consider;
Place every text file inside a folder (let's call it questions), and sets its filename to an integer (no extension).
Generate an integer randomly, possibly with a maximum value (depending on how you're numbering these questions).
If there exists a file in questions named for that integer (i.e. if you draw 41, then if ./questions/41 exists), use it. If not, draw again.
By the way, you wouldn't happen to go to high school on Long Island, would you? If so, I think we might have gone to the same school (though I graduated).
I am currently teaching myself C++ using A C++ for Dummies All-In-One; second edition. TO create this program I am using Qt. I understand it to be a good practice to organize objects and classes in your header files and prospectively your member functions in a .cpp file built in addition to the main.cpp. In this regard I try to run the exercises in this book as such but just recently encountered the following error.
expected primary-expression before '.' token
This error occurs on Lines 31, 32, and 37 so they appear to be relevant to my class member functions specifically.
My main.cpp
#include "controlinginput.h"
#include <QtCore/QCoreApplication>
#include <iostream>
#include <sstream>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// just a basic name-entering
string name;
cout << "What is your name?";
cin >> name;
cout << "Hello " << name << endl;
/* now you are asked for a number
but the computer will allow you to enter anything*/
int x;
cout << endl << "Enter a number! Any Number!" << endl;
cin >> x;
cout << "You choose " << x << endl;
/* now youll be asked for a number again
but the computer will only allow numbers */
cout << endl<< "This time you will ONLY be able to enter a number! " << endl;
cout << "SO, Pick a number! any number!" << endl;
string entered = ControlingInput.enterOnlyNumbers(); // ###Error###
int num = ControlingInput.stringToANumber(entered); // ###Error###
cout << endl << "You entered " << num << endl; // value is displayed
//Now finally we enter the password
cout << endl;
cout << "Please enter a password" << endl;
string password = ControlingInput.EnterPassword(); // ###Error###
cout << "shh... your password is " << password << endl;
return a.exec();
}
I did some research to find that this error indicates a pretty broad range of misuse of syntax. Unfortunately I was unable to find an instance that resembled mine specifically; I was hoping to get some insight from some of the more experienced programmers. If this is a simple issue that is on account of negligence on my end I apologize in advance and appreciate the feedback. I learn better if it gave me allot of trouble as opposed to a little..
Because these include my member functions I have also included my header file and .cpp
controlingInput.cpp (I have included my header file and iostream and sstream here but for some reason the editor was giving me problems on here)
using namespace std;
ControlingInput::ControlingInput()
{
}
int ControlingInput::stringToANumber(string MyString)
{
istringstream converter(MyString); //Holds the string that was passed to this function
int result; //Holds the integer result
//perform the conversion
converter >> result;
return result; //function completes and returns converted string
}
string ControlingInput::enterOnlyNumbers()
{
string numbAsString = ""; // this holds our numeric string
char ch = getch(); // This gets a single character from our user
//Says to keep gettting characters from our user untill user presses enter
while (ch != '\r') // \r is the enter key
{
//This says to add characters only if they are numbers
if (ch >= '0' && ch <='9')
{
cout << ch; // show
numbAsString += ch; // add character to the string
}
ch = getch(); // get the next character from the user
}
return numbAsString;
}
string ControlingInput::EnterPassword()
{
string numbAsString = ""; //this will hold our password string
char ch = getch(); // this gets a single char from our users just like before
//keep gettting characters from the user until enter/return is pressed
while (ch != '\r'); // \r is the enter or return key
{
//for security passwords are displayed as asterisks instead of characters
cout << '*';
//add character input into the password string
numbAsString += ch;
//Get the next character from the user
ch = getch();
}
return numbAsString; // return the user input from this function
And Here is my controlingInput.h
#ifndef CONTROLINGINPUT_H
#define CONTROLINGINPUT_H
#include <iostream>
using namespace std;
class ControlingInput
{
public:
int stringToANumber(string MyString);
string EnterPassword();
string enterOnlyNumbers();
};
#endif // CONTROLINGINPUT_H
Thanks in advance for any feedback.
You are attempting to call instance variables with the class itself as if they were static (which would still be invalid syntax). For this to work properly you need an instance of ControlingInput.
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ControlingInput ctrlInput; //Create instance
...
string entered = ctrlInput.enterOnlyNumbers();
int num = ctrlInput.stringToANumber(entered);
cout << endl << "You entered " << num << endl; // value is displayed
...
string password = ctrlInput.EnterPassword();
cout << "shh... your password is " << password << endl;
return a.exec();
}