How to read a text file into parallel arrays - c++

I must have a function that reads card information from a text file
(cards.txt) and insert them to parallel arrays in the main program using a pointer.
I have successfully read the text file, but cannot successfully insert the info to the arrays.
#include <iostream>
#include <stream>
#include <string>
using namespace std;
void readCards();
int main() {
ifstream inputFile;
const int SIZE = 10;
int id[SIZE];
string beybladeName[SIZE];
string productCode[SIZE];
string type[SIZE];
string plusMode[SIZE];
string system[SIZE];
readCards();
return 0;
}
void readCards() {
ifstream inputFile;
const int SIZE = 10;
int id[SIZE];
string beybladeName[SIZE];
string productCode[SIZE];
string type[SIZE];
string plusMode[SIZE];
string system[SIZE];
int i = 0;
inputFile.open("cards.txt");
cout << "Reading all cards information..." << endl;
if (inputFile) {
while (inputFile >> id[i] >> beybladeName[i] >> productCode[i] >> type[i] >> plusMode[I] >>
system[I]) {
i++;
}
cout << "All cards information read." << endl;
}
inputFile.close();
for (int index = 0; index < SIZE; index++) {
cout << "#:" << id[index] << endl;
cout << "Beyblade Name: " << beybladeName[index] << endl;
cout << "Product Code: " << productCode[index] << endl;
cout << "Type: " << type[index] << endl;
cout << "Plus Mode: " << plusMode[index] << endl;
cout << "System: " << system[index] << endl;
cout << " " << endl;
}
}

The main problem is that you have two sets of arrays, one in main, and one in readCards. You need one set of arrays in main and to pass those arrays (using pointers) to readCards. Like this
void readCards(int* id, string* beybladeName, string* productCode, string* type, string* plusMode, string* system);
int main()
{
ifstream inputFile;
const int SIZE = 10;
int id[SIZE];
string beybladeName[SIZE];
string productCode[SIZE];
string type[SIZE];
string plusMode [SIZE];
string system [SIZE];
readCards(id, beybladeName, productCode, type, plusMode, system);
return 0;
}
void readCards(int* id, string* beybladeName, string* productCode, string* type, string* plusMode, string* system)
{
...
}

Related

Reading from a text file into an array

I'm just a beginner for C++
I want to read the text file (maximum of 1024 words) into an array, and I need to ignore all single character words. Can you guys help me to discard words that are single characters to avoid symbols, special characters.
This is my code:
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
const int SIZE = 1024;
void showArray(string names[], int SIZE){
cout << "Unsorted words: " << endl;
for (int i = 0; i < SIZE; i++){
cout << names[i] << " ";
cout << endl;
}
cout << endl;
}
int main()
{
int count = 0;
string names[SIZE];
// Ask the user to input the file name
cout << "Please enter the file name: ";
string fileName;
getline(cin, fileName);
ifstream inputFile;
inputFile.open(fileName);
// If the file name cannot open
if (!inputFile){
cout << "ERROR opening file!" << endl;
exit(1);
}
// sort the text file into array
while (count < SIZE)
{
inputFile >> names[count];
if (names[count].length() == 1);
else
{
count++;
}
}
showArray(names, SIZE); // This function will show the array on screen
system("PAUSE");
return 0;
}
If you change names into a std::vector, then you can populate it using push_back. You could fill names like this.
for (count = 0; count < SIZE; count++)
{
std::string next;
inputFile >> next;
if (next.length() > 1);
{
names.push_back(next);
}
}
Alternatively you could fill all the words into names and then utilize the Erase–remove idiom.
std::copy(std::istream_iterator<std::string>(inputFile),
std::istream_iterator<std::string>(),
std::back_inserter<std::vector<std::string>>(names));
names.erase(std::remove(names.begin(), names.end(),
[](const std::string& x){return x.length() == 1;}), names.end());

Extra string outputs if user input is more than one word

This is my first time asking a question on here, so be gentle lol. I wrote up some code for an assignment designed to take information from a (library.txt datatbase) file, store it in arrays, then access/search those arrays by title/author then output that information for the user based on what the user enters.
The issue I am having is, whenever the user enters in a search term longer than one word, the output of "Enter Q to (Q)uit, Search (A)uthor, Search (T)itle, (S)how All: " is repeated several times before closing.
I am just looking to make this worthy of my professor lol. Please help me.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
struct Book
{
string title;
string author;
};
int loadData(string pathname);
char switchoutput();
void showAll(int count);
int showBooksByAuthor(int count, string name);
int showBooksByTitle(int count, string title);
int FindAuthor(int count, string userinput);
int FindTitle(int count, string userinput);
void ConvertStringToLowerCase(const string orig, string& lwr); //I found this program useful to convert any given string to lowercase, regardless of user input
const int ARRAY_SIZE = 1000;
Book books[ARRAY_SIZE];
int main()
{
string pathname;
string name;
string booktitle;
int count = 0;
int counta = 0;
int countt = 0;
char input = 0;
cout << "Welcome to Jacob's Library Database." << endl;
cout << "Please enter the name of the backup file: " ;
cin >> pathname;
count = loadData(pathname);
cout << count << " records found in the database." << endl;
while (toupper(input != 'Q'))
{
input = switchoutput(); // function call for switchoutput function
switch (input)
{
case 'A':
cout << "Author's Name: ";
cin >> name;
counta = showBooksByAuthor(count, name);
cout << counta << " records found." << endl;
break;
case 'T':
cout << "Book Title: ";
cin >> booktitle;
countt = showBooksByTitle(count, booktitle);
cout << countt << " records found." << endl;
break;
case 'S':
showAll(count);
break;
case 'Q':
break;
}
}
//Pause and exit
cout << endl << "Press 'ENTER' to quit";
getchar();
getchar();
return 0;
}
int loadData(string pathname) //loading data into the array of structs
{
ifstream inFile;
inFile.open(pathname);
if (!inFile) {
cout << "Error, could not read into file. Please re-compile." << endl;
system("PAUSE");
exit(1); //if not in file, exit;
}
int i = 0;
while (!inFile.eof()) {
getline(inFile, books[i].title);
getline(inFile, books[i].author);
i++;
}
return i;
}
char switchoutput() //seperate output function to get my characteroutput constantly resetting and returning the uppercase version for my switch
{
char input;
cout << "Enter Q to (Q)uit, Search (A)uthor, Search (T)itle, (S)how All: ";
cin >> input;
return toupper(input);
}
int showBooksByAuthor(int count, string name)
{
int authorcount = 0;
authorcount = FindAuthor(count, name);
return authorcount;
}
int showBooksByTitle(int count, string title)
{
int titlecount = 0;
titlecount = FindTitle(count, title);
return titlecount;
}
void showAll(int count)
{
for (int i = 0; i < count; i++)
{
cout << books[i].title << " (" << books[i].author << ")" << endl;
}
}
int FindAuthor(int count, string userinput)
{
int authorcount = 0;
string stringlower, arraylower;
int num;
// called upon function to lowercase any of the user inputs
ConvertStringToLowerCase(userinput, stringlower);
for (int i = 0; i < count; ++i) //this function's count determines at which locations to output the author and names (an argument from books by author)
{
// called upon function to lowercase any of the stored authors'
ConvertStringToLowerCase(books[i].author, arraylower);
num = arraylower.find(stringlower); // searches string for userinput (in the lowered array) and stores its value
if (num > -1) // you can never get a -1 input value from an array, thus this loop continues until execution
{
cout << books[i].title << " (" << books[i].author << ")" << endl; //cout book title and book author
authorcount++; //count
}
}
return authorcount;
}
int FindTitle(int count, string userinput) //same as previous but for titles
{
int titlecount = 0;
string stringlower, arraylower;
int num;
ConvertStringToLowerCase(userinput, stringlower);
for (int i = 0; i < count; ++i)
{
ConvertStringToLowerCase(books[i].title, arraylower);
num = arraylower.find(stringlower);
if (num > -1)
{
cout << books[i].title << " (" << books[i].author << ")" << endl;
titlecount++; //count
}
}
return titlecount;
}
void ConvertStringToLowerCase(const string orig, string& lwr) // I found this from another classmate during tutoring, I thought to be useful.
{
lwr = orig;
for (int j = 0; j < orig.length(); ++j) //when called upon in my find functions, it takes the string and convers the string into an array of lowercase letters
{
lwr[j] = tolower(orig.at(j));
}
}

String with character spacing

This program works EXCEPT that it does not allow a space between the first and last name. Below is an example as to what I am talking about:
Link to Picture
Can someone please help me to fix this? I believe it is in string playerName as it will not accept a space between the first and last name.
#include "stdafx.h"
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
// Structure to hold the Player Data
struct Player {
string playerName;
int playerNumber;
int pointsScored;
};
// Function Prototypes
void getPlayerInfo(Player &);
void showInfo(Player[], int);
int getTotalPoints(Player[], int);
void showHighest(Player[], int);
int main(int argc, char *argv[])
{
const int N = 12;
Player players[N];
for (int i = 0; i<N; i++) {
cout << "\nPLAYER #" << i + 1 << "\n";
cout << "---------\n";
getPlayerInfo(players[i]);
}
showInfo(players, N);
int totalPoints = getTotalPoints(players, N);
cout << "TOTAL POINTS: " << totalPoints << "\n";
cout << "The player who scored the most points is :";
showHighest(players, N);
cout << "\n";
system("pause");
return 0;
}
void getPlayerInfo(Player &P) {
cout << "Player Name:";
//cin >> P.playerName; **CHANGED THIS**
cin.ignore(std::numeric_limits<std::streamsize>::max(), ' ');
std::getline(std::cin, P.playerName); **TO THIS**
do {
cout << "Player Number:";
cin >> P.playerNumber;
if (P.playerNumber<0)
cout << "invalid Input\n";
} while (P.playerNumber<0);
do {
cout << "Points Scored:";
cin >> P.pointsScored;
if (P.pointsScored<0)
cout << "invalid Input\n";
} while (P.pointsScored<0);
}
void showInfo(Player P[], int N) {
cout << "\nNAME" << "\t\tNUMBER" << "\t\tPOINTS SCORED" << "\n";
for (int i = 0; i<N; i++)
cout << P[i].playerName << "\t\t" << P[i].playerNumber << "\t\t" << P[i].pointsScored << "\n";
}
int getTotalPoints(Player P[], int N) {
int Points = 0;
for (int i = 0; i<N; i++)
Points += (P[i].pointsScored);
return Points;
}
void showHighest(Player P[], int N) {
int HighestPoint = P[0].pointsScored;
string Name = P[0].playerName;
for (int i = 1; i<N; i++) {
if (HighestPoint<P[i].pointsScored) {
HighestPoint = P[i].pointsScored;
Name = P[i].playerName;
}
}
cout << Name;
}
When std::cin uses operator>> to insert into a std::string, it stops reading at space (' ') characters. Use std::getline instead.
std::getline(std::cin, P.playerName); //read everything up to '\n'
The problem is in this code:
void getPlayerInfo(Player &P) {
cout << "Player Name:";
cin >> P.playerName;//<<----
cin treats ' ' (space) as a delimiter. If you want to have an input with ' ' (space) you need to use: (thanks to #James Root)
//before doing get line make sure input buffer is empty
see also: https://stackoverflow.com/a/10553849/3013996
cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
std::getline(std::cin,P.playerName);

Segmentation fault using string pointer

I'm a C++ newbie, I'm trying to put in practice pointers with strings. The program I have made is just to store strings the user types in the command line. But I'm getting segfault, not sure why.
This is the code:
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
//This code is meant to learn how to use pointers and strings
//Ask the user for who are they in the family and save it in string array!
void print_string (string* Value, int const nSize);
int get_names(string* Family_input);
int main ( int nNumberofArgs, char* pszArgs[])
{
cout << "Tis program stores your family members\n";
cout<< "Type the names and write 0 to exit\n";
string familia_string;
string* familia = &familia_string;
int family_number;
family_number=get_names(familia);
cout << "The family members are: ";
print_string(familia, family_number);
cout << endl;
return 0;
}
int get_names(string* Family_input)
{
int i=0;
string input="";
string old_input="";
while (input!="0")
{
cout << "type " << i <<" member\n";
//cin >> *(Family_input+i);
//input=*(Family_input+i);
cin >> input;
*(Family_input + old_input.length()) = input;
old_input=input;
i++;
}
return i;
}
void print_string (string* Value, int const nSize)
{// I don't want to &psValue to be changed!
for (int i=0; i<nSize; i++)
{
cout << *(Value+i) << " ";
//&psValue++;
}
}
I'm not sure if it's because I'm not taking correctly the size of the string, or I'm not using correctly the pointer or is that I have to allocate memory before using the offset.
As #kleszcz pointed out already, the line
*(Family_input + old_input.length()) = input;
is wrong. You are accessing memory that you are not supposed to.
The easiest fix is to change get_names slightly:
int get_names(string* Family_input)
{
int i=0;
string input="";
while (input!="0")
{
cout << "type " << i <<" member\n";
cin >> input;
*Family_input += input; // Just keep on appending to the input argument.
*Family_input += "\n"; // Add a newline to separate the inputs.
i++;
}
return i;
}
Also change print_string to:
void print_string (string* Value)
{
cout << *Value;
}
Of course, print_string has become so simple, you don't need to have it at all.
You could change get_names to use a reference argument instead of a pointer argument. This is a better practice.
int get_names(string& Family_input)
{
int i=0;
string input="";
while (input!="0")
{
cout << "type " << i <<" member\n";
cin >> input;
Family_input += input; // Just keep on appending to the input argument.
Family_input += "\n"; // Add a newline to separate the inputs.
i++;
}
return i;
}
Then, change the call to get_names. Instead of using
family_number=get_names(familia);
use
family_number=get_names(familia_string);
You get seg fault because you haven't allocate memory for an array of strings.
*(Family_input + old_input.length()) = input;
This is total nonsense. If you'd have an array you increment index only by one not by length of string.
If you want to save different names in different string objects I would suggest:
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
void print_string(string** Value, int const nSize);
void get_names(string** Family_input, int count);
int main(int nNumberofArgs, char* pszArgs[]) {
cout << "This program stores your family members\n";
int family_number;
cout << "Types the number of family members";
cin >> family_number;
/*allocate the number of string pointers that you need*/
string** familia = new string*[family_number];
cout << "Type the names\n";
get_names(familia, family_number);
cout << "The family members are: ";
print_string(familia, family_number);
cout << endl;
return 0;
}
void get_names(string** Family_input, int count) {
for(int i = 0 ; i < count; i++){
cout << "type " << i << " member\n";
/*create a string obj in the heap memory*/
string *input = new string ("");
// using that way you get only a single word
cin >> *input;
/*create a string object on the stack and put its pointer in the family_array*/
Family_input[i] = input;
}
}
void print_string(string** Value, int const nSize) {
for (int i = 0; i < nSize; i++) {
cout << *(Value[i]) << " ";
}
}

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.