How to print specific array entries from a .txt file in C++? - c++

First, I'm very new to coding in C++.
So, I have a .txt file, with names and numbers--here's an example.
chris 5
tara 7
Sam 13
Joey 15
I would like to use this code to retrieve the names and numbers, but how does one print specific array entries instead of just the variables name and number (I want it to show the name and the number on the screen)?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
string name;
int number;
struct sEntry
{
std::string name;
int number;
};
sEntry entries[256];
std::ifstream fin("input.txt"); // opens the text file
int nb_entries; // Keeps track of the number of entries read.
for (nb_entries = 0; fin.good() && nb_entries < 256; nb_entries++) // Keep going until we hit the end of the file:
{
fin >> entries[nb_entries].name;
fin >> entries[nb_entries].number;
cout << "Here, "<< name <<" is name.\n";
cout << "Here, "<< number <<" is number.\n";
}
}

You're writing out name and number, but those aren't the variables you've read. You've read array entries.
Getting it working as simply as possible just comes down to changing your cout lines to be:
cout << "Here, " << entries[nb_entries].name << " is name.\n";
cout << "Here, " << entries[nb_entries].number << " is number.\n";
No need for a std::vector, ther's nothing wrong with how you've done it.

Instead of using a plain C array of sEntry you should use a C++ vector instead (which can change size dynamically). Then you create a new sEntry instance inside your loop (which can just use fin.eof() as termination condition then) and use the operator>>() to assign the values. Afterwards you use push_back() to add the sEntry instances to your vector.
You need to use the sEntry.name, sEntry.number fields for output on the screen, name and number as shown in your code won't ever receive values.
#include <vector>
#include <string>
#include <iostream>
struct sEntry
{
std::string name;
int number;
};
int main() {
string name;
int number;
std::vector<sEntry> entries;
std::ifstream fin("input.txt"); // opens the text file
// int nb_entries; // Keeps track of the number of entries read. -> not necessary, use entries.size()
while(!fin.eof()) // Keep going until we hit the end of the file:
{
sEntry entry;
fin >> entry.name;
fin >> entry.number;
cout << "Here, "<< entry.name <<" is name.\n";
cout << "Here, "<< entry.number <<" is number.\n";
entries.push_back(entry);
}
}

Related

More appropriate way to loop input from a file?

I want to be able to loop this file opening and closing to continually search for names.
The first time is no problem and output is what is expected then, when choosing y for yes, an output loop occurs.
Any ideas as to why this would happen? The logic seems more than correct.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string boys, girls, name;
int rank;
char end = 'n';
while (end != 'y' || end != 'Y')
{
cout << "Enter a name to search";
cin >> name;
ifstream input;
input.open("Names2016");
if (input.fail())
cout << "Failed to open file.\n";
while (!input.eof())
{
input >> rank >> boys >> girls;
if (boys == name)
cout << name << " ranks " << rank << " among boys.\n";
if (girls == name)
cout << name << " ranks " << rank << " among girls.\n";
}
input.close();
cout << "Would you like to search another name?\n"
<< "Enter Y for yes or N for no.\n";
cin >> end;
}
return 0;
}
There are a some of things you can do to make this code better,
The first is to use ifstreams and do file input/output the proper idiomatic way in a loop, don't use .eof() to check for end of file in a loop condition (the answer linked in the comments is a good place to start if you want to know why),
The second thing you want to check for validity of the file with a simple if (!file) its much cleaner IMO.
The third thing is, when you have a local file handle like you do in your code, then you can just let it go out of scope and let the destructor cleanup the file and close() it, it's the C++ RAII way of doing things (notice that I have removed the open() method to the constructor call (which does the same thing)
Use cerr instead of cout to report errors
Use char instead of int to represent characters
Not a big change, but using std::toupper like advised in the other answer's comments is a good readable way to check for uppercase and lowercase values at the same time
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
string boys, girls, name;
int rank;
char end = 'n';
while (std::toupper(end) == 'Y')
{
cout << "Enter a name to search";
cin >> name;
ifstream input{"Names2016"};
// change here
if (!input) {
cerr << "Failed to open file.\n";
}
while (input >> rank >> boys >> girls)
{
if (boys == name)
cout << name << " ranks " << rank << " among boys.\n";
if (girls == name)
cout << name << " ranks " << rank << " among girls.\n";
}
// change below, just let the file handle go out of scope and close
// input.close();
cout << "Would you like to search another name?\n"
<< "Enter Y for yes or N for no.\n";
cin >> end;
}
return 0;
}
But you can do better on the I/O if your file isn't guaranteed to change over different iterations (in which case you probably need to make sure that there is no race anyway, so I am assuming the file does not change much). Read in the file once and save that information to be used later
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <unordered_map>
#include <vector>
using namespace std;
int main()
{
string boys_name, girls_name, name;
int rank;
char end = 'n';
ifstream input{"Names2016"};
if (!input) {
cerr << "Failed to open file" << endl;
}
// preprocess the information and store it in a map
// making a map from string to vector because it is unclear whether
// there is a 1-1 mapping from the name to the rank for each name
unordered_map<string, vector<int>> boys;
unordered_map<string, vector<int>> girls;
while (input >> rank >> boys_name >> girls_name) {
boys[boys_name].push_back(rank);
girls[girls_name].push_back(rank);
}
while (std::toupper(end) == 'Y')
{
cout << "Enter a name to search";
cin >> name;
// use the map to do the lookup, much faster than reading
// the entire file over and over again
}
return 0;
}
First of all, what is this supposed to mean int end = 'n'; Are you assigning an integer with a character value?!
And why are you opening the same file inside the loop. You should probably open it only once at the beginning of the program.
And the eof doesn't have what to check for, because you have to read from a file to reach its end.

Keep getting "member reference base type 'string [1000]' is not a structure or union" error and dont know how to fix it?

This program reads an SSN from the user and checks if it matches an SSN in a text file provided. Tried switching the array to a vector and it didnt work. Tried putting the array in the structure function and using info:: but nothing seems to work. I know this is pretty basic but I cant get it, thanks.
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char* argv[]){
struct info{
string SSN;
string firstName;
string lastName;
};
string list[1000];
string userSSN;
char x;
fstream input(argv[1]);
int i = 0;
while(!input.eof()){
input >> list.x[i] >> list.SSN[i] >> list.firstName[i] >> list.lastName[i];
i++;
}
input.close();
cout << "Input a SSN:" << endl;
cin >> userSSN >> endl;
for(int k = 0; k < i; k++){
if(userSSN.compare(list.SSN[k]) == 0){
cout << "Found at location " << k << endl;
}
}
}
list is just an array of 1000 std::strings. It looks like you need it to be of type info. Even that won't solve your problems as info has no member named x. After that, to access a member of info in an array would be like
list[i].SSN
not
list.SSN[i]
There are so many things wrong with this code that I don't know where to start. Let's see:
Using using namespace std; is almost always a bad idea, and if you have an identifier list, then it's even worse because it conflicts with std::list.
Using std::string without #include <string> is not guaranteed to work. It may work if you include some other standard header, but don't rely on it.
Your variable x is unused.
string list[1000]; should probably be info list[1000];.
list.SSN[i] et al should probably be changed to list[i].SSN.
list.x[i] does not make sense at all and can probably be removed. (Or you meant to read into the otherwise unused x to skip parts of the file.)
You cannot read from std::cin into std::endl. Remove std::endl from that line.
Using std::string's compare function is pretty strange here, just use ==.
The issues in your code were already pointed out in other's answers. I'll show you a "working" example:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using std::string;
using std::vector;
using std::cout;
using std::cin;
struct info {
char x; // You were reading that from the file so I added it
string SSN;
string firstName;
string lastName;
friend std::istream &operator>>( std::istream &is, info &i ) {
// maybe you should check data input somehow...
is >> i.x >> i.SSN >> i.firstName >> i.lastName;
return is;
}
};
int main(int argc, char* argv[]) {
// check if a file name has been passed as a parameter
string file_name;
if ( argc < 2 ) {
cout << "Please, enter the input file name:\n";
cin >> file_name;
}
else
file_name = argv[1];
std::ifstream input(file_name);
if ( !input ) {
std::cerr << "Error. Unable to open file: " << file_name << '\n';
exit(-1);
}
// Just use a vector to store all the structs
vector<info> my_list;
info temp_info;
while( input >> temp_info ) {
my_list.push_back(temp_info);
}
input.close();
cout << "Input a SSN: ";
string userSSN;
cin >> userSSN;
// That's not cheap. You may want to change the container or sort it
for ( int k = 0; k < my_list.size(); k++ ) {
if ( userSSN == my_list[k].SSN ) {
cout << "Found at location " << k << '\n';
}
}
return 0;
}

reading row from text file into two vectors c++

I am trying to read the two words "kelly 1000" in the text file "players", into vectors players and balances respectively. Don't know why it's not working?
string name = "kelly";
int main()
{
int num =0;
vector<string> players;
vector<int> balances;
ifstream input_file("players.txt");
while(!input_file.eof())
{
input_file >> players[num];
input_file >> balances[num];
num++;
}
for(size_t i = 0; i=players.size(); i++)
{
if(name==players[i])
cout << "Welcome " << name << ", your current balance is " << balances[i] << "$." << endl;
else
break;
}
With operator[] you can only access existing elements. Going out of bounds invokes undefined behaviour. Your vectors are empty and you need to use push_back method to add elements to them.
Second problem is while (!file.eof()) anti-pattern. It'll typicaly loop one to many times because the read of last record doesn't neccesarily trigger eof. When reading from streams, always check whether input succeeded before you make use of values read. That's typicaly done by using operator>> inside loop condition.
string temp_s;
int temp_i;
while (input_file >> temp_s >> temp_i) {
players.push_back(temp_s);
balances.push_back(temp_i);
}
This way the loop stops if operator>> fails.
//Hope this is something you want dear.Enjoy
#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
string name = "kelly";
int main()
{
int num =0;
string tempname;
int tempbalance;
vector<string> players;
vector<int> balances;
ifstream input_file("players.txt");
while(!input_file.eof())
{ input_file>>tempname;
input_file>>tempbalance;
players.push_back(tempname);
balances.push_back(tempbalance);
}
for(size_t i = 0; i<players.size(); i++)
{
if(name==players.at(i))
cout<< "Welcome " << name << ", your current balance is " << balances.at(i)<< "$." << endl;
}
return 0;
}

how can I change a file content in c++?

I have this program that changes negative numbers to positive in my file.
It works, but negative numbers in the file don't change.
for example, if I have this numbers in my file : 12 2 -3 -1
when I run the program, the sum of numbers will be 18, but when I open my file again, I see
12 2 -3 -1 . What should I do to see 12 2 3 1 ?
here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string name;
cin >> name;
int number;
int num=0;
ifstream myFile(name, ios::in);
ofstream mine(name, ios::app);
while(myFile >> number)
{
num += (number<0 ? -number : number);
mine << num;
}
cout << "num = " << num << endl;
system("pause");
return 0;
}
Opening the file for reading and writing for the same time is generally not a bad idea. You probably got an I/O error during opening mine, but since you didn't check it, the program ignored your writes silently. Try reading the file contents first (to a vector for example), then close the file for reading and open again for writing (not appending, because that would leave the old contents in the file).
When writing the values back to the file, also write whitespace after the number, otherwise you'll just get a string of digits in the file but you won't know where one begins and another ends.
Your program now doesn't "change negative numbers to positive" but it prints the cumulative sum of absolute values to the file.
Try writing to the standard output first so you won't ruin your file while you are testing. If it works, then change cout to your output stream.
Here is the code.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
using namespace std;
int main()
{
string name;
cin >> name;
int number;
int num=0;
ifstream myFile(name, ios::in);
vector<int> vec;
while(myFile >> number)
{
vec.push_back(abs(number));
}
ofstream mine(name, ios::out);
for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
num += *it;
mine << *it << " ";
}
cout << "num = " << num << endl;
return 0;
}
Opening a read and write file streams for the same file and process at the same time is inviting file corruption. Use ostringstream to store the values read from the file. The values
from the file are read, and the values stored in the ostringstream
buffer. The ifstream object is closed before re-opening the file with
an ofstream object so that the buffer contents can be saved.
Note the ios::app flag has been removed. Otherwise the new values
will append to the existing values.
abs() function is used to write back the absolute values - this
forces all values positive.
#include<sstream>
int main()
{
string name;
cin >> name;
int number;
int num=0;
ifstream myfile(name.c_str(), ios::in);
ostringstream oss;
while (myfile >> number)
{
num += (number<0 ? -number : number);
oss << abs(number) << " ";
}
myfile.close();
ofstream mine(name.c_str());
cout << "num = " << num << endl;
mine << oss.str();
return 0;
}
string name;
cin >> name;
int number=0;
int sum=0;
string outname=name+".pos.txt";
ifstream myFile(name,ifstream::in);
ofstream mine(outname, ofstream::out );
while(myFile >> number)
{
number= (number<0 ? -number : number);
sum+=number;
mine << number<<' ';
}
myFile.close();
mine.close();
cout << "sum = " << sum << endl;
system("pause");

Outputting Data From A File Into Structs And Arrays Of Structs

I am having a lot of trouble being able to get data from a file and input it into given structs and arrays of structs and then outputting the file. We are given a file that contains 96 lines and looks like this:
Arzin, Neil
2.3 6.0 5.0 6.7 7.8 5.6 8.9 7.6
Babbage, Charles
2.3 5.6 6.5 7.6 8.7 7.8 5.4 4.5
This file continues for 24 different people and then repeats with different scores (the second line).
The first number, in this case is 2.3 for both people is a difficulty rating. The next 6 numbers are scores.
We are given this data in order to set up our structs and arrays and my code:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <cmath>
using namespace std;
int main ()
{
ifstream inFile;
inFile.open("C://diveData.txt");
// checking to see if file opens correctly
if (!inFile)
{
cout << "Error opening the file!" << endl;
}
const int numRounds = 2; // variable to hold the number of rounds
const int numScores = 7; // variable to hold the number of rounds
const int numDivers = 24; // variable to hold the number of divers
typedef double DifficultyList[numRounds]; // 1D array for storing difficulty of dives on each round
typedef double ScoreTable [numRounds] [numScores]; // 2D array of dive scores
// struct to store information for one diver
struct DiverRecord
{
string name;
double totalScore;
double diveTotal;
DifficultyList diff;
ScoreTable scores;
};
DiverRecord DiverList[numDivers];
// my attempt at printing out the contents of the file
while (!EOF)
{
for (int x = 0; x < 25; x++)
{
infile >> DiverList[x].name;
inFile >> DiverList[x].totalScore;
inFile >> DiverList[x].diveTotal;
cout << DiverList.[x].name << endl;
cout << DiverList.[x].totalScore << endl;
cout << DiverList.[x].diveTotal << endl;
}
}
return 0;
}
First of all the >> operator ends input at the first whitespace character so when you read in the name you only get the last name and the comma it will try to put the first name into totalScore. To get the full name do the following.
string temp;
infile >> DiverList[x].name;
infile >> temp;
DiverList[x].name + " ";
DiverList[x].name + temp;
Also when outputting you don't need that extra '.'
cout << DiverList[x].name << endl;
and so on should work just fine.
Couple of questions:
decide whether ifstream is open or not, use ifstream::is_open;
decide whether end of file is encountered, try code below;
If I get it right, your input file format should be:
name1,name2
difficulty score1 score2 ... score7
In this sense, the totalScore should not be input from the stream, but calculated instead.
you have two names for one record, so the definition of your record structure seems fuzzy.
Here is a revised version:
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;
struct DiverRecord
{
string a, b;
double totalScore;
double difficulty;
double scores[7];
};
int main ()
{
ifstream inFile("C://diveData.txt");
// checking to see if file opens correctly
if (!inFile.is_open()) {
cout << "Error opening the file!" << endl;
}
vector<DiverRecord> DiverList;
DiverRecord record;
char ch;
while (inFile) {
inFile >> record.a >> ch >> record.b >> record.difficulty;
record.totalScore = 0;
for (int i = 0; i < 7; ++i) {
inFile >> record.scores[i];
record.totalScore += record.scores[i];
}
DiverList.push_back(record);
}
// output your DiverList here.
return 0;
}
As I said in my earlier comment I am now trying to concentrate on not using the structs and arrays of structs and am trying to use other functions in order to read the data from the file. I want to put the data in a logical form such as:
Name Of Person
Round 1: Difficulty Scores
Round 2: Difficulty Scores
But I am having trouble accessing specific elements from the file.
The code I am using is:
while(inFile)
{
string name;
getline(inFile, name);
cout << name << endl;
}
This outputs the data file as is, but when I try to declare different variables for the difficulty and the seven scores it does not output correctly at all.