Reading chunks of line from text file into strings - c++

So say if I have this line in a text file.
AarI/CACCTGCNNNN'NNNN/'NNNNNNNNGCAGGTG//
What I want is to read this line into a string until the forwardslash appears and then start reading the next set of characters into another string.. So in this example I would have 3 strings containing
string1 = "AarI"
string2 = "CACCTGCNNNN'NNNN"
string3 = "'NNNNNNNNGCAGGTG"
Any idea how to go about this?

istream::getline() with a delim character of '/' - see: http://www.cplusplus.com/reference/istream/istream/getline/
Not the best or safest, probably amongst the simpler approaches.

Use sstream. The code below shows an example of how to split a string.
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
vector<string> split(string str, char delimiter);
int main(int argc, char **argv) {
string DNAstr = "AarI/CACCTGCNNNN'NNNN/'NNNNNNNNGCAGGTG//";
vector<string> splittedlines = split(DNAstr, '/');
for(int i = 0; i < splittedlines.size(); ++i)
cout <<""<<splittedlines[i] << " \n";
return 0;
}
vector<string> split(string str, char delimiter) {
vector<string> buffer;
stringstream ss(str);
string tok;
while(getline(ss, tok, delimiter)) {
buffer.push_back(tok);
}
return buffer;
}

Related

How do I read a file into a 2D list by splitting at the comma

I'm working on a program where the user will input in the format x,0,0 and it will be saved to a file then read into an array where I can compare the values however I'm stuck when trying to read into a 2D array can someone please help? Think the error is in the struct part
This is what I have so far:
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
#include <sstream>
using namespace std;
struct listArray
{
string name[];
int price1[];
int price2[];
};
int main()
{
listArray la;
string line;
cout << "Enter your list: ";
ofstream fout;
fout.open("list.txt");
while (fout) {
getline(cin, line);
if (line == "-1")
break;
fout << line << endl;
}
fout.close();
int count = 0;
ifstream listFile;
listFile.open("list.txt");
if(listFile.is_open()){
while (listFile) {
getline(listFile, la.name[count], ",");
count++;
listFile.close();
}
}
You can use delimiter to grab the substring, and use this substring to fill your struct, an exemple of split:
#include<iostream>
std::vector<std::string> split(const string& input, const string& regex)
{
// passing -1 as the submatch index parameter performs splitting
std::regex re(regex);
std::sregex_token_iterator first{input.begin(), input.end(), re, -1},last;
return {first, last};
}
if you are using C++11 or higher, you can use std::vector for arrays, and you also can use boost library, they have nice support for delimiter and other stuffs.

How to get input an array of strings with \n as delimiter?

#include<bits/stdc++.h>
using namespace std;
int main()
{
int i=0;
char a[100][100];
do {
cin>>a[i];
i++;
}while( strcmp(a[i],"\n") !=0 );
for(int j=0;j<i;i++)
{
cout<<a[i]<<endl;
}
return 0;
}
Here , i want to exit the do while loop as the users hits enter .But, the code doesn't come out of the loop..
The following reads one line and splits it on white-space. This code is not something one would normally expect a beginner to write from scratch. However, searching on Duckduckgo or Stackoverflow will reveal lots of variations on this theme. When progamming, know that you are probably not the first to need the functionality you seek. The engineering way is to find the best and learn from it. Study the code below. From one tiny example, you will learn about getline, string-streams, iterators, copy, back_inserter, and more. What a bargain!
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <vector>
int main() {
using namespace std;
vector<string> tokens;
{
string line;
getline(cin, line);
istringstream stream(line);
copy(istream_iterator<string>(stream),
istream_iterator<string>(),
back_inserter(tokens));
}
for (auto s : tokens) {
cout << s << '\n';
}
return 0;
}
First of all, we need to read the line until the '\n' character, which we can do with getline(). The extraction operator >> won't work here, since it will also stop reading input upon reaching a space. Once we get the whole line, we can put it into a stringstream and use cin >> str or getline(cin, str, ' ') to read the individual strings.
Another approach might be to take advantage of the fact that the extraction operator will leave the delimiter in the stream. We can then check if it's a '\n' with cin.peek().
Here's the code for the first approach:
#include <iostream> //include the standard library files individually
#include <vector> //#include <bits/stdc++.h> is terrible practice.
#include <sstream>
int main()
{
std::vector<std::string> words; //vector to store the strings
std::string line;
std::getline(std::cin, line); //get the whole line
std::stringstream ss(line); //create stringstream containing the line
std::string str;
while(std::getline(ss, str, ' ')) //loops until the input fails (when ss is empty)
{
words.push_back(str);
}
for(std::string &s : words)
{
std::cout << s << '\n';
}
}
And for the second approach:
#include <iostream> //include the standard library files individually
#include <vector> //#include <bits/stdc++.h> is terrible practice.
int main()
{
std::vector<std::string> words; //vector to store the strings
while(std::cin.peek() != '\n') //loop until next character to be read is '\n'
{
std::string str; //read a word
std::cin >> str;
words.push_back(str);
}
for(std::string &s : words)
{
std::cout << s << '\n';
}
}
You canuse getline to read ENTER, run on windows:
//#include<bits/stdc++.h>
#include <iostream>
#include <string> // for getline()
using namespace std;
int main()
{
int i = 0;
char a[100][100];
string temp;
do {
getline(std::cin, temp);
if (temp.empty())
break;
strcpy_s(a[i], temp.substr(0, 100).c_str());
} while (++i < 100);
for (int j = 0; j<i; j++)
{
cout << a[j] << endl;
}
return 0;
}
While each getline will got a whole line, like "hello world" will be read once, you can split it, just see this post.

extract individual words from string c++

I am trying to make a C++ program that receives user input, and extracts the individual words in the string, e.g. "Hello to Bob" would get "Hello", "to", "Bob". Eventually, I will be pushing these into a string vector. This is the format I tried to use when designing the code:
//string libraries and all other appropriate libraries have been included above here
string UserInput;
getline(cin,UserInput)
vector<string> words;
string temp=UserInput;
string pushBackVar;//this will eventually be used to pushback words into a vector
for (int i=0;i<UserInput.length();i++)
{
if(UserInput[i]==32)
{
pushBackVar=temp.erase(i,UserInput.length()-i);
//something like words.pushback(pushBackVar) will go here;
}
}
However, this only works for the first space encountered in the string.It does not work if there are any spaces before the word (e.g. if we have "Hello my World", pushBackVar will be "Hello" after the first loop, and then "Hello my" after the second loop, when I want "Hello" and "my".) How do I fix this? Is there any other better way to extract individual words from a string? I hope I haven't confused anyone.
See Split a string in C++?
#include <string>
#include <sstream>
#include <vector>
using namespace std;
void split(const string &s, char delim, vector<string> &elems) {
stringstream ss(s);
string item;
while (getline(ss, item, delim)) {
elems.push_back(item);
}
}
vector<string> split(const string &s, char delim) {
vector<string> elems;
split(s, delim, elems);
return elems;
}
So in your case just do:
words = split(temp,' ');
You can use the operator >> direct to a microbuffer (string) to extract the word. (getline is not needed). Take a look at the function below:
vector<string> Extract(const string& Text) {
vector<string> Words;
stringstream ss(Text);
string Buf;
while (ss >> Buf)
Words.push_back(Buf);
return Words;
}
#include <algorithm> // std::(copy)
#include <iostream> // std::(cin, cout)
#include <iterator> // std::(istream_iterator, back_inserter)
#include <sstream> // std::(istringstream)
#include <string> // std::(string)
#include <vector> // std::(vector)
using namespace std;
auto main()
-> int
{
string user_input;
getline( cin, user_input );
vector<string> words;
{
istringstream input_as_stream( user_input );
copy(
istream_iterator<string>( input_as_stream ),
istream_iterator<string>(),
back_inserter( words )
);
}
for( string const& word : words )
{
cout << word << '\n';
}
}
Here I have created a vector of words from the sentence.
#include<bits/stdc++.h>
using namespace std;
int main(){
string s = "the devil in the s";
string word;
vector<string> v;
for(int i=0; i<s.length(); i++){
if(s[i]!=' '){
word+=s[i];
}
else{
v.push_back(word);
if(i<s.length()+1)
word.clear();
}
}
v.push_back(word);
for(auto i:v){
cout<<i<<endl;
}
}

Trying to read from a file and skip punctuation in C++, tips?

I'm trying to read from a file, and make a vector of all the words from the file. What I tried to do below is have the user input the filename, and then have the code open the file, and skip characters if they aren't alphanumeric, then input that to a file.
Right now it just closes immediately when I input the filename. Any idea what I could be doing wrong?
#include <vector>
#include <string>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
string line; //for storing words
vector<string> words; //unspecified size vector
string whichbook;
cout << "Welcome to the book analysis program. Please input the filename of the book you would like to analyze: ";
cin >> whichbook;
cout << endl;
ifstream bookread;
//could be issue
//ofstream bookoutput("results.txt");
bookread.open(whichbook.c_str());
//assert(!bookread.fail());
if(bookread.is_open()){
while(bookread.good()){
getline(bookread, line);
cout << line;
while(isalnum(bookread)){
words.push_back(bookread);
}
}
}
cout << words[];
}
I think I'd do the job a bit differently. Since you want to ignore all but alphanumeric characters, I'd start by defining a locale that treats all other characters as white space:
struct digits_only: std::ctype<char> {
digits_only(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table() {
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::space);
std::fill(&rc['0'], &rc['9']+1, std::ctype_base::digit);
std::fill(&rc['a'], &rc['z']+1, std::ctype_base::lower);
std::fill(&rc['A'], &rc['Z']+1, std::ctype_base::upper);
return &rc[0];
}
};
That makes reading words/numbers from the stream quite trivial. For example:
int main() {
char const test[] = "This is a bunch=of-words and 2#numbers#4(with)stuff to\tseparate,them, I think.";
std::istringstream infile(test);
infile.imbue(std::locale(std::locale(), new digits_only));
std::copy(std::istream_iterator<std::string>(infile),
std::istream_iterator<std::string>(),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
For the moment, I've copied the words/numbers to standard output, but copying to a vector just means giving a different iterator to std::copy. For real use, we'd undoubtedly want to get the data from an std::ifstream as well, but (again) it's just a matter of supplying the correct iterator. Just open the file, imbue it with the locale, and read your words/numbers. All the punctuation, etc., will be ignored automatically.
The following would read every line, skip non-alpha numeric characters and add each line as an item to the output vector. You can adapt it so it outputs words instead of lines. I did not want to provide the entire solution, as this looks a bit like a homework problem.
#include <vector>
#include <sstream>
#include <string>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string line; //for storing words
vector<string> words; //unspecified size vector
string whichbook;
cout << "Welcome to the book analysis program. Please input the filename of the book you would like to analyze: ";
cin >> whichbook;
cout << endl;
ifstream bookread;
//could be issue
//ofstream bookoutput("results.txt");
bookread.open(whichbook.c_str());
//assert(!bookread.fail());
if(bookread.is_open()){
while(!(bookread.eof())){
line = "";
getline(bookread, line);
string lineToAdd = "";
for(int i = 0 ; i < line.size(); ++i)
{
if(isalnum(line[i]) || line[i] == ' ')
{
if(line[i] == ' ')
lineToAdd.append(" ");
else
{ // just add the newly read character to the string 'lineToAdd'
stringstream ss;
string s;
ss << line[i];
ss >> s;
lineToAdd.append(s);
}
}
}
words.push_back(lineToAdd);
}
}
for(int i = 0 ; i < words.size(); ++i)
cout << words[i] + " ";
return 0;
}

The last word in line not read

I am currently working on a program that read each line from a file and extract the word from the line using specific delimiter.
So basically my code looks like this
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argv, char **argc)
{
ifstream fin(argc[1]);
char delimiter[] = "|,.\n ";
string sentence;
while (getline(fin,sentence)) {
int pos;
pos = sentence.find_first_of(delimiter);
while (pos != string::npos) {
if (pos > 0) {
cout << sentence.substr(0,pos) << endl;
}
sentence =sentence.substr(pos+1);
pos = sentence.find_first_of(delimiter);
}
}
}
However my code didnot read the last word in the line. For example, my file looks like this.
hello world
the output from the program is only the word "hello" but not "world" . I have use '\n' as the delimiter but why didnot it works?.
Any hint would be appreciated.
getline does not save the new line character in the string. For example, if your file has the line
"Hello World\n"
getline will read this string
"Hello World\0"
So your code misses the "World".
Igonoring that sentence is not defined, you could alter your code to work like this:
#include<iostream>
#include<fstream>
using namespace std;
int main(int argv, char *argc)
{
ifstream fin(argc[1]);
char delimiter[]="|,.\n ";
while (getline(fin,sentence)) {
sentence += "\n";
int pos;
pos = find_first_of(sentence,delimiter);
while (pos != string:: npos) {
if (pos > 0) {
cout << sentence.substr(0,pos) << "\n";
}
sentence =sentence.substr(pos+1);
pos = find_first_of(sentence,delimiter);
}
}
}
Note, I borrowed Bill the Lizards more elegant solution of appending the last delimiter. My previous version had a loop exit condition.
Paraphrasing this reference document:
Characters are extracted until the delimiting character (\n) is found, discarded and the remaining characters returned.
Your string doesn't end with an \n, it is ^`hello world`$, so no delimiter or new pos is found.
As others have mentioned, getline doesn't return the newline character at the end. The simplest way to fix your code is to append one to the end of the sentence after the getline call.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argv, char **argc)
{
ifstream fin(argc[1]);
char delimiter[] = "|,.\n ";
string sentence;
while (getline(fin,sentence)) {
sentence += "\n";
int pos;
pos = sentence.find_first_of(delimiter);
while (pos != string::npos) {
if (pos > 0) {
cout << sentence.substr(0,pos) << endl;
}
sentence =sentence.substr(pos+1);
pos = sentence.find_first_of(delimiter);
}
}
}