Process was terminated. It took longer than 12000ms to complete - c++

Create a function that takes a sentence and turns every "i" into "wi" and "e" into "we", and add "owo" at the end.
I was creating the function for the above question and received an error:
Process was terminated. It took longer than 12000ms to complete
Can anyone please help me with the fix?
#include<string>
std::string owofied(std::string sentence) {
int pos=0;
for(int i =0 ; i<sentence.size(); i++)
{
if(sentence[i]=='i')
sentence.replace(i,1,"wi");
else if(sentence[i]=='e')
sentence.replace(i,1,"we");
pos=i;
}
sentence.insert(pos,"owo");
return sentence;
}

Your code turns "e" into "we". But then it turns the "e" in "we" into "we", creating another "we" that also gets replaced.
One simple fix is to increment i an extra time after the replacement.

When you insert a wi or we, you are not incrementing i past that replacement, so the next iteration finds that new i/e and replaces it, and so on, and so on, endlessly, until the code either times out or runs out of memory.
Try this instead:
#include <string>
std::string owofied(std::string sentence)
{
std::string::size_type i = 0;
while (i < sentence.size())
{
if (sentence[i] == 'i')
{
sentence.replace(i, 1, "wi", 2);
i += 2;
}
else if (sentence[i] == 'e')
{
sentence.replace(i, 1, "we", 2);
i += 2;
}
else {
++i;
}
}
return sentence + "owo";
}
Which can then be simplified a little by using std::string::find_first_of() to find the characters to replace, eg:
#include <string>
std::string owofied(std::string sentence)
{
std::string::size_type i = 0;
char replacement[2] = { 'w', '?' };
while ((i = sentence.find_first_of("ie", i, 2)) != std::string::npos)
{
replacement[1] = sentence[i];
sentence.replace(i, 1, replacement, 2);
i += 2;
}
return sentence + "owo";
}
Alternatively, since the "replacements" are really just "insertions" of w:
#include <string>
std::string owofied(std::string sentence)
{
std::string::size_type i = 0;
while ((i = sentence.find_first_of("ie", i, 2)) != std::string::npos)
{
sentence.insert(i, 1, 'w'); // or: sentence.insert(i, "w", 1);
i += 2;
}
return sentence + "owo";
}

Related

Find words in a string with characters that are repeated

I was given the task to remove all extra spaces (should remain 1) and output only those words in which the letters are repeated. I've been sitting for a week and can't find the error, maybe this will help me)))
I've figured out the whitespace, but the word formatting I can't do((
Please help me find a bug in my code
If I enter I like to play soccer every day, the program should output soccer every.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main()
{
char str[128];
printf("Write String: ");
fgets(str, 128, stdin);
int i = 0, j;
i = 0;
int start = i;
while (str[i] != '\0')
{
if (str[i] == ' ' || str[i] == '\n')
{
int end = i;
int first = start;
int first2 = start + 1;
int last = end - 1;
while (first < last)
{
for (first; first < last; first++)
{
for (first2; first2 < last; first2++)
{
if ((str[first] == str[first2]) && (first != first2))
{
break;
}
else
{
if((first == last - 1) && (first2 == last - 1))
{
for (j = start; str[end] != '\0'; ++end)
{
str[j] = str[end + 1];
j += 1;
}
}
}
}
}
}
if (i != start)
{
start = i + 1;
++i;
}
}
else
{
++i;
}
}
}
A possible solution:
read your input one word at a time, and
check if each word has a repeated letter. If it does, print the word.
Now, how to read the input one word at a time. In the example below I've used a std::istringstream, but std::cin would do.
And, how to check if a word has a repeated letter. A simple, surely not the fastest, way is to create a set from an input string, and check if the set and the string don't have the same number of letters. I've used a lambda for has_a_repeated_letter but a function would do.
[Demo]
#include <iostream> // cout
#include <set>
#include <string>
#include <sstream> // istringstream
int main() {
std::istringstream iss{"I like to play soccer every day"};
auto has_a_repeated_letter = [](const std::string& word) {
std::set<char> letters{ word.begin(), word.end() };
return letters.size() != word.size();
};
std::string word{};
while (iss >> word) {
if (has_a_repeated_letter(word)) {
std::cout << word << " ";
}
}
}
// Outputs:
//
// soccer every

How to delete characters in vector of strings?

I am writing a code where I read a subtitle file and remove the text in () including the brackets themselves, that is subtitles for hearing impaired which have background noise in ().
The example:
13
00:01:08,535 --> 00:01:10,127 // remove this
(PIANO PLAYING) // remove this
125
00:07:09,162 --> 00:07:12,393
BOTH: (SINGING WITH RADIO) Teach // remove only the text in parenthesis, including ()
them well and let them lead the way
The code is here:
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
using namespace std;
void subRem();
int main() {
subRem();
system("PAUSE");
}
void subRem() {
ofstream out;
ifstream in;
out.open("whip it2.srt");
if (out.fail()) {
perror("whip it2.srt");
}
in.open("whip it.srt");
if (out.fail()) {
perror("whip it.srt");
}
vector<string> input;
string inc;
while (getline(in, inc)) {
input.push_back(inc);
}
vector<int> len;
for (int i = 0; i < input.size(); i++) {
len.push_back(input[i].size());
}
for (int i = 0; i < input.size(); i++) {
for (int j = 0; j < len[i]; j++) {
if (input[i][j] == '(') {
for (int k = j; k < len[i]; k++) {
j = k;
if (input[i][k] == ')') {
if (k == (len[i] - 1)) {
input[i - 1] = "";
}
input[i][k] = '\0';
break;
}
input[i][k] = '\0';
}
}
}
}
for (int k = 0; k < input.size(); k++) {
out << input[k] << endl;
}
}
I want to delete the characters in parenthesis, so I am using:
input[i][k] = '\0';
The problem is the characters are removed but they are replaced by whitespace, for example:
(SHOUTING) with her?
I get:
___________with her?
(____ are whitespaces because I couldn't make them appear)
There is the white space. If it was string, I could do:
input[i][k] = "";
but with characters I get the error when I do:
input[i][k] = '';
quoted string should contain at least one character
I plan to improve the code further by renaming the line numbers and deleting extra newlines, but I want to create like an app where I can drag and drop the subtitle file and click run, to get the modified subtitle file. What do I need to know to create the GUI? Do I need to learn Qt or some other libraries?
std:;string can contain \0 without problems, it's not the end-of-string character inside a std::string. MikeCAT's suggestion is the correct answer: use std::string::erase.
(Please don't ask multiple questions at once, but yes Qt is a reasonable way to create GUI's)
Try using substr. This method gives you a substring between two given positions. Although this solves the problem for your second problem, it leaves empty subtitles for strings on the first case. I would recommend checking for an empty result and removing the string at all.
Since you're basically copying characters from one file to another, I'd just keep track of whether you're in a subtitle as you copy, and if so, don't copy characters until you encounter a close parenthesis again.
#include <string>
#include <iostream>
#include <sstream>
int main() {
std::istringstream in{
R"(13
00:01:08,535 --> 00:01:10,127
(PIANO PLAYING)
125
00:07:09,162 --> 00:07:12,393
BOTH: (SINGING WITH RADIO) Teach
them well and let them lead the way)"
};
bool in_subtitle = false;
std::string temp;
while (std::getline(in, temp)) {
unsigned line_len = 0;
for (char ch : temp) {
switch (ch) {
case '(': in_subtitle = true; break;
case ')': in_subtitle = false; break;
default:
if (!in_subtitle) {
std::cout << ch;
++line_len;
}
break;
}
}
if (line_len != 0) std::cout << "\n";
}
}
#include <iostream>
#include <regex>
int main() {
std::string text("this text (remove this) and (remove this) end.");
// First Method: with regular expression
std::regex expr("\\(.*?\\)");
std::cout << std::regex_replace (text, expr, "");
// Second Method: with stl
auto begin = text.find_first_of("(");
auto end = text.find_last_of(")") + 1;
if (std::string::npos != begin && std::string::npos != end && begin <= end)
text.erase(begin, end-begin);
// Optional
std::cout << text << std::endl;
}

Printing null character when input is odd character amount

I've been toying with this c program for a while, and I can't seem to figure out what I'm missing.
In the very bottom of my code, I have a function that replaces every other word with a "-".
My problem is that when I enter an odd numbered word, such as "Cat", "dog", "hamburger", it will place a "-" in what I think is the null character position, though I have not been able to debunk it.
Thank you for your help!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void replace(char w[]);
int main( )
{
char w[100], x[100], y[100];
int z = 0;
printf("Player 1, please enter the secret word: ");
fgets(x,100,stdin);
// system("clear");
while( strcmp(x,y) != 0 )
{
strcpy(w,x);
// printf("\nLength of String : %d", strlen(w)-1);
replace(w);
printf("Player 2, the word is %s\n",w);
printf("Player 2, please guess the word: ");
fgets(y,100,stdin);
z++;
if( strcmp(x,y) != 0 )
{
printf("Wrong. Try again.\n");
}
else
{
//system("clear");
printf("Correct!\n");
printf("It took you %d attempt(s).\n",z);
switch (z)
{
case 1 :
case 2 :
printf("A. Awesome work!");
{break;}
case 3 :
case 4 :
printf("B. Best, that was!");
{break;}
case 5 :
case 6 :
printf("C. Concentrate next time!");
{break;}
case 7 :
printf("D. Don't quit your day job.");
{break;}
default :
printf("F. Failure.");
{break;}
}
}
}
getch();
}
void replace(char w[])
{
int a;
a = 0;
while (w[a] != '\0')
{
if (a % 2 != 0)
{
w[a] = '-';
a++;
}
if (w[a] != '\0')
{
a++;
}
else
{
break;
}
}
}
From the fgets manual;
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte (\0) is stored after the last character in the buffer.
The newline entered is what you're replacing.
You can implement like this...
int a;
int len;
a = 0;
len = strlen(w);
if(len%2 == 0)
len = len-1;
while (len!=a)
{
if (a % 2 != 0)
{
w[a] = '-';
a++;
}
if (w[a] != '\0')
{
a++;
}
else
{
break;
}
}
I think replacing fgets with just gets will work:
Try:
//fgets(x,100,stdin);
gets(x);
and
//fgets(y,100,stdin);
gets(y);
That will be enough I think.
The problem is caused by the additional '\n' character in the char array passed to the replace function.
For instance, when the input is "Cat", the passed char[] w contains {'C', 'a', 't', '\n', '\0'};
The additional '\n' also gets replaced with "-" character.
The following will solve this problem.
while (w[a] != '\0')
{
if (w[a] != '\0' && w[a] != '\n')
{
if (a % 2 != 0)
{
w[a] = '-';
}
a++;
}
else
{
break;
}
}
As a bit of an aside, can I suggest structuring your replace() code differently
void replace(char charw[])
{
int length=strlen(charw);
int i;
for (i=0;i<length;i++)
{
if (i%2==1) /*yes, i%2 would also work, but lets not get too clever*/
{charw[i]='-';}
}
}
This is far more readable. Breaking in the middle of a loop...not so much.

Complex algorithm to extract numbers/number range from a string

I am working on a algorithm where I am trying the following output:
Given values/Inputs:
char *Var = "1-5,10,12,15-16,25-35,67,69,99-105";
int size = 29;
Here "1-5" depicts a range value, i.e. it will be understood as "1,2,3,4,5" while the values with just "," are individual values.
I was writing an algorithm where end output should be such that it will give complete range of output as:
int list[]=1,2,3,4,5,10,12,15,16,25,26,27,28,29,30,31,32,33,34,35,67,69,99,100,101,102,103,104,105;
If anyone is familiar with this issue then the help would be really appreciated.
Thanks in advance!
My initial code approach was as:
if(NULL != strchr((char *)grp_range, '-'))
{
int_u8 delims[] = "-";
result = (int_u8 *)strtok((char *)grp_range, (char *)delims);
if(NULL != result)
{
start_index = strtol((char*)result, (char **)&end_ptr, 10);
result = (int_u8 *)strtok(NULL, (char *)delims);
}
while(NULL != result)
{
end_index = strtol((char*)result, (char**)&end_ptr, 10);
result = (int_u8 *)strtok(NULL, (char *)delims);
}
while(start_index <= end_index)
{
grp_list[i++] = start_index;
start_index++;
}
}
else if(NULL != strchr((char *)grp_range, ','))
{
int_u8 delims[] = ",";
result = (unison_u8 *)strtok((char *)grp_range, (char *)delims);
while(result != NULL)
{
grp_list[i++] = strtol((char*)result, (char**)&end_ptr, 10);
result = (int_u8 *)strtok(NULL, (char *)delims);
}
}
But it only works if I have either "0-5" or "0,10,15". I am looking forward to make it more versatile.
Here is a C++ solution for you to study.
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
int ConvertString2Int(const string& str)
{
stringstream ss(str);
int x;
if (! (ss >> x))
{
cerr << "Error converting " << str << " to integer" << endl;
abort();
}
return x;
}
vector<string> SplitStringToArray(const string& str, char splitter)
{
vector<string> tokens;
stringstream ss(str);
string temp;
while (getline(ss, temp, splitter)) // split into new "lines" based on character
{
tokens.push_back(temp);
}
return tokens;
}
vector<int> ParseData(const string& data)
{
vector<string> tokens = SplitStringToArray(data, ',');
vector<int> result;
for (vector<string>::const_iterator it = tokens.begin(), end_it = tokens.end(); it != end_it; ++it)
{
const string& token = *it;
vector<string> range = SplitStringToArray(token, '-');
if (range.size() == 1)
{
result.push_back(ConvertString2Int(range[0]));
}
else if (range.size() == 2)
{
int start = ConvertString2Int(range[0]);
int stop = ConvertString2Int(range[1]);
for (int i = start; i <= stop; i++)
{
result.push_back(i);
}
}
else
{
cerr << "Error parsing token " << token << endl;
abort();
}
}
return result;
}
int main()
{
vector<int> result = ParseData("1-5,10,12,15-16,25-35,67,69,99-105");
for (vector<int>::const_iterator it = result.begin(), end_it = result.end(); it != end_it; ++it)
{
cout << *it << " ";
}
cout << endl;
}
Live example
http://ideone.com/2W99Tt
This is my boost approach :
This won't give you array of ints, instead a vector of ints
Algorithm used: (nothing new)
Split string using ,
Split the individual string using -
Make a range low and high
Push it into vector with help of this range
Code:-
#include<iostream>
#include<vector>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
int main(){
std::string line("1-5,10,12,15-16,25-35,67,69,99-105");
std::vector<std::string> strs,r;
std::vector<int> v;
int low,high,i;
boost::split(strs,line,boost::is_any_of(","));
for (auto it:strs)
{
boost::split(r,it,boost::is_any_of("-"));
auto x = r.begin();
low = high =boost::lexical_cast<int>(r[0]);
x++;
if(x!=r.end())
high = boost::lexical_cast<int>(r[1]);
for(i=low;i<=high;++i)
v.push_back(i);
}
for(auto x:v)
std::cout<<x<<" ";
return 0;
}
You're issue seems to be misunderstanding how strtok works. Have a look at this.
#include <string.h>
#include <stdio.h>
int main()
{
int i, j;
char delims[] = " ,";
char str[] = "1-5,6,7";
char *tok;
char tmp[256];
int rstart, rend;
tok = strtok(str, delims);
while(tok != NULL) {
for(i = 0; i < strlen(tok); ++i) {
//// range
if(i != 0 && tok[i] == '-') {
strncpy(tmp, tok, i);
rstart = atoi(tmp);
strcpy(tmp, tok + i + 1);
rend = atoi(tmp);
for(j = rstart; j <= rend; ++j)
printf("%d\n", j);
i = strlen(tok) + 1;
}
else if(strchr(tok, '-') == NULL)
printf("%s\n", tok);
}
tok = strtok(NULL, delims);
}
return 0;
}
Don't search. Just go through the text one character at a time. As long as you're seeing digits, accumulate them into a value. If the digits are followed by a - then you're looking at a range, and need to parse the next set of digits to get the upper bound of the range and put all the values into your list. If the value is not followed by a - then you've got a single value; put it into your list.
Stop and think about it: what you actually have is a comma
separated list of ranges, where a range can be either a single
number, or a pair of numbers separated by a '-'. So you
probably want to loop over the ranges, using recursive descent
for the parsing. (This sort of thing is best handled by an
istream, so that's what I'll use.)
std::vector<int> results;
std::istringstream parser( std::string( var ) );
processRange( results, parser );
while ( isSeparator( parser, ',' ) ) {
processRange( results, parser );
}
with:
bool
isSeparator( std::istream& source, char separ )
{
char next;
source >> next;
if ( source && next != separ ) {
source.putback( next );
}
return source && next == separ;
}
and
void
processRange( std::vector<int>& results, std::istream& source )
{
int first = 0;
source >> first;
int last = first;
if ( isSeparator( source, '-' ) ) {
source >> last;
}
if ( last < first ) {
source.setstate( std::ios_base::failbit );
}
if ( source ) {
while ( first != last ) {
results.push_back( first );
++ first;
}
results.push_back( first );
}
}
The isSeparator function will, in fact, probably be useful in
other projects in the future, and should be kept in your
toolbox.
First divide whole string into numbers and ranges (using strtok() with "," delimiter), save strings in array, then, search through array looking for "-", if it present than use sscanf() with "%d-%d" format, else use sscanf with single "%d" format.
Function usage is easily googling.
One approach:
You need a parser that identifies 3 kinds of tokens: ',', '-', and numbers. That raises the level of abstraction so that you are operating at a level above characters.
Then you can parse your token stream to create a list of ranges and constants.
Then you can parse that list to convert the ranges into constants.
Some code that does part of the job:
#include <stdio.h>
// Prints a comma after the last digit. You will need to fix that up.
void print(int a, int b) {
for (int i = a; i <= b; ++i) {
printf("%d, ", i);
}
}
int main() {
enum { DASH, COMMA, NUMBER };
struct token {
int type;
int value;
};
// Sample input stream. Notice the sentinel comma at the end.
// 1-5,10,
struct token tokStream[] = {
{ NUMBER, 1 },
{ DASH, 0 },
{ NUMBER, 5 },
{ COMMA, 0 },
{ NUMBER, 10 },
{ COMMA, 0 } };
// This parser assumes well formed input. You have to add all the error
// checking yourself.
size_t i = 0;
while (i < sizeof(tokStream)/sizeof(struct token)) {
if (tokStream[i+1].type == COMMA) {
print(tokStream[i].value, tokStream[i].value);
i += 2; // skip to next number
}
else { // DASH
print(tokStream[i].value, tokStream[i+2].value);
i += 4; // skip to next number
}
}
return 0;
}

Separator character in string c++

This is the requirement: Read a string and loop it, whenever a new word is encountered insert it into std::list. If the . character has a space, tab, newline or digit on the left and a digit on the right then it is treated as a decimal point and thus part of a word. Otherwise it is treated as a full stop and a word separator.
And this is the result I run from the template program:
foo.bar -> 2 words (foo, bar)
f5.5f -> 1 word
.4.5.6.5 -> 1 word
d.4.5f -> 3 words (d, 4, 5f)
.5.6..6.... -> 2 words (.5.6, 6)
It seems very complex for me in first time dealing with string c++. Im really stuck to implement the code. Could anyone suggest me a hint ? Thanks
I just did some scratch ideas
bool isDecimal(std::string &word) {
bool ok = false;
for (unsigned int i = 0; i < word.size(); i++) {
if (word[i] == '.') {
if ((std::isdigit(word[(int)i - 1]) ||
std::isspace(word[(int)i -1]) ||
(int)(i - 1) == (int)(word.size() - 1)) && std::isdigit(word[i + 1]))
ok = true;
else {
ok = false;
break;
}
}
}
return ok;
}
void checkDecimal(std::string &word) {
if (!isDecimal(word)) {
std::string temp = word;
word.clear();
for (unsigned int i = 0; i < temp.size(); i++) {
if (temp[i] != '.')
word += temp[i];
else {
if (std::isalpha(temp[i + 1]) || std::isdigit(temp[i + 1]))
word += ' ';
}
}
}
trimLeft(word);
}
I think you may be approaching the problem from the wrong direction. It seems much easier if you turn the condition upside down. To give you some pointers in a pseudocode skeleton:
bool isSeparator(const std::string& string, size_t position)
{
// Determine whether the character at <position> in <string> is a word separator
}
void tokenizeString(const std::string& string, std::list& wordList)
{
// for every character in string
// if(isSeparator(character) || end of string)
// list.push_back(substring from last separator to this one)
}
I suggest to implement it using flex and bison with c++ implementation