Finding Word + X letters after it - c++

I want to start of by saying that I am still learning and some might think that my code looks bad, but here it goes.
So I have this text file we can call example.txt.
A line in example.txt can look like this:
randomstuffhereitem=1234randomstuffhere
I want my program to take in the numbers that are next to the item= and I have started a bit on it using the following code.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string word;
int main()
{
ifstream readFile("example.txt", ios::app);
ofstream outfile("Found_Words.txt", ios::app);
bool found = false;
long int price;
cout << "Insert a number" << endl;
cout << "number:";
cin >> number;
system("cls");
outfile << "Here I start:";
while( readFile >> word )
{
if(word == "item=")
Here is the problem; first of all it only searchs for "item=" but to find it, it cannot be included with other letters. It has to be a standalone word.
It wont find:
helloitem=hello
It will find:
hello item= hello
It has to be separated with spaces which is also a problem.
Secondly I want to find numbers next to the item=. Like I want it to be able to find item=1234 and please note that 1234 can be any number like 6723.
And I dont want it to find what comes after the number, so when the number stops, it wont take in anymore data. Like item=1234hello has to be item=1234
{
cout <<"The word has been found." << endl;
outfile << word << "/" << number;
//outfile.close();
if(word == "item=")
{
outfile << ",";
}
found = true;
}
}
outfile << "finishes here" ;
outfile.close();
if( found = false){
cout <<"Not found" << endl;
}
system ("pause");
}

You can use a code like this:
bool get_price(std::string s, std::string & rest, int & value)
{
int pos = 0; //To track a position inside a string
do //loop through "item" entries in the string
{
pos = s.find("item", pos); //Get an index in the string where "item" is found
if (pos == s.npos) //No "item" in string
break;
pos += 4; //"item" length
while (pos < s.length() && s[pos] == ' ') ++pos; //Skip spaces between "item" and "="
if (pos < s.length() && s[pos] == '=') //Next char is "="
{
++pos; //Move forward one char, the "="
while (pos < s.length() && s[pos] == ' ') ++pos; //Skip spaces between "=" and digits
const char * value_place = s.c_str() + pos; //The number
if (*value_place < '0' || *value_place > '9') continue; //we have no number after =
value = atoi(value_place); //Convert as much digits to a number as possible
while (pos < s.length() && s[pos] >= '0' && s[pos] <= '9') ++pos; //skip number
rest = s.substr(pos); //Return the remainder of the string
return true; //The string matches
}
} while (1);
return false; //We did not find a match
}
Note that you should also change the way you read strings from file. You can either read to newline (std::getline) or to the end of stream, like mentioned here: stackoverflow question

Related

Can't add a gate in order to prevent my code from entering the if second time

That's the first if, which I don't want my code to enter second time, so I added a gate. I have another if, which has as a condition the counter to be equal to 3, so you can imagine that if I don't have a gate for the first if, my code will keep entering the first if, as 2 comes before 3 always. Now what's my problem... Whenever I add the condition with the gate and the line (gate=0) inside the if my code goes on an infinity loop. Also, if I set the gate in a different value than 1, I get the same infinity loop. Please help me.
EDIT: Below you can find a better example of my code in order to help me. Thank you :)
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream file;
file.open ("file.txt");
ofstream file1;
file1.open ("file1.txt");
char counter = 0;
char ch;
char x;
string word;
string word2;
string word3;
int gate = 1;
word.clear();
while (file >> std::noskipws >> ch) {
if (ch == ' ') {
++counter;
}
else if (ch != ' ') {
counter = 0;
}
if ( (counter == 2) && (gate == 1) ) {
gate = 0;
x = file.get();
while ( x != ' ' ) {
word = word + x;
x = file.get();
}
counter = 1;
word2 = word;
word.clear();
file2 << word1 << " ";
}
if (counter == 3) {
x = file.get();
while ( x != ' ' ) {
word = word + x;
x = file.get();
}
counter = 1;
word3 = word;
word.clear();
file2 << word3 << endl;
word3.clear();
gate = 1;
}
if (file.eof()) {
break;
}
}
file.close();
file1.close();
return 0;
}
Your endless loop is probably here:
x = file.get();
while ( x != ' ' ){
word = word + x;
x = file.get();
}
If you reach the end of the input stream, x will become EOF, which is different from space and thus the while-loop will never be left. Do check for EOF or check the eofbit from the istream (file).

print 2nd word in a string with its size in C++

I am trying to make a program in which a user enters a string and i will print out the second word in the string with its size.
The delimiter's are space( ), comma(,) and tab( ).
I have used a character array and fgets to read from user and a character pointer that points to the first element of the array.
source code:
#include"iostream"
#include<stdio.h>
#include<string>
using namespace std;
// extract the 2nd word from a string and print it with its size(the number of characters in 2nd word)
int main()
{
char arr[30], arr1[30];
char *str = &arr1[0];
cout<<"Enter a string: ";
fgets(str, 30, stdin);
int i = 0, j, count = 1, p = 0; // count is used to find the second word
// j points to the next index where the first delimiter is found.
// p is used to store the second word found in character array 'arr'
while(*(str+i) != '\n')
{
if(*(str+i) == ' ' || *(str+i) == ',' || *(str+i) == ' ')
{
count++;
if(count == 2)
{
// stroing 2nd word in arr character array
j = i+1;
while(*(str+j) != ' ' || *(str+j) != ',' || *(str+j) != ' ')
{
arr[p] = *(str+j);
cout<<arr[p];
p++;
i++;
j++;
}
break;
}
}
i++;
}
arr[p+1] = '\0'; // insert NULL at end
i = 0;
while(arr[i] != '\0')
{
cout<<arr[i];
i++;
}
cout<<"("<<i<<")"<<endl;
return 0;
}
Help me out with this.
To start, don't use std::cin for testing. Just set a value in your code for consistency and ease of development. Use this page for a reference.
#include <iostream>
#include <string>
int main() {
std::string str("this and_that are the tests");
auto start = str.find_first_of(" ,\n", 0);
auto end = str.find_first_of(" ,\n", start + 1);
std::cout << str.substr(start, end - start);
return 0;
}
And this is still somewhat of a hack, it just depends where you are going. For instance the Boost library is rich with extended string manipulation. If you are going to parse out more than just one word it can still be done with string manipulations, but ad-hoc parsers can get out of hand. There are other tools like Boost Spirit to keep code under control.
The delimiters used when extracting from a stream depends on the locale currently in effect. One (cumbersome) way to change the extraction behaviour is to create a new locale with a special facet in which you specify your own delimiters. In the below example the new locale is used to imbue a std::stringstream instead of std::cin directly. The facet creation part is mostly copy/paste from other answers here on SO, so you'll find plenty of other examples.
#include <iostream>
#include <locale> // std::locale, std::ctype<char>
// https://en.cppreference.com/w/cpp/locale/ctype_char
#include <sstream> // std::stringstream
#include <algorithm> // std::copy_n
#include <vector> // a container to store stuff in
// facet to create our own delimiters
class my_facet : public std::ctype<char> {
mask my_table[table_size];
public:
my_facet(size_t refs = 0)
: std::ctype<char>(&my_table[0], false, refs)
{
// copy the "C" locales table to my_table
std::copy_n(classic_table(), table_size, my_table);
// and create our delimiter specification
my_table[' '] = (mask)space;
my_table['\t'] = (mask)space;
my_table[','] = (mask)space;
}
};
int main() {
std::stringstream ss;
// create a locale with our special facet
std::locale loc(std::locale(), new my_facet);
// imbue the new locale on the stringstream
ss.imbue(loc);
while(true) {
std::string line;
std::cout << "Enter sentence: ";
if(std::getline(std::cin, line)) {
ss.clear(); // clear the string stream from prior errors etc.
ss.str(line); // assign the line to the string stream
std::vector<std::string> words; // std::string container to store all words in
std::string word; // for extracting one word
while(ss>>word) { // extract one word at a time using the special facet
std::cout << " \"" << word << "\" is " << word.size() << " chars\n";
// put the word in our container
words.emplace_back(std::move(word));
}
if(words.size()>=2) {
std::cout << "The second word, \"" << words[1] << "\", is " << words[1].size() << " chars\n";
} else {
std::cout << "did not get 2 words or more...\n";
}
} else break;
}
}
#include"iostream"
#include<stdio.h>
#include<string>
#include <ctype.h>
using namespace std;
int main()
{
char c;
string str;
char emp = ' ';
cout<<"Enter a string: ";
getline (cin,str);
int j = 0, count = 1, counter = 0;
for (int i = 0; i < str.length() && count != 2; i++)
{
cout<< str[i] <<endl;
if( isspace(str[i]) || str[i] == ',' || str[i] == '\t' )
{
count++;
if(count == 2)
{
j = i+1;
while(j < str.length())
{
if (isspace(str[j]) || str[j] == ',' || str[j] == '\t')
{
break;
}
cout<<str[j];
counter++;
j++;
}
cout<<endl;
}
}
}
cout<<"size of the word: "<<counter<<endl;
return 0;
}
This is a simple answer to what you want, hope to help you.
// Paul Adrian P. Delos Santos - BS Electronics Engineering
// Exercise on Strings
#include <iostream>
#include <sstream>
using namespace std;
int main(){
// Opening Message
cout << "This program will display the second word and its length.\n\n";
// Ask for a string to the user.
string input;
cout << "Now, please enter a phrase or sentence: ";
getline(cin, input);
// Count the number of words to be used in making a string array.
int count = 0;
int i;
for (i=0; input[i] != '\0'; i++){
if (input[i] == ' ')
count++;
}
int finalCount = count + 1;
// Store each word in a string array.
string arr[finalCount];
int j = 0;
stringstream ssin(input);
while (ssin.good() && j < finalCount){
ssin >> arr[j];
j++;
}
// Display the second word and its length.
string secondWord = arr[1];
cout << "\nResult: " << arr[1] << " (" << secondWord.size() << ")";
return 0;
}

Parsing out things surrounded by quotes in C++

I'm trying to make a parser that would only take text surrounded by quotes and place it in a new file I've already tried many times but can't figure it out it would have to take the original text out of a file by the way then place it in a new file I would like to do this in C++.
This is what I currently have:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char current_letter;
char quote_mark = '"';
int isquote = 0;
std::cin >> current_letter;
LOOP : do
{
if(current_letter == quote_mark) {++isquote;}
if(isquote == 1 && current_letter != quote_mark) {std::cout << current_letter;}
if(isquote == 1 && current_letter == quote_mark) {--isquote;}
if(isquote == 0) {goto LOOP;}
} while (cin >> current_letter);
if(cin != current_letter) {cout << "END" <<endl;}
return(0);
It doesn't print anything now but it used to print out random stuff or just quote marks.
You could just do something like this:
string str;
getline(cin, str);
string currStr = "";
for (int i = 0; i < str.length(); i++)
{
if (str[i] != '\"') currStr += str[i];
}
cout << currStr << "\n";
This won't work if there are double quotes within the text that you want to parse however.

Separate two inputs C++

I have made a quiz helper, but, as I want it for you to be able to input a new question without starting it, I made a do/while loop. The first run goes fine. When it asks you if you want to input another question, if you choose y, it runs the main program too at the same time, and the program registers y as a question. How do I separate this?Code:
#include <cctype>
#include <iostream>
#include <string>
#include "Quiz.h"
#include "Quiz2.h"
char choice;
int main()
{
do{
quiz();
std::cout << "Da li zelite da vam odgovorim na jos jedno pitanje?(y/n)" << std::endl;
std::cin >> choice;
} while(choice != 'n');
}
The first header file just includes the function to find words:
#ifndef QUIZ_H_INCLUDED
#define QUIZ_H_INCLUDED
bool contains_word(const std::string& sentence, const std::string& word)
{
size_t pos = 0;
while ((pos = sentence.substr(pos).find(word)) != std::string::npos) {
if (!(isalpha(sentence[pos - 1])) || !(isalpha(sentence[pos + word.size() + 1])))
return true;
}
return false;
}
#endif
And the other one contains the real code, it is partially in Serbian:
#ifndef QUIZ2_H_INCLUDED
#define QUIZ2_H_INCLUDED
int quiz()
{
std::string sentence;
std::cout << "Ukucajte pitanje ili kljucne reci: " << std::flush;
std::getline(std::cin, sentence);
std::string word ("Belgija");
std::string word2 ("regija");
std::string word3 ("Kanada");
std::string word4 ("teritorija");
std::string word5 ("Holandija");
std::string word6 ("delova");
if (contains_word(sentence, word) && contains_word(sentence, word2))
std::cout << "Odgovor je 3 regije." << std::endl;
else if (contains_word(sentence, word3) && contains_word(sentence, word4))
std::cout << "Odgovor je 3 teritorije." << std::endl;
else if (contains_word(sentence, word5) && contains_word(sentence, word6))
std::cout << "Odgovor je 3 dela." << std::endl;
else
std::cout << "Nisam mogao pronaci odgovor na to pitanje!" << std::endl;
return 0;
}
#endif
Any help is appreciated.
There is a newline character after a choice, so just add cin.ignore:
std::cin >> choice;
std::cin.ignore();
It ignores one character from input.
Alternative solution
Alternatively, you could discard all empty lines in quiz() function - substitute
std::getline(std::cin, sentence);
with
do {
std::getline(std::cin, sentence);
} while( sentence.empty() );
Other issue with the code
The contains_word function should be corrected. You shouldn't get value of sentence[pos + word.size() + 1] if it is possible for the word to be at the very end of sentence (subscript past the end of array).
Similar error in sentence[pos - 1] - what if pos is 0? You get some random stuff before the string.
You have to rework the condition also - certainly if( !(...) || !(...) ) is not what you wanted.
Should be something like this:
bool contains_word(const std::string& sentence, const std::string& word)
{
size_t pos = 0;
while ((pos = sentence.substr(pos).find(word)) != std::string::npos) {
if( (pos == 0 || isalpha(sentence[pos - 1])) &&
(pos + word.size() == sentence.size() || isalpha(sentence[pos + word.size()])) )
return true;
}
return false;
}
getline() and cin don't play well together. After a cin operation there is typically a newline left in the input stream that the getline reads and immediately concludes it is done. You can "solve" the problem by calling getline twice and ignoring the first result. However note that this only happens AFTER a call to cin, so the first time thru you should NOT use getline twice. This is why I say they "don't play well together".

Why doesn't this code run?

Hey, sorry if this is asked a lot but I have no idea what the problem here is.
In the C++ code below, I'm reading from a user defined input file and generating output. I've been writing it piece by piece and putting it together, compiling, testing, etc as I go to work out the bugs. This is a learning experience for me, first self-directed program I guess...
Anyways, when I run the code, the command prompt prints ONE line and goes unresponsive. I would say it has been caught in some kind of loop, but I believe that's impossible.
I think it might have something to do with the array I'm trying to declare, I wanted to make a dynamic string array but I found out that's difficult...
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cctype>
#include <string>
using namespace std;
int wordCount(string line)
{
int fpos, fpos2;
int count = 0;
fpos = line.find_first_not_of(' ');
line.erase(0, fpos);
while(line.size() > 0)
{
fpos = line.find_first_of(' ');
if(line.at(0) == '"')
{
line.erase(0, 1);
for(int i = 0; i <line.size(); i++)
if(line.at(i) == '"' && line.at(i-1) != '\\')
{
fpos2 = i;
break;
}
line.erase(0, fpos2 + 2);
}
else
line.erase(0, fpos + 1);
count++;
}
return count;
}
int main()
{
//Current line; Input file; Output file;
string currentline, fileName, outFileName;
ifstream fin;
ofstream fout;
cout << "Enter input file name: ";
getline(cin, fileName);
cout << "Enter output file name: ";
getline(cin, outFileName);
fin.open(fileName.c_str());
if (!fin.good()) throw "I/O error";
fout.open(outFileName.c_str());
if (!fout.good()) throw "I/O error";
getline(fin, currentline);
while (!currentline.empty())
{
int pos, pos1;
pos = currentline.find("//");
string postScript = currentline.substr(pos+2,-1);
pos = currentline.find_first_of(';');
string xline = currentline.substr(0,pos+1);
cout << xline << endl;
int size = wordCount(xline);
string *words;
words = (string *) malloc (size*sizeof(string));
words = new string[size];
pos = xline.find_first_not_of(' ');
xline.erase(0, pos);
for ( int i = 0; i < size; i++ )
{
pos = xline.find_first_of(' ');
if ( xline.at(0) == '"' )
{
xline.erase(0, 1);
for(int a = 0; a < xline.size(); a++) //This for loop finds the end of a quoted statement within the line.
if ( xline.at(a) == '"' && xline.at(a-1) != '\\' )
{
pos = a;
break;
}
words[i] = xline.substr(0,pos);
xline.erase(0,pos + 2);
}
else
{
words[i] = xline.substr(0,pos);
xline.erase(0,pos + 1);
}
cout << words[i] << endl;
}
cout << xline << endl << endl;
getline(fin, currentline);
}
return 0;
}
I would suggest you commenting out bits of code until it starts to work the way you expect (Usually the problematic bit will become obvious this way.) Once you figure out what is wrong you can ask a more specific question on StackOverflow.
You should use a debugger to investigate the program behavior.
To avoid single stepping the whole program, you can set breakpoints where you expect to passs the sequence. When a breakpoint is not hit you can use single stepping from the previous point. Additionally you can look at variables content.
It never finds the end quote:
if ( xline.at(a) == '"' && xline.at(a-1) != '\\' )
{
pos = a;
break;
}
Try this instead:
if (xline.at(a) == '"')
{
pos = a;
break;
}
You only need to escape " if its contained in a string literal, e.g. "There's a \" in this literal"