Reading in a text file to a C++ program I'm working on, and storing each string in a node for a double-linked list. Problem is, I don't know how to split up a line into smaller strings, separating them where the space is.
For instance, one input is
"Duck Donald 940-666-5678"
and I'm attempting to split it into a lastname string, a firstname string, and a phnum string at the white space. The result would essentially be:
lastname==Duck
firstname==Donald
phnum==940-666-5678
How would I do this?
Although I not sure how you're extracting this data, I believe you should just be able to use the >> operator.
Example:
string lastname;
string firstname;
string phnum;
ifstream myFile;
myFile.open("example.txt");
myFile >> lastname >> firstname >> phnum;
I am not quite sure how you are reading in from your file, but this bit of code may help you.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
istringstream iss(s);
do
{
string sub;
iss >> sub;
cout << "Substring: " << sub << endl;
} while (iss);
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
Make sure to search Stackoverflow/Google before asking because you can find your answer really easily many times (see my resources)
Resources: http://www.cplusplus.com/doc/tutorial/files/, Split a string in C++?
Related
data.txt contains the following information: firstName, lastName, salary, increment.
James Chong 5000 3
Peter Sun 1000 5
Leon Tan 9500 2
I want to read data.txt, make the necessary calculations, and store the output of 3 variables in anewData.txt:
firstName, lastName, updatedSalary(salary*percentageIncrement)
I only managed to proceed to reading and display information in data.
Below is my code:
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
int main()
{
string filename = "data.txt";
ifstream infile;
infile.open(filename);
//if file cannot open, exit program
if (!infile.is_open()){
exit(EXIT_FAILURE);
}
string word;
infile >> word;
while(infile.good()){
cout << word << " ";
infile >> word;
}
system("pause");
return 0;
}
May I know are there any references that I can make use of? Thank you
I am not entirely sure about the question , but you might find substr function useful (if you need to process the data),about writing to a file, you can just create an ofstream output("newData.txt") and simply write the result there. (output << result). Also there is a tokenizer library in BOOST if you don't want to solve it with substr.
You're expecting each line to have 4 words separated by whitespace, so it's as easy as extracting them from infile at each iteration:
while(infile.good()) {
string first_name, last_name;
infile >> first_name;
infile >> last_name;
unsigned int salary, increment;
infile >> salary;
infile >> increment;
}
of course you should check that infile is good after attempting to extract the various pieces, should the lines be malformed.
You can get fancier here, but this covers your basic needs.
I can get the file to save right but I can't seem to get multiple words to write to .txt, like if I type "Hi purple" it just writes "Hi", here is code
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
system("color F0");
string name0;
cout << "Please enter a file name, no spaces/special characters" << endl;
cin >> name0;
name0 = name0+".txt";
system("cls");
cout << " FISHSOFT" << endl;
cout << "The best text editor in the world" << endl << endl;
string text;
cin >> text;
ofstream myfile;
myfile.open (name0.c_str() , ios::out | ios::trunc);
myfile << text;
myfile.close();
system("PAUSE");
return 0;
}
Use std::getline to read an entire line of input including spaces.
cin >> text; will read one whitespace delimited token from the input stream. One word in == one word out.
std::getline(cin, text); will read a whole line. Reading more than that is tricky, but typically a loop around multiple calls to getline.
Suggestion: Save yourself time and fire up your IDE's debugger to see what's happening in your code before posting a question. Almost always faster, and if not, you can make much better, tighter-focused questions.
std::cin is able to get several parameters at once.
That mean you may write:
std::cin >> name0 >> name1 >> name2;
// input: a1 a2 a3
// make: name0: a1, name1: a2, name3:a3
By default, the space is the separator between parameters.
To avoid this behavior, you could use getLine:
std::getline(std::cin, name0);
There are 2 ways to get the string with spaces and special character.
cin.getline(name);
gets(name);
Hope this will serve your purpose.
I'm learning about splitting strings for a program in class, and i came across this example.
#include <string>
#include <sstream>
#include <iostream>
int main()
{
std::string str = "23454323 ABCD EFGH";
std::istringstream iss(str);
std::string word;
while(iss >> word)
{
std::cout << word << '\n';
}
}
I modified so that the user instead inputs the string,but if I input the string stored in str i get 23454323 and not the other material in the string.
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
string str;
cout<<"Enter a postfix with a space between each object:";
cin>>str;
istringstream iss(str);
string word;
while(iss >> word)
{
cout << word << '\n';
}
}
Ok, thanks for the help everyone got it!
You need to modify your input code a little for this to work. Use:
getline(cin, str);
instead of:
cin >> str;
The latter will stop reading a string on whitespace characters.
Because you use the same input operator as for istringstream when you input from cin and it always breaks on whitespace.
That means you only read a single word from the user. You want to use std::getline.
Just as iss >> word reads a single space-separated word from iss, so cin >> str just reads the first word from cin.
To read a whole line, use getline(cin, str).
(Also, get out of the habit of dumping namespace std into the global namespace. It will cause problems as your programs grow.)
For a couple of weeks now, I have been developing a random class generator for the Xbox game Call of Duty: Modern Warfare 3. In this game, different weapons have different levels, which increase as you use the weapon more. I am storing the weapons and their levels in a text file, which store the data on separate lines with the format
weapon-weapon_level
So the M4A1 with weapon level 8 would look like:
m4a1-8
(The weapons are all in lowercase with no punctuation or spaces).
I have already written methods for creating the file and reading the file, but I want a method to edit the file, so the user enters the weapon whose level they want to change, then the new level. Here's what I have so far: (The file is called "weaponlevels.txt")
void WeaponLevelFile::editFile()
{
string line;
string weapon;
string weaponent;
string weaponlevel;
string temp;
cout<<"Please enter the weapon whose level you wish to change. Enter the name in lowercase, with "<<endl;
cout<<"no spaces or punctuation except full stops. E.g. SCAR-L becomes scarl and Barrett .50cal "<<endl;
cout<<"becomes barrett.50cal."<<endl;
cin>>weaponent;
cout<<"Please enter the new weapon level."<<endl;
cin>>temp;
ifstream infile("weaponlevels.txt");
ofstream outfile("weaponlevels.txt");
while (getline(infile, line))
{
istringstream ss(line);
getline(ss,weapon,'-');
if (weapon == weaponent)
{
ss>>weaponlevel;
weaponlevel=temp;
outfile<<weaponlevel<<endl;
infile.close();
outfile.close();
}
}
}
This method does not work however; all it does is wipe the file (so the file is blank). Why does it do this, and what is a better method?
EDIT:
#stardust_'s answer worked the best, but still didn't completely do it. Here is the code:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main()
{
string temp;
string line;
string weapon;
string weaponent;
string weaponlevel;
cout<<"enter weapon"<<endl;
cin>>weaponent;
cout<<"enter level"<<endl;
cin>>temp;
ifstream infile("weaponlevels.txt");
std::string in_str((std::istreambuf_iterator<char>(infile)),
std::istreambuf_iterator<char>());
infile.close();
stringstream infile_ss(in_str);
while (getline(infile_ss, line))
{
istringstream ss(line);
getline(ss,weapon,'-');
if (weapon == weaponent)
{
ss>>weaponlevel;
weaponlevel=temp;
infile_ss<<weaponlevel<<endl;
}
}
ofstream outfile("weaponlevels.txt");
outfile << infile_ss.str();
outfile.close();
}
It modifies the right part of "weaponlevels.txt", but doesn't completely do it. if i enter m4a1 as the weapon and 7 as the weapon level, instead of becoming m4a1-7 it becomes:
7
a1-3
After quite a lot of work, here's what worked:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main()
{
string temp;
string line;
string weapon;
string weaponent;
string weaponlevel;
cout<<"enter weapon"<<endl;
cin>>weaponent;
cout<<"enter level"<<endl;
cin>>temp;
ifstream infile("weaponlevels.txt");
std::string in_str((std::istreambuf_iterator<char>(infile)),
std::istreambuf_iterator<char>());
infile.close();
stringstream infile_ss(in_str);
ostringstream out;
while (getline(infile_ss, line))
{
istringstream ss(line);
getline(ss,weapon,'-');
out << weapon << '-'; // Write the first part of the line.
if (weapon != weaponent)
{ // Not the correct weapon so just write the original information.
ss >> weaponlevel;
out << weaponlevel << endl;
}
else
{ // Found the desired weapon, change the level.
out << temp << endl;
}
}
I loaded the whole string into an ostringstream and found the weapon within the string.
Have you tried using pointers to search through the file for a specific string to replace? I have yet to write a program that uses this myself, but I know it's pretty common. Otherwise you'll just be overwriting the entire file.
Note that I'm not entirely certain whether you have used pointers in your code for this purpose because, as I stated above, I have yet to use this myself. However, from what I saw, I don't think you did. Just correct me if I'm wrong.
There are many problems with your code. You are opening a file twice. you are closing the ifstreams in a loop while reading them (?). ...
However algorithm wise you can open the file for reading, read the whole thing to a string, close the file, modify the string, open the file for writing, write the string, close the file.
int main()
{
cin>>temp;
ifstream infile("weaponlevels.txt");
std::string in_str((std::istreambuf_iterator<char>(infile)),
std::istreambuf_iterator<char>());
infile.close();
stringstream infile_ss(in_str);
while (getline(infile_ss, line))
{
istringstream ss(line);
getline(ss,weapon,'-');
if (weapon == weaponent)
{
ss>>weaponlevel;
weaponlevel=temp;
infile_ss<<weaponlevel<<endl;
}
}
ofstream outfile("weaponlevels.txt");
outfile << infile_ss.str();
outfile.close();
}
instead of
ifstream infile("weaponlevels.txt");
use
ifstream infile("weaponlevels.txt", ifstream::in)
Check this program
ifstream filein("Hey.txt");
filein.getline(line,99);
cout<<line<<endl;
filein.getline(line,99);
cout<<line<<endl;
filein.close();
The file Hey.txt has alot of characters in it. Well over a 1000
But my question is
Why in the second time i try to print line. It doesnt get print?
The idiomatic way to read lines from a stream is this:
std::ifstream filein("Hey.txt");
for (std::string line; std::getline(filein, line); )
{
std::cout << line << std::endl;
}
Notes:
No close(). C++ takes care of resource management for you when used idiomatically.
Use the free std::getline, not the stream member function.
According to the C++ reference (here) getline sets the ios::fail when count-1 characters have been extracted. You would have to call filein.clear(); in between the getline() calls.
#include<iostream>
using namespace std;
int main()
{
ifstream in;
string lastLine1;
string lastLine2;
in.open("input.txt");
while(in.good()){
getline(in,lastLine1);
getline(in,lastLine2);
}
in.close();
if(lastLine2=="")
cout<<lastLine1<<endl;
else
cout<<lastLine2<<endl;
return 0;
}
As Kerrek SB said correctly There is 2 possibilities:
1) Second line is an empty line
2) there is no second line and all more than 1000 character is in one line, so second getline has nothing to get.
An easier way to get a line is to use the extractor operator of ifstream
string result;
//line counter
int line=1;
ifstream filein("Hey.txt");
while(filein >> result)
{
//display the line number and the result string of reading the line
cout << line << result << endl;
++line;
}
One problem here though is that it won't work when the line have a space ' ' because it is considered a field delimiter in ifstream. If you want to implement this kind of solution change your field delimiter to e.g. - / or any other field delimiter you like.
If you know how many spaces there is you can eat all the spaces by using other variables in the extractor operator of ifstream. Consider the file has contents of first name last name.
//file content is: FirstName LastName
int line=1;
ifstream filein("Hey.txt");
string firstName;
string lastName;
while(filein>>firstName>>lastName)
{
cout << line << firstName << lastName << endl;
}