I am trying to remove leading whitespace and store the characters after the whitespace. I don't want the newline to be considered
This is a file that I am reading from:
Map: Out of planet
Player: Max
My expected result and what I am looking for should be
cout << kill.killMap << endl;
Out of planet // NOTICE THERE IS NO WHITESPACE
cout << kill.player << endl;
Max // NOTICE THERE IS NO WHITESPACE
If the file looks like this...
Map:
Player: Max
Nothing should be stored in the map variable and player variable.
Although the ws function removes whitespace from the stream, I don't think it does the same with char arrays. Would really appreciate it if someone could tell me a way of getting ws to work or just simply an efficient way of removing the whitespace
This is what I am getting:
cout << kill.killMap << endl;
Out of planet //THERE IS WHITESPACE
cout << kill.player << endl;
Max //THERE IS WHITESPACE
Is there a way of doing this without using C++ strings or Vectors. I intend on using C Style strings
THIS IS MY EDITED CODE, HOWEVER IT DOESN'T WORK IF THERE ARE VALID CHARACTERS AFTER THE DELIMITER :... WOULD REALLY APPRECIATE IT IF SOMEONE COULD FIX MY CODE, WOULD MEAN A LOT TO ME.
istreams.get(characters, 50, ':');
istreams.get(c);
istreams.getline(kill.killMap, 35);
while ((is.get(c) != "\n") && (is.get(c) != '\0') )
{
is >> ws;
}
is.getline(kill.killMap, DATA_FILE_SIZE);
if(kill.killMap[0] = '\0)
{
cout << "Error;
break;
}
istreams >> ws;
istreams.get(characters, 50, ':');
istreams.get(c);
while ((is.get(c) != "\n") && (is.get(c) != '\0') )
{
is >> ws;
}
istreams.getline(kill.player, 35);
if(kill.player[0] = '\0)
{
cout << "Error;
break;
}
You can do something like this:
void eatwhites(istream& stream)
{
const string skip=" \t";//put here all wanted skip chars (here i put only SPACE and TAB
while(string::npos != skip.find(stream.peek())){ //if next char in stream exist in skip string
stream.ignore();//then ignore it (1 character).
}
}
EDIT
Here is how i tested it and it works for me:
note you still have to trim the string after you read it, means put the '\0' after the last non white character.
if there is a problem you can tell what input it was and what have you got.
int main()
{
string s1,s2;
eatwhites(cin);
getline(cin,s1, ':');//read until ":"
eatwhites(cin);
getline(cin,s2); //read until "\n"
cout<<"'"<<s1<<"':'"<<s2<<"'"<<endl;
return 0;
}
inputs I've tried:
[SPACE] 123:[SPACE] 456 gives: '123':'456'
[SPACE] 123:[SPACE] gives: '123':''
EDIT2:
With char array it can be used just the same, like this:
#define MAX_FIELD 128
int main()
{
char s1[MAX_FIELD],s2[MAX_FIELD];
eatwhites(cin);
cin.getline(s1, MAX_FIELD, ':');
eatwhites(cin);
cin.getline(s2, MAX_FIELD);
cout<<"'"<<s1<<"':'"<<s2<<"'"<<endl;
return 0;
}
Same results for same input.
Related
I want to write code that takes a string of text from the user and shows the number of characters and the number of words using the .find () function. then takes a word from user and Search the text and show the position of the word. I'm in trouble now, please help me.
#include<iostream>
#include <cctype>
#include<string>
#include<cstring>
using namespace std;
int main()
{ char quit;
int word=0;
string txt;
cout << "Enter a string: ";
getline(cin, txt);
cout << "The number of characters in the string is:" << txt.length() << endl;
while(string txt != NULL)
{ if(txt.find(" "))
++word;
}
cout<<"wors is "<<word;
while(quit!='q')
{
cout<<"wors is ";
cin>>search;
cout<<"Enter(c)if you want to continue, and enter(q)if you want quic:";
cin>>quit;
}
return 0;
}
Here's an example of extracting words. There are many other methods.
static const char end_of_word_chars[] = "!?., :\t";
//...
std::string::size_type previous_position = 0;
std::string::size_type position = txt.find_first_of(end_of_word_chars);
while (position != std::string::npos)
{
std::string word = txt.substr(previous_position, position - previous_position);
std::cout << word << "\n";
previous_position = txt.find_first_of(position + 1);
position = txt.find_first_not_of(end_of_word_chars);
}
The above code uses an array of "end of word characters", to denote the end of a word. The string txt is searched from the beginning to find the position of the first character that is in the set of word endinging characters. In the while loop, the spaces or non-word characters are skipped. And the position of the next "word ending" character is found and the loop may repeat again.
Edit 1: String as stream
Another method is to treat the txt as a string stream and use operator>> to skip whitespace:
std::istringstream text_stream(txt);
std::string word;
while (text_stream >> word)
{
std::cout << word << "\n";
}
One issue with the above code fragment is that it doesn't account for word ending characters that are not spaces or tabs. So for example, in the text "Yes. I'm Home.", the period is included as part of the "word", such as "Yes." and "Home."
I'm doing the assignment and I'm at the end of my powers. Right now I can't figure out what's missing or what I could change.
I need the program to read me a file. If it finds the beginning of the search word, it lists the word and its meaning. If he finds it more than once, he writes only that word without meaning.
Right now, if the program finds more words, it writes the meaning for the first word and writes the word for the other words found.
I don't know what other cycle I could use. If you could help me, I would be grateful.
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include<bits/stdc++.h>
using namespace std;
int main()
{
ifstream dictionary("dictionary.txt");
if(!dictionary.is_open()){
cout<< "File failed to open" << endl;
return 0;
}
int option;
cout << "1.<starting>" << endl;
cout << "4.<stop>" << endl;
cin >> option;
string find_word;
string word, meaning;
string line;
string found;
int count = 0;
if (option == 1)
{
cout << "Find the meaning of the word beginning with the characters:";
cin >> find_word;
while (getline(dictionary,line))
{
stringstream ss(line);
getline (ss, word, ';');
getline (ss, meaning, ';');
if (word.rfind(find_word, 0) != string::npos)
{
count++;
if (count <=1)
{
found = word + meaning;
cout << found << endl;
}
if (count >= 2)
{
found = word ;
cout << found << endl;
}
}
}
}
if (option == 4)
{
return 0;
}
dictionary.close();
return 0;
}
EDIT
dictionary.txt looks like this:
attention; attentionmeaning
attention; attentionmeaning2
computer; computermeaning
criminal; criminalmeaning
boat; boatmeaning
alien; alienmeaning
atter; meaning
.
.
etc.
For example input is:
Find the meaning of the word beginning with the characters: att
this is what i get now (output):
attention attentionmeaning
attention
atter
this is what i expect (desire output):
attention
attention
atter
if program find only one searching word it should write this:
Find the meaning of the word beginning with the characters: bo
output:
boat boatmeaning
As it was already suggested, while reading the file, you don't know if there will be more than one entries matching your search term. That being said, you need some intermediate structure to store all the matching entries.
After you have gathered all the results, you can easily check if the data contains more than one result, in which case you only print the "word" without the meaning. In case there is only one result, you can print the "word" together with its meaning.
The code for that could look something like this:
struct Entry {
std::string name;
std::string meaning;
bool startsWith(const std::string& str) {
return name.find(str) != std::string::npos;
}
};
Entry createEntry(const std::string& line) {
Entry entry;
std::stringstream ss(line);
std::getline(ss, entry.name, ';');
std::getline(ss, entry.meaning, ';');
return entry;
}
int main() {
std::string query = "att";
std::ifstream dictionary("dictionary.txt");
std::vector<Entry> entries;
std::string line;
while (std::getline(dictionary, line)) {
Entry entry = createEntry(line);
if (entry.startsWith(query)) {
entries.emplace_back(std::move(entry));
}
}
for (const Entry& entry : entries) {
std::cout << entry.name << (entries.size() > 1 ? "\n" : " " + entry.meaning + '\n');
}
}
This code could definitely be more optimized, but for the sake of simplicity, this should suffice.
Demo
The problem is that at the first time through the loop you do not know if there is one or more valid words that follow from your string. I would suggest you create an empty list outside the loop, and push all the word and meaning pairs that match onto the list. Then after if the size of the list is 1 you can output the word and meaning pair else use a for loop to loop through and just print the words.
Objective:
I am reading a text file word by word, and am saving each word as an element in an array. I am then printing out this array, word by word. I know this could be done more efficiently, but this is for an assignment and I have to use an array.
I'm doing more with the array, such as counting repeated elements, removing certain elements, etc. I also have successfully converted the files to be entirely lowercase and without punctuation.
Current Situation:
I have a text file that looks like this:
beginning of file
more lines with some bizzare spacing
some lines next to each other
while
others are farther apart
eof
Here is some of my code with itemsInArray initialized at 0 and an array of words refered to as wordArray[ (approriate length for my file ) ]:
ifstream infile;
infile.open(fileExample);
while (!infile.eof()) {
string temp;
getline(infile,temp,' '); // Successfully reads words seperated by a single space
if ((temp != "") && (temp != '\n') && (temp != " ") && (temp != "\n") && (temp != "\0") {
wordArray[itemsInArray] = temp;
itemsInArray++;
}
The Problem:
My code is saving the end of line character as an item in my array. In my if statement, I've listed all of the ways I have tried to disclude the end of line character, but I've had no luck.
How can I prevent the end of line character from saving as an item in my array?
I've tried a few other methods I have found on threads similar to this, including something with a *const char that I couldn't make work, as well as iterating through and deleting the new line characters. I've been working on this for hours, I don't want to repost the same issue, and have tried many many methods.
The standard >> operator overloaded for std::string already uses white-space as word boundary so your program can be simplified a lot.
#include <iostream>
#include <string>
#include <vector>
int
main()
{
std::vector<std::string> words {};
{
std::string tmp {};
while (std::cin >> tmp)
words.push_back(tmp);
}
for (const auto& word : words)
std::cout << "'" << word << "'" << std::endl;
}
For the input you are showing, this will output:
'beginning'
'of'
'file'
'more'
'lines'
'with'
'some'
'bizzare'
'spacing'
'some'
'lines'
'next'
'to'
'each'
'other'
'while'
'others'
'are'
'farther'
'apart'
'eof'
Isn't this what you want?
The stream's extraction operator should take care of that for you
std::ifstream ifs("file.txt");
while (ifs.good())
{
std::string word;
ifs >> word;
if (ifs.eof())
{
break;
}
std::cout << word << "\n";
}
int main()
{
char *n;
int count=0,count1=0;
ofstream output("user.txt");
output<<"aa bb cc";
output.close();
ifstream input("user.txt");
while(!input.eof())
{
count++;
if(count1<count)
cout<<" ";
count1=count;
input>>n;
cout<<n;
}
cout<<"\ncount="<<count;
getch();
}
I am trying to read a poorly formatted text file, and maybe I'm going about this the wrong way, but based on the getline documentation it sounded like it would pull values until the values weren't a delimiter value (' ', in my case):
"If the delimiter is found, it is extracted and discarded, i.e. it is
not stored and the next input operation will begin after it. If you
don't want this character to be extracted, you can use member get
instead."
But for some reason it returns nothing many times. See lines 604-607, all those commas in my output are returns of getline. Could someone tell me why it is returning blanks 6 times before it comes to the value? The text file only contains one space before the value. Thanks in advance. :)
Relevant screenshot: http://j.drhu.me/2011-09-07_1317.png
#include <iostream>
#include <fstream>
#include <string>
void CMuscleModel::LoadOpParams()
{
int i, j;
ifstream param("params.txt", ios::in);
if (param.is_open())
{
stringstream iss, isn;
string line, word;
i=0; j=0;
while (getline(param,line))
{
isn.clear();
isn << line;
if(i>27){
while (getline(isn,word,' ')) {
//LGma[i][j]=atof(word.c_str());
if(word == "SM"){
getline(param,line);
cout << line << endl << endl;
isn.clear(); isn << line;
getline(isn,word,' ');
int junk=0;
while (atof(word.c_str())==0){
junk++;
getline(isn,word,' ');
}
cout << atof(word.c_str()) << ", " << junk << endl;
}
if(word == "ST"){
cout << word << endl;
}
if(word == "BFL"){
cout << word << endl;
}
if(word == "BFS"){
cout << word << endl;
}
if(word == "MG"){
cout << word << endl;
}
if(word == "LG"){
cout << word << endl;
}
if(word == "RF"){
cout << word << endl;
}
if(word == "VM"){
cout << word << endl;
}
if(word == "VL"){
cout << word << endl;
}
if(word == "VI"){
cout << word << endl;
}
j++;
}
}
j=0; i++;
isn.clear();
}
}
param.close();
}
Ah, sorry for not including code.
If you're using space as a delimiter anytime it's encountered getline will return with whatever there was upto the delimiter. If the file had 5 spaces in a row before any other characters for example you'd now have to call getline 6 times.
Perhaps use the default newline character instead '\n'?
Edit: Didn't see code before. Perhaps restructure your code to read lines and then use find in conjunction with substr on each line to search for your keywords? Would be simpler code and less looping. There is no reason to read from the file only to output to a stringstream which you then read from.
Bi-directional I/O with std::stringstream is really ambiguous. I recommand that you use it a little differently.
ifstream param("params.txt", ios::in);
if (param.is_open())
{
stringstream iss;
string line, word;
i=0; j=0;
while (getline(param,line))
{
istringstream isn(line);
// ...
}
}
This creates a fresh string stream with clean state and contains the contents of the line read from the file each time. If you really want to re-use the instance for reading tokens on multiple lines, I recommand you use the .str(line) syntax rather than .clear() and operator<<.
If you want to clear the whitespace at the beginning of each line, you can use the std::ws manipulator:
istringstream isn(line);
isn >> ws;
// ...
I think the output text file I was reading from had trailing spaces and they were just being put into the stream so I was really confused about what was going on. I simply used .str("") at the end of each line to reset my current stream and things worked out marvelously. Thanks for all the help guys.
I'm trying to parse a simple string in C++. I know the string contains some text with a colon, followed immediately by a space, then a number. I'd like to extract just the number part of the string. I can't just tokenize on the space (using sstream and <<) because the text in front of the colon may or may not have spaces in it.
Some example strings might be:
Total disk space: 9852465
Free disk space: 6243863
Sectors: 4095
I'd like to use the standard library, but if you have another solution you can post that too, since others with the same question might like to see different solutions.
std::string strInput = "Total disk space: 9852465";
std::string strNumber = "0";
size_t iIndex = strInput.rfind(": ");
if(iIndex != std::string::npos && strInput.length() >= 2)
{
strNumber = strInput.substr(iIndex + 2, strInput.length() - iIndex - 2)
}
For completeness, here's a simple solution in C:
int value;
if(sscanf(mystring.c_str(), "%*[^:]:%d", &value) == 1)
// parsing succeeded
else
// parsing failed
Explanation: the %*[^:] says to read in as many possible characters that aren't colons, and the * suppresses assignment. Then, the integer is read in, after the colon and any intervening white space.
I can't just tokenize on the space (using sstream and <<) because the text in front of the colon may or may not have spaces in it.
Right, but you can use std::getline:
string not_number;
int number;
if (not (getline(cin, not_number, ':') and cin >> number)) {
cerr << "No number found." << endl;
}
Similar to Konrads answer, but using istream::ignore:
int number;
std::streamsize max = std::numeric_limits<std::streamsize>::max();
if (!(std::cin.ignore(max, ':') >> number)) {
std::cerr << "No number found." << std::endl;
} else {
std::cout << "Number found: " << number << std::endl;
}
I'm surprised that no one mentioned regular expressions. They were added as part of TR1 and are included in Boost as well. Here's the solution using regex's
typedef std::tr1::match_results<std::string::const_iterator> Results;
std::tr1::regex re(":[[:space:]]+([[:digit:]]+)", std::tr1::regex::extended);
std::string str("Sectors: 4095");
Results res;
if (std::tr1::regex_search(str, res, re)) {
std::cout << "Number found: " << res[1] << std::endl;
} else {
std::cerr << "No number found." << std::endl;
}
It looks like a lot more work but you get more out of it IMHO.
const std::string pattern(": ");
std::string s("Sectors: 4095");
size_t num_start = s.find(pattern) + pattern.size();