c++ Script that finds questions in string - c++

I am new at coding , been coding for about a week and i am trying to do a script that finds the "?" and the "." in the script , then outputs their position in the script and i use those value to print the question to a text file.
Except it does not really work.
If you put the value in like this, it works.
myfile << test.substr( 18, 20 )
But like this it does not work it just print the whole script from the value of dot[0] until the end of the script.
myfile << test.substr( dot[0], interrogation[0] )
The way that i use to find the "?" position in the string is also not very accurate.
Where there is the .
if(x > 0){
I had a while loop but i replaced it for debugging reasons .
This is the whole code.
If you can help me i appreciate it.
Thanks.
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main (){
std::vector< int > interrogation ;
std::vector< int > dot;
string look = "?";
string look_again = ".";
string test = "ver. o que e isto? nao sei. ola? adeus. fghfghfhfghf";
string::size_type pos = test.find(look);
string::size_type sop = test.find(look_again);
string::size_type exc = test.find(look_again_again);
while (pos != std::string::npos)
{
int a = pos ;
int b = sop;
cout << " . found at : " << sop << std::endl;
cout << " ? found at : " << pos << std::endl;
interrogation.push_back(a);
dot.push_back(b);
string fragment = test.substr (0 , pos ); // works
//cout << fragment << endl ;
string fragment2 = test.substr (0 , sop ); // works
//cout << fragment2 << endl ;
pos = test.find(look, pos + 1);
sop = test.find(look_again, sop + 1);
}
int x = 1;
if(x > 0){
int a = 1;
int q = dot[a];
int w = interrogation[a];
// to save text
// to save text
string save = "saved_question.txt" ;
ofstream myfile;
myfile.open (save.c_str(), ios::app);
myfile << test.substr( 18, 20 ) + "\n" ;
myfile.close();
cout << "Question saved in text file" << endl;
}
}

The code is not finished yet but i got it working with help.
Thanks
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main (){
std::vector< int > interrogation ;
std::vector< int > dot;
//std::vector< int > exclamation;
string look = "?";
string look_again = ".";
string look_again_again = "!";
string test = " ver.o que e isto? nao sei. ola? adeus.";
string::size_type pos = test.find(look);
string::size_type sop = test.find(look_again);
while (pos != std::string::npos)
{
int a = pos ;
int b = sop;
cout << " . found at : " << sop << std::endl;
cout << " ? found at : " << pos << std::endl;
// cout << " ! found at : " << exc << std::endl;
interrogation.push_back(a);
dot.push_back(b);
//exclamation.push_back(c);
string fragment = test.substr (0 , pos ); // works
//cout << fragment << endl ;
string fragment2 = test.substr (0 , sop) ; // works
//cout << fragment2 << endl ;
string fragment3 = test.substr (dot.back() + 1, interrogation.back() - dot.back()); // works
cout << fragment3 << endl ;
pos = test.find(look, pos + 1);
sop = test.find(look_again, sop + 1);
}
}

You can do something like this:
void function(string str) {
string sentence = "";
for(int i=0; i < str.length(); i++) {
if(str[i] == '.' || str[i] == '!')
sentence = ""; // the sentence is not a question so clear the sentence
else if(str[i] == '?') {
sentence.push_back(str[i]);
cout << sentence << endl; // output the question - just replace cout with your ofstream
}
else
sentence.push_back(str[i]);
}
}
I think I've seen this question before though..

Related

How to memoize a recursive problem to avoid re-calculating subproblems?

I am trying to solve this problem:
https://www.geeksforgeeks.org/count-possible-decodings-given-digit-sequence/
Example:
Input:
Input str = "121"
Total decoding:: 3 :: ABA AU LA
I am able to code this problem through recursion. But the code fails to process a bigger input sequence (for e.g., i/p str = 11111111111111111111111111111111111111111)
This is happening because I am calculating sub-problems again-and-again.
Can anyone help me by letting me know how to memoize below sample code?
PS - I know there are other ways to solve this problem. But I don't want to do that. I want to memoize this solution only. It will help me to build my concept. Please help.
Here is the code:
#include "iostream"
#include <iostream>
#include <vector>
#include <string>
using namespace std;
namespace solution3
{
void solve(string str, string& out, vector<string>& v)
{
if (str.size() == 0)
{
v.push_back(out);
return;
}
//we have 2 choices:
//ch#1: take 1st char of str
//ch#2: take 1st and 2nd chars of str
if (str.size() >= 1)//ch#1: take 1st char of str
{
string out1 = out;
string str1 = str;
int num1 = stoi(str.substr(0, 1)); // converting string at index 0 to integer
if (num1) // we will not consider if the string at index 0 is zero.
{
out1.push_back(('#' + num1)); //<-- It will conevrt 1 into A; 2 into B; and so on.
str1 = str1.erase(0, 1);//erase the index 0 from str1.
solve(str1, out1, v);
}
}
if (str.size() >= 2)//ch#2: take 1st and 2nd chars of str
{
string out2 = out;
string str2 = str;
int num2 = stoi(str.substr(0, 2)); // converting string at index 0 and 1 to integer
// checking if num2 is a valid number for decoding.
// num2 should be - NON-ZERO, 1st char is not ZERO, is within the range of 1 and 26.
if (num2 && str[0] != '0' && num2 > 0 && num2 <= 26)
{
out2.push_back(('#' + num2));
//Erase 1st two chars from str
str2 = str2.erase(0, 1);//erase the index 0 from str1.
str2 = str2.erase(0, 1);//erase the index 0 from str1.
solve(str2, out2, v);
}
}
}
void alphacode(string str)
{
string out;
vector<string> v; //<-- To store all the Decodings
solve(str, out, v);
cout << "Total decoding:: " << v.size() << ":: ";
for (int i = 0; i < v.size(); i++)
cout << v[i] << " ";
cout << endl;
}
}
int main()
{
string str = "25114";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "1111111111";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "3333333333";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "202";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "2010";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "1111111111111111111111111111111"; //<-- takes too much time! How to solve this?
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
return 0;
}
You can memoize each substring that you are currently working with, which you're forming after deleting one or two characters, depending on the case. Something like this:
#include "iostream"
#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;
map<string, vector<string>> dp;
namespace solution3
{
void solve(string str, string& out, vector<string>& v)
{
if (str.size() == 0)
{
v.push_back(out);
return;
}
//we have 2 choices:
//ch#1: take 1st char of str
//ch#2: take 1st and 2nd chars of str
if(dp.find(str) != dp.end()) {
vector<string> current = dp[str];
for(string s: current) {
v.push_back(s);
}
return;
}
if (str.size() >= 1)//ch#1: take 1st char of str
{
string out1 = out;
string str1 = str;
int num1 = stoi(str.substr(0, 1)); // converting string at index 0 to integer
if (num1) // we will not consider if the string at index 0 is zero.
{
out1.push_back(('#' + num1)); //<-- It will conevrt 1 into A; 2 into B; and so on.
str1 = str1.erase(0, 1);//erase the index 0 from str1.
solve(str1, out1, v);
}
}
if (str.size() >= 2)//ch#2: take 1st and 2nd chars of str
{
string out2 = out;
string str2 = str;
int num2 = stoi(str.substr(0, 2)); // converting string at index 0 and 1 to integer
// checking if num2 is a valid number for decoding.
// num2 should be - NON-ZERO, 1st char is not ZERO, is within the range of 1 and 26.
if (num2 && str[0] != '0' && num2 > 0 && num2 <= 26)
{
out2.push_back(('#' + num2));
//Erase 1st two chars from str
str2 = str2.erase(0, 1);//erase the index 0 from str1.
str2 = str2.erase(0, 1);//erase the index 0 from str1.
solve(str2, out2, v);
}
}
dp[str] = v;
}
void alphacode(string str)
{
string out;
vector<string> v; //<-- To store all the Decodings
solve(str, out, v);
cout << "Total decoding:: " << v.size() << ":: ";
// for (int i = 0; i < v.size(); i++)
// cout << v[i] << " ";
cout << endl;
}
}
int main()
{
string str = "25114";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "1111111111";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "3333333333";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "202";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "2010";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "1111111111111111111111111111111"; //<-- takes too much time! How to solve this?
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
return 0;
}

how can I find the sequence number (index) of word in such a paragraph c++?

I'm working on a project which needs to find the number of words and the indices of each word in the paragraph ...I have written the code which is counting the number of word in a string but I stuck with finding the indices of words,
such as : Hi John How are you I miss you ..
I need to print the indices like : 0 1 2 3 4 5 6 7
here is the code:
int _tmain(int argc, _TCHAR* argv[])
{
int count_words(std::string);
std::string input_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
int number_of_words=1;
int counter []={0};
for(int i = 0; i < input_text.length();i++)
if(input_text[i] == ' ')
number_of_words++;
std::cout << "Number of words: " << number_of_words << std::endl;
//std:: cout << number_of_words << std::endl;
system ("PAUSE");
}
Hopefully this helps. Edited to include use of count_words function.
#include <iostream>
#include <sstream>
void count_words(std::string);
int main(){
std::string input_text, output_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
count_words(input_text);
system ("PAUSE");
return 0; //MUST RETURN AN INTEGER VALUE FROM 'INT MAIN'
}
void count_words(std::string inputString){
std::string output_text;
std::stringstream indexes;
int number_of_words=0; //If there are no words, it would be false, make it 0.
//int counter []={0}; //This serves no purpose.
if(!inputString.empty()){// test to make sure it isn't empty.
number_of_words++;
for(int i = 0; i < inputString.length();i++){ // For loops should have curly braces {} containing their statement.
if(inputString[i] == ' '){
number_of_words++;
}
if((isalpha(inputString[i]))&&inputString[i-1]==' '){ //test for following space separated word
indexes << i << " ";
}
}
}
output_text = indexes.str(); //convert stringstream to string
std::cout << "Number of words: " << number_of_words << std::endl;
//std:: cout << number_of_words << std::endl; //duplicate info
std::cout << "Indexes: " << output_text << std::endl;
}
I'm not sure if i understand the question. You only need print the "indices"?? like this? (Using your own code)
#include <iostream>
#include <vector>
#include <string>
void stringTokenizer(const std::string& str, const std::string& delimiter, std::vector<std::string>& tokens) {
size_t prev = 0, next = 0, len;
while ((next = str.find(delimiter, prev)) != std::string::npos) {
len = next - prev;
if (len > 0) {
tokens.push_back(str.substr(prev, len));
}
prev = next + delimiter.size();
}
if (prev < str.size()) {
tokens.push_back(str.substr(prev));
}
}
int main()
{
std::vector <std::string> split;
std::string input_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
stringTokenizer(input_text, " ", split);
int number_of_words = 0;
for (std::vector<std::string>::iterator it = split.begin(); it != split.end(); it++, number_of_words++) {
std::cout << *it << " " << number_of_words << std::endl;
}
}

segfault variable creation c++

So I'm having some troubles with a segfault right now.
The problem appears to be on line 122
file_stream.read(binaryData, fileSizeInt);
The message seems to be unable to create variable object.
I'm using the debugger on CLion, if this is of any help.
I'm fairly new to C++ so please bear with me on this. I've included my source code below, since I have no idea what will and wont be relevant.
#include <fstream>
#include <iostream>
#include <math.h>
using namespace std;
//string dataLocation = "/dev/rdisk2"; // Variable for the mounting point of the SD Card.
string dataLocation = "/Volumes/Untitled/data/smith_data_backup.dat"; // Test location
int sectorSize = 512;
int bytesRead = 0;
string outDir = "/Volumes/Untitled/data/readData/";
char data_stop[10] = "Data_Stop";
char* findHeader(char* inputData) {
int i = 1;
//look for the end of the header
while(true) {
//cout << data[i] << '\n';
if (inputData[i] == '}') {
// found the end of the header
cout << "found the end of the header" << '\n';
break;
}
if (i > 200) { // don't get into an infinite loop here
cout << "something went wrong here" << '\n';
break;
}
i++;
}
// copy the header to a new char array
char* header = new char[i+1];
memcpy(header, &inputData[0], (size_t) (i +1));
return header;
}
int main() {
ifstream file_stream;
file_stream.open(dataLocation);
for( int j = 0; j < 10; j++ ) {
char data[sectorSize]; // figure out a decent size for this.....
string date = "";
string time = "";
string site = "";
string intId = "";
string totalFiles = "";
string fileNo = "";
string fileSize = "";
try {
// read the data file... this will be fun
cout << "Reading the data file" << '\n';
file_stream.read(data, sectorSize);
bytesRead += sectorSize;
if (data[0] == '{') {
char *header = findHeader(data);
cout << header << '\n';
//loop over the header to find the date, time, site ID, Instrument ID, and expected file size.
int commasFound = 0;
for(int i = 1; header[i] != '}', i++;) {
// increment the number of commas that have been found
if (header[i] == ',') {
commasFound ++;
continue;
}
//check for the end f the header
if (header[i] == '}') {
break;
}
//for some reason the first one never gets added
if (i==2) {
date += header[1];
}
// append to appropriate strings based on the number of commas that have been passed in the header
if (commasFound == 0) {
date += header[i];
}
if (commasFound == 1 && time.length() < 6) {
time += header[i];
}
if (commasFound == 2) {
fileNo += header[i];
}
if (commasFound == 6) {
site += header[i];
}
if (commasFound == 8) {
intId += header[i];
}
if (commasFound == 16) {
fileSize += header[i];
}
if (commasFound == 17) {
totalFiles += header[i];
}
//paranoia of infinite loops
if (i > 150) {
break;
}
}
string formattedDate = "20" + date.substr(4,2) + date.substr(2,2) + date.substr(0,2);
cout << formattedDate << " " << time << " " << " " << site << " " << intId << " " << fileSize << " " << totalFiles<< " " << '\n';
// Read in the data size
int fileSizeInt = atoi(fileSize.c_str()) * atoi(fileSize.c_str());
char binaryData[fileSizeInt];
file_stream.read(binaryData, fileSizeInt);
bytesRead += fileSizeInt;
string dateDir = outDir + formattedDate.substr(0,4) + "/" + date.substr(2,2) + "/" + site + "/" + date.substr(0,2) + "/";
string fileName = dateDir + formattedDate + "_" + time + "_" + site + "_" + intId + "_Full_Data.dat";
//cout << fileName << '\n';
//create the directory with the date.
string mkdirCommand = "mkdir -p " + dateDir;
system(mkdirCommand.c_str());
cout << "size " << sizeof(binaryData) << '\n';
//write data to file
try {
cout << "Write the data file " << '\n';
cout << header << " " << strlen(header) << '\n';
ofstream outFile;
outFile.open(fileName.c_str());
outFile.write(header, strlen(header));
outFile.write(binaryData, sizeof(binaryData));
outFile.write(data_stop, sizeof(data_stop));
outFile.close();
} catch (ofstream::failure e ) {
cout << "Unable to write the file " << fileName << '\n';
}
//read till the start of the next sector
int nextSector = (int) ceil(((double) bytesRead)/512.0);
int startOfNextSector = nextSector * 512;
cout << startOfNextSector << '\n';
int bytesToRead = startOfNextSector - bytesRead;
char dump[bytesToRead];
file_stream.read(dump, bytesToRead);
bytesRead += bytesToRead;
// The first block may be empty, quick check to see if the first block needs to be skipped
} else if (j == 0 && data[0] != '{') {
cout << "Skipping the first block" << '\n';
continue;
} else {
//cout << "no start here....." << bytesRead << '\n';
}
}
catch (ifstream::failure& e) {
cout << "Error" << "\n";
break;
}
}
file_stream.close();
return 0;
}

Strange Output Difference Between GCC and MinGW (C++)

I'm working on a project for a computer science class. I wrote the code and tested it using MinGW, and it works fine. I then copied the code over to the university's Linux server and tested it there, since that's what my professor grades assignments on. The output is very different - like it printed out a carriage return in the middle of an output.
The interesting thing is, the issue also appears when compiled and run with Cygwin GCC (32-bit, 4.7.2). Does anyone have any insight as to why this is happening and how to fix it?
Code and a sample input file (to be named lifepath.txt and placed in the same directory as the executable).
#include <iostream>
#include <fstream>
#include <map>
#include <set>
#include <string>
#include <cstdlib>
using namespace std;
bool younger(string s1, string s2) {
string y1 = s1.substr(s1.rfind('-')+1);
string y2 = s2.substr(s2.rfind('-')+1);
if(y1 < y2) return true;
else if(y1 > y2) return false;
string m1 = s1.substr(s1.find('-')+1, s1.rfind('-')-s1.find('-')-1);
string m2 = s2.substr(s2.find('-')+1, s2.rfind('-')-s2.find('-')-1);
if(m1 < m2) return true;
else if(m1 > m2) return false;
string d1 = s1.substr(0, s1.find('-'));
string d2 = s2.substr(0, s2.find('-'));
return d1 < d2;
}
int main() {
ifstream in("lifepath.txt");
map<int, int> pathcounts;
set<string> bdays;
string oldest, youngest;
map<string, int> years;
string line;
while(getline(in, line)) {
string monthday = line.substr(0, line.rfind('-'));
bdays.insert(monthday);
string num = line;
while(num.find('-') != string::npos) num.erase(num.find('-'));
int path = atoi(num.c_str()) % 9 + 1;
pathcounts[path]++;
if(youngest == "" || younger(line, youngest)) youngest = line;
if(oldest == "" || younger(oldest, line)) oldest = line;
years[line.substr(line.rfind('-')+1)]++;
}
for(int i = 1; i <= 9; i++) {
cout << i << ": " << pathcounts[i] << endl;
}
cout << endl;
cout << "The oldest birthday is " << oldest << endl;
cout << "The youngest birthday is " << youngest << endl;
cout << endl;
cout << "There are " << bdays.size() << " unique birthdays" << endl;
cout << endl;
string modeyear = "";
int modeyearcount = 0;
for(map<string, int>::iterator it = years.begin(); it != years.end(); it++) {
if(it->second > modeyearcount) {
modeyear = it->first;
modeyearcount = it->second;
}
else if(it->second == modeyearcount) modeyear += " " + it->first;
}
cout << "The mode of the birthyears is " << modeyear;
cout << ", appearing " << modeyearcount << " times" << endl;
return 0;
}
I will post a link to an image of the output as a reply, since I don't have enough rep to have more than two links in a post.
This is because different line endings, \r in Windows' case means just go to the beginning of the line, when you're reading data from a file and set the years array. You use keys, not just #### but ####\r, and this last symbol is displayed during cout.
So you need to change your code:
years[line.substr(line.rfind('-')+1, 4)]++;

C++ Parsing a line out of a large file

I have read an entire file into a string from a memory mapped file Win API
CreateFile( "WarandPeace.txt", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 )
etc...
Each line is terminated with a CRLF. I need to find something on a line like "Spam" in the line "I love Spam and Eggs" (and return the entire line (without the CRLF) in a string (or a pointer to the location in the string) The original string cannot be altered.
EDITED:
Something like this:
string ParseStr( string sIn, string sDelim, int nField )
{
int match, LenStr, LenDelim, ePos, sPos(0), count(0);
string sRet;
LenDelim = sDelim.length();
LenStr = sIn.length();
if( LenStr < 1 || LenDelim < 1 ) return ""; // Empty String
if( nField < 1 ) return "";
//=========== cout << "LenDelim=" << LenDelim << ", sIn.length=" << sIn.length() << endl;
for( ePos=0; ePos < LenStr; ePos++ ) // iterate through the string
{ // cout << "sPos=" << sPos << ", LenStr=" << LenStr << ", ePos=" << ePos << ", sIn[ePos]=" << sIn[ePos] << endl;
match = 1; // default = match found
for( int k=0; k < LenDelim; k++ ) // Byte value
{
if( ePos+k > LenStr ) // end of the string
break;
else if( sIn[ePos+k] != sDelim[k] ){ // match failed
match = 0; break; }
}
//===========
if( match || (ePos == LenStr-1) ) // process line
{
if( !match ) ePos = LenStr + LenDelim; // (ePos == LenStr-1)
count++; // cout << "sPos=" << sPos << ", ePos=" << ePos << " >" << sIn.substr(sPos, ePos-sPos) << endl;
if( count == nField ){ sRet = sIn.substr(sPos, ePos-sPos); break; }
ePos = ePos+LenDelim-1; // jump over Delim
sPos = ePos+1; // Begin after Delim
} // cout << "Final ePos=" << ePos << ", count=" << count << ", LenStr=" << LenStr << endl;
}// next
return sRet;
}
If you like it, vote it up. If not, let's see what you got.
If you are trying to match a more complex pattern then you can always fall back to boost's regex lib.
See: http://www.boost.org/doc/libs/1_41_0/libs/regex/doc/html/index.html
#include <iostream>
#include <string>
#include <boost/regex.hpp>
using namespace std;
int main( )
{
std::string s;
std::string sre("Spam");
boost::regex re;
ifstream in("main.cpp");
if (!in.is_open()) return 1;
string line;
while (getline(in,line))
{
try
{
// Set up the regular expression for case-insensitivity
re.assign(sre, boost::regex_constants::icase);
}
catch (boost::regex_error& e)
{
cout << sre << " is not a valid regular expression: \""
<< e.what() << "\"" << endl;
continue;
}
if (boost::regex_match(line, re))
{
cout << re << " matches " << line << endl;
}
}
}
Do you really have to do it in C++? Perhaps you could use a language which is more appropriate for text processing, like Perl, and apply a regular expression.
Anyway, if doing it in C++, a loop over Prev_delim_position = sIn.find(sDelim, Prev_delim_position) looks like a fine way to do it.
system("grep ....");