How do separate a string from a text file - c++

I have a text file that has information format like this:
id last,first string
for example:
0 Snow,John nothing
1 Norris,Chuck everything
How do i get last name and first name stored separately?
To get information from file, I did:
#include <fstream>
int id;
string str;
string last;
string first;
int main()
{
ifstream myfile(ex.txt);
myfile >> id;
while (myfile)
{
for (int i = 0; i < 4; i++) // this is the amount of times i'll get information from 1 line
{
id = id; // its actually some_structure.id = id, omit
getline(myfile, last, ','); // i think i need to use another function as getline get the whole line
cout << id;
cout << last; // print out the whole line!
}
}
}

ifstream myfile;
string line;
while (getline(myfile, line))
{
istringstream ss(line);
int id;
ss >> id;
string fullname;
ss >> fullname;
string firstname, lastname;
{
istringstream ss2(fullname);
getline(ss2, lastname, ',');
getline(ss2, firstname);
}
}

if (std::ifstream input(filename))
{
int id;
string lastname, firstname, other_string;
while (input >> id && getline(input, lastname, ',') &&
input >> firstname >> other_string)
... do whatever you like...
if (!input.eof())
std::cerr << "error while parsing input\n";
}
else
std::cerr << "error while opening " << filename << '\n';
The code above has more error checking than the other answers I've seen, but admittedly - because it doesn't read text a line at a time then parse out the fields, it would happily accept e.g.:
10 Chuck,
Norris whatever

Would recomend something like this:
string name;
myfile >> id >> name >> str;
first = name.substr(0, name.find(","));
last = name.substr(name.find(",") + 1);
Note that your EOF checking is incorrect.

// The complete code that will do the job
// Please remove uncomment all code
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("ex.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
string last = line.substr(line.find(" ") + 1, line.find(",") - 2);
string first = line.substr(line.find(",") + 1, line.find(",") + line.find(" ") - 1);
}
myfile.close();
}
else {
cout << "Unable to open file";
}
return 0;
}

Related

Read array of objects from file by custom separator

I have model class for my objects:
class customClass {
string s1;
string s2;
string s3;
}
and file like this:
text1;text1;text1 text1 text1...
text2;text2;text2 text2 text2...
...
and I want make array of objects where
s1 = "text1"
s2 = "text1"
s3 = "text1 text1 text1..."
...
My code:
infile.open("file.txt");
if (infile.is_open())
{
string line;
for (int i = 0; i < 3; i++)
{
infile >> line;
stringstream ss(line);
while (ss.good())
{
string substring;
getline(ss, substring, ';');
cout << substring <<endl;
}
}
}
But it separated every single word. How can I ignore whitespaces to make my 3rd string as text not as single word.
The reason it doesnt work for you is because infile >> line; will read up to the first space character instead of the whole line (this is when you need getline). Maybe something like this:
#include <string>
#include <iostream>
#include <fstream>
int main()
{
std::ofstream outfile("file.txt");
outfile <<
R"(text1;text1;text1 text1 text1...
text2;text2;text2 text2 text2...)";
outfile.close();
// read file
std::ifstream infile("file.txt");
std::string par1, par2, par3;
while (std::getline(infile, par1, ';') && std::getline(infile, par2, ';') && std::getline(infile, par3))
std::cout << par1 << " | " << par2 << " | " << par3 << std::endl;
}
Demo: http://coliru.stacked-crooked.com/view?id=eb52001b5d4ecbed
Read all line with getline function. Default >> operation get values until \n, (space) character.
#include <iostream>
#include <fstream>
#include <string.h>
#include <sstream>
using namespace std;
class CustomClass
{
public:
string s1;
string s2;
string s3;
};
int main()
{
ifstream infile;
infile.open("test.txt");
if (infile.is_open())
{
while (!infile.eof())
{
string line;
getline(infile, line);
stringstream ss(line);
CustomClass cls;
getline(ss, cls.s1, ';');
getline(ss, cls.s2, ';');
getline(ss, cls.s3, ';');
cout << cls.s1 << " - " << cls.s2 << " - " << cls.s3 << endl;
}
}
return 0;
}
Just don't read single string at the begining, also I added the loop until the end of file, so your code would look like:
std::ifstream infile("file.txt");
std::string line;
if (infile.is_open())
{
string line;
while (std::getline(infile, line)) {
std::stringstream ss(line);
string substring;
while (getline(ss, substring, ';')) {
cout << substring <<endl;
}
}
}

C++ Validate Emails Via Substrings

I'm trying to take the profile info(username, email, etc.) from one directory and put it in another. I've been debugging the code for this program, and while there are no errors, the program won't run, saying that the program "has stopped working". I have already looked on this website and others for any possible answers, and found none.
#include <string>
#include <cstring>
#include <iostream>
#include <istream>
#include <ostream>
#include <fstream>
#include <iomanip>
#include <filesystem>
using namespace std;
class path{
public:
string parent_directory;
string root_directory;
};
class Data{
public:
string userName;
string nickName;
string fName;
string arena_FName;
string lName;
string arena_LName;
string email;
string arenaEmail;
friend std::istream& operator>>(std::istream& input, Data& d);
};
std::istream& operator>>(std::istream& input, Data& d){
std::getline(input, d.userName);
std::getline(input, d.nickName);
//...
std::getline(input, d.arenaEmail);
return input;
}
int main(){
ifstream myfile("myfunk.txt", ios::in);
ofstream arena("arena.txt");
myfile.open("myfunk.txt", ios::in);
if(myfile){
cout << "Input file open." << endl;
}
arena.open("arena.txt", ios::out | ios::app);
if(arena){
cout << "Output file open." << endl;
}
cout << "file opening test: success" << endl;
int x = 0;
int y = 4101; //Total number of users in the directory.
int z = 0; //For inputting the required lines of info for each profile.
int profile = 0;
bool valid = false;
string role;
//string arenaRole;
bool post = false;
string line;
string p = "This PC/..."; //Path to the folder of the individual pictures.
//myVar.save("...");
string p = "...";
path path1;
path root_directory;
path parent_directory;
//bool is_directory(const std::filesystem::path& p, std::error_code& ec) noexcept; //Checks if current location is a directory.
//bool postPic;
const unsigned int MAXIMUM_DATA = 4100u;
Data database[MAXIMUM_DATA];
cout << "All variables but the filesystem have been accepted! Please install this program on the network." << endl;
while(x < y){
cout << "Primary loop functioning" << endl;
if(post = true){
getline(myfile, line); //Grab and read next line.
myfile >> line;
line = userName[x];
arena << "Username: " << userName[x] << "\n";
z++;
getline(myfile, line);
myfile >> line;
line = role[x];
arena << "Role: " << role[x] << "\n";
z++;
getline(myfile, line);
line = nickName[x];
myfile >> nickName[x];
arena << "nickname: " << nickName[x] << "\n";
z++;
getline(myfile, line);
line = fName[x];
myfile >> fName;
arena << "First Name: " << fName[x] << "\n";
z++;
getline(myfile, line);
line = lName[x];
myfile >> lName;
arena << "Last Name: " << lName[x] << "\n";
z++;
getline(myfile, line);
myfile >> line;
line = email[x];
arena << "Email: " << email[x] << "\n";
getline(myfile, line);
z = 0; //Next profile...
}
int data;
while(myfile >> data){
if(nickName[x] = NULL){
myfile >> "<Error> Some required information is missing! Contact user! </Error> /n";
valid = false;
post = false;
x++;
}
if(email[x] != NULL){
std::string str("#");
std::string str2(".com");
std::string str3(".net");
std::string str4(".edu");
if(std::size_t found = email[x].find(str) & (std::size_t found = email[x].find(str2) || std::size_t found = email[x].find(str3) || std::size_t found = email[x].find(str4)){
valid = true;
if(valid = true){
post = true;
}
}
else{
valid = false;
post = false;
x++;
}
}
}
}
}
}
x++;
}
//x++;
myfile.close(); //Closes the file in the directory.
arena.close(); //Closes the file in Arena.
return 0;
}
Let's rework your code.
First, let's create a data structure for the data:
class Data
{
public:
string userName;
string nickName;
string fName;
string arena_FName;
string lName;
string arena_LName;
string email;
string arenaEmail;
};
If you need an array for the data, it would be declared as:
const unsigned int MAXIMUM_DATA = 4100u;
Data database[MAXIMUM_DATA];
Next, let's overload the extraction operator>> to make reading easier:
class Data
{
public:
//...
friend std::istream& operator>>(std::istream& input, Data& d);
};
std::istream& operator>>(std::istream& input, Data& d)
{
std::getline(input, d.userName);
std::getline(input, d.nickName);
//...
std::getline(input, d.arenaEmail);
return input;
}
This simplifies your input loop to:
std::vector<Data> database;
Data d;
while (my_file >> d)
{
database.push_back(d);
}
You can query the amount of data read in by using the std::vector::size() method, i.e. database.size().
Also, you don't need a separate structure for a file path. A simple std::string will suffice. I recommend using forward slash, '/', because it is recognized by both Windows and *nix operating systems and won't be interpreted as an escape character.

Reading in a file with delimiter and blank lines for hashing program

How do I read in lines from a file and assign specific segments of that line to the information in structs? And how can I stop at a blank line, then continue again until end of file is reached?
Background: I am building a program that will take an input file, read in information, and use double hashing for that information to be put in the correct index of the hashtable.
Suppose I have the struct:
struct Data
{
string city;
string state;
string zipCode;
};
But the lines in the file are in the following format:
20
85086,Phoenix,Arizona
56065,Minneapolis,Minnesota
85281
56065
I cannot seem to figure this out. I am having a really hard time reading in the file. The first line is basically the size of the hash table to be constructed. The next blank line should be ignored. Then the next two lines are information that should go into the struct and be hashed into the hash table. Then another blank line should be ignored. And finally, the last two lines are input that need to be matched to see if they exist in the hash table or not. So in this case, 85281 is not found. While 56065 is found.
This is what I have and it doesn't seem to be doing what I want it to do:
int main(int argc, char *argv[])
{
string str;
//first line of file is size of hashtable
getline(cin, str);
stringstream ss(str);
int hashSize;
ss >> hashSize;
//construct hash table
Location *hashTable = new Location[hashSize];
//skip next line
getline(cin, str);
string blank = " ";
while(getline(cin, str))
{
{
//next lines are data
Location locate;
string line;
getline(cin, line);
istringstream is(line);
getline(is, locate.zipCode, ',');
getline(is, locate.city, ',');
getline(is, locate.state, ',');
insertElementIntoHash(hashTable, locate, hashSize);
}
}
dispHashTable(hashTable, hashSize);
//read third set of lines that check if the zipCodes are in the hashtable or not
while(getline(cin, str))
{
//stop reading at a blank line or in this case, end of file
stringstream is(str);
string searchZipCode;
is >> searchZipCode;
searchElementInHash(hashTable, hashSize, searchZipCode);
}
//delete hash table after use
delete []hashTable;
return 0;
}
You might read the input this way:
#include <iostream>
#include <sstream>
#include <vector>
struct Location
{
std::string city;
std::string state;
std::string zipCode;
};
int main(int argc, char *argv[]) {
std::istringstream input(
"2\n"
"\n"
"85086,Phoenix,Arizona\n"
"56065,Minneapolis,Minnesota\n"
"\n"
"85281\n"
"56065\n"
);
// Make the size unsigned, to avoid signed/unsigned compare warnings.
unsigned hashSize;
std::string line;
getline(input, line);
std::istringstream hash_line(line);
// Ignore white space.
if( ! (hash_line >> hashSize >> std::ws && hash_line.eof())) {
std::cerr << "Error: Invalid file format [1].\n" << line << '\n';
return -1;
}
else {
getline(input, line);
std::istringstream first_blank_line(line);
// Ignore white space.
first_blank_line >> std::ws;
if( ! first_blank_line.eof()) {
// Missing blank line.
std::cerr << "Error: Invalid file format [2].\n" << line << '\n';
return -2;
}
else {
// Have a local variable (No need to allocate it)
// (Is it a hash table !???)
std::vector<Location> hashTable;
hashTable.reserve(hashSize);
while(hashTable.size() < hashSize && getline(input, line)) {
std::istringstream data_line(line);
Location locate;
getline(data_line, locate.zipCode, ',');
getline(data_line, locate.city, ',');
getline(data_line, locate.state); // Note: No comma here.
if(data_line && data_line.eof()) {
// Note: The fields may have leading and/or trailing white space.
std::cout
<< "Insert the location into the hash table.\n"
<< locate.zipCode << '\n'
<< locate.city << '\n'
<< locate.state << '\n';
hashTable.push_back(locate);
}
else {
std::cerr << "Error: Invalid file format [3].\n" << line << '\n';
return -3;
}
}
if(hashTable.size() != hashSize) {
std::cerr << "Error: Invalid file format [4].\n";
return -4;
}
else {
getline(input, line);
std::istringstream second_blank_line(line);
// Ignore white space.
second_blank_line >> std::ws;
if( ! second_blank_line.eof()) {
// Missing blank line.
std::cerr << "Error: Invalid file format [5].\n";
return -5;
}
else {
std::string searchZipCode;
while(input >> searchZipCode) {
// Search element in the hash table
}
}
}
}
}
return 0;
}
Following modification should work:
//skip next line
getline(cin, str);
string blank = " ";
string line;
while(getline(cin, line) && (line != ""))
{
{
//next lines are data
Location locate;
istringstream is(line);
getline(is, locate.zipCode, ',');
getline(is, locate.city, ',');
getline(is, locate.state, ',');
insertElementIntoHash(hashTable, locate, hashSize);
}
}

how to extract out data from a txt file which is seperated by |

I am looking for a way to extract out data from a txt file which data is seperated by row and each column of data is seperaed by |
Here's an example
12|john bravo|123 kings street
15|marry jane|321 kings street
Previously i did it by separating using spaces like this
12 john kingstreet
15 marry kingstreet
But it poses a problem when I add a last name to the names/ add an address with spaces, ex: john bravo
So I decided to separate the column data using |
this is how I extract the data
struct PERSON{
int id;
string name;
string address;
};
//extract
int main(){
PERSON data[2];
ifstream uFile("people.txt");
int i = 0;
while(uFile >> data[i].id >> data[i].name >> data[i].address){
i++;
}
return 0;
}
So how do i extract if the columns are separated by | ??
Use getline() twice:
First, get each line use default seperator (new line); second, for each segment from first step, use '|' as seperator. "stringstream" class may be used to transfer data.
#edward The code below is modified from yours, and I think #P0W58 's answer is better.
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
const int length = 2;
struct PERSON
{
int id;
string name;
string address;
};
//extract
int main()
{
PERSON data[length];
ifstream fin("people.txt");
int i = 0;
while(true)
{
string segment;
if (!getline(fin, segment))
break;
stringstream transporter;
transporter << segment;
string idString;
getline(transporter, idString, '|');
getline(transporter, data[i].name, '|');
getline(transporter, data[i].address, '|');
stringstream idStream;
idStream << idString;
idStream >> data[i].id;
i++;
}
for (i=0; i<length; i++)
cout << data[i].id << '+' << data[i].name << '+'\
<< data[i].address << endl;
return 0;
}
To read into a struct , I'd overload << and then parse the text as mentioned in one of the answer .
Something like this :
#include<sstream>
//...
struct PERSON{
int id;
std::string name;
std::string address;
friend std::istream& operator >>(std::istream& is, PERSON& p)
{
std::string s;
std::getline(is, s); //Read Line, use '\r' if your file is saved on linux
std::stringstream ss(s);
std::getline(ss, s, '|'); //id
p.id = std::atoi(s.c_str());
std::getline(ss, p.name, '|'); // name
std::getline(ss, p.address, '|'); //address
return is ;
}
};
And then you can probably do,
std::ifstream fin("input.txt");
PERSON p1;
while (fin >> p1)
//std::cout << p1.id << p1.name << std::endl ;
You can overload << too
Use boost::tokenizer or find first of like :
// code example
string s = "12|john bravo|123 kings street";
string delimiters = "|";
size_t current;
size_t next = -1;
do
{
current = next + 1;
next = s.find_first_of( delimiters, current );
cout << s.substr( current, next - current ) << endl;
}
while (next != string::npos);

Trouble with reading/outputting files

I want to open a file for reading then output what is in that .txt file, any suggestion on my code?
string process_word(ifstream &word){
string line, empty_str = "";
while (!word.eof()){
getline(word, line);
empty_str += line;
}
return empty_str;
}
int main(){
string scrambled_msg = "", input, output, line, word, line1, cnt;
cout << "input file: ";
cin >> input;
ifstream inFile(input);
cout << process_word(inFile);
}
Instead of:
while (!word.eof()) {
getline(word, line);
empty_str += line;
}
do:
while ( std::getline(word, line) ) {
empty_str += line;
}
and it would be also wise to give your variables more appropriate names.
Your function can be simplified to:
#include <iterator>
std::string process_word(std::ifstream& word)
{
return std::string{std::istream_iterator<char>{word},
std::istream_iterator<char>{}};
}
int main()
{
string input;
std::cin >> input;
std::ifstream inFile(input);
std::cout << process_word(inFile);
}