I have a required where i need to extract a number from a string in the needed format like :
f001-->100
f100-->1
2030-->302
0203-->3020
2031-->1302
so the operation above is :
remove any f character if it is present
reverse the string
remove leading zeros from the string
I have written a code which is working fine in c++:
int main(int argc,char* argv[])
{
string str1(argv[argc-1]);
reverse(str1.begin(),str1.end());
str1.erase(remove(str1.begin(),str1.end(),'f'),str1.end());
str1.erase(0,str1.find_first_not_of('0',0));
cout <<str1<<endl;
return 0;
}
is there any better way of doing the same thing?
I Guess, a simple function as below will do the job
NOTE:- It is not a complete program. Just a flow... It will parse the string once in stead of 3 times as in your case. I definitely hope there are better C++ style approach, and looking forward to the same.
foo(char* str) {
int state=0;
int len=strlen(str);
for(i=len-1; i>=0; i++) {
if(state==0 && str[i]!='0') { //Ignore trailing zeros
state=1;
}
else if(stare==1) {
if(str[i]=='f')
break;
//Reverse logic here, just store the char in a heap as it comes which will be returned after the for finishes
}
}
}
Related
I am really having a hard time getting recursions but i tried recursion to match a pattern inside a string.
Suppose i have a string geeks for geeks and i have a pattern eks to match.I could use many methods out there like regex, find method of string class but i really want to do this thing by recursions.
To achieve this i tried this code:
void recursion(int i,string str)
{
if(!str.compare("eks"))
cout<<"pattern at :"<<i<<'\n';
if(i<str.length() && str.length()-1!=0)
recursion(i,str.substr(i,str.length()-1));
}
int main()
{
string str("geeks for geeks");
for(int i=0;i<str.length();i++)
recursion(i,str.substr(i,str.length()));
}
Output :
Desired Ouput :
pattern at 2
pattern at 12
What could i be doing wrong here and what would be a good way to do this with recursions?
I understood a lot of topics in cpp but with recursions , i know how they work and even with that whenever i try to code something with recursions , it never works.Could there be any place that could help me with recursions as well?
You will never get pattern at 2, since compare doesn't work like that. Ask yourself, what will
std::string("eks for geeks").compare("eks")
return? Well, according to the documentation, you will get something positive, since "eks for geeks" is longer than "eks". So your first step is to fix this:
void recursion(int i, std::string str){
if(!str.substr(0,3).compare("eks")) {
std::cout << "pattern at: " << i << '\n';
}
Next, we have to recurse. But there's something off. i should be the current position of your "cursor". Therefore, you should advance it:
i = i + 1;
And if we reduce the length of the string in every iteration, we must not test i < str.length, otherwise we won't check the later half of the string:
if(str.length() - 1 > 0) {
recursion(i, str.substr(1));
}
}
Before we actually compile this code, let's reason about it:
we have a substring of the correct length for comparison with "eks"
we never use i except for the current position
we advance the position before we recurse
we "advance" the string by removing the first character
we will end up with an empty string at some point
Seems reasonable:
#include <iostream>
#include <string>
void recursion(int i, std::string str){
if(!str.substr(0,3).compare("eks")) {
std::cout << "pattern at: " << i << '\n';
}
i = i + 1;
if(str.length() - 1 > 0) {
recursion(i, str.substr(1));
}
}
int main () {
recursion(0, "geeks for geeks");
return 0;
}
Output:
pattern at: 2
pattern at: 12
However, that's not optimal. There are several optimizations that are possible. But that's left as an exercise.
Exercises
compare needs to use substr due to it's algorithm. Write your own comparison function that doesn't need substr.
There's a lot of copying going on. Can you get rid of that?
The for loop was wrong. Why?
Recursive function must not run into loop. And you have some mistakes.Try this code.
void recursion(string str, string subStr, int i){
if(str.find(subStr) != string::npos ) {
int pos = str.find(subStr);
str = str.substr(pos + subStr.length(), str.length()-1);
cout << "pattern at " << (pos + i) << endl;
recursion(str, subStr, pos+subStr.length() );
}
}
int main(int argc, char** argv) {
string str("geeks for geeks");
string subStr("eks");
recursion(str, subStr, 0);
return 0;
}
I'm creating a program in which I get the path of a file, then send it as a parameter into another program. The problem is when I get the path, it has the special character '\', which completely mess up the string I send to the other program. Is there a way I can ignore the escape character or change it to '/'?
Thanks!!
To change the \ to /, a simple iteration over the string should suffice. The required code is:
's' is assumed to be the concerned string.
for (int i = 0; i < s.length(); i++)
{
if (s[i] == `\`)
s[i] = `/`;
}
Please elaborate your question. The problem may be with second program.
First Program may be :
char str1[50]="start abc.exe ";
char str2[20];
cin>>str2;
strcat(str1,str2);
system(str1);
Second program may be (abc.exe) :
int main(int argc,char *argv[])
{
for(i=1;i<argc;i++)
{
cout<<argv[i]<<" \n";
}
}
This is just an example.
I'm making a class to delete repeated character from a random word. For example if the input is "aabbccddeeff", it should output "abcdef". However my output contains strange characters after "abcdef". The main.cpp file already exists as the requirements for creating the class. Please see the following codes:
main.ccp
#include <iostream>
#include "repeatdeletion.h"
using namespace std;
int main()
{
char* noRepeats;
int length;
string s;
cout<<"Enter a random word with repeating characters: ";
cin>>s;
RepeatDeletion d;
length=s.length();
noRepeats=d.deleteRepeats(s, length);
cout<<"Your word without any repeating characters: ";
for (int k=0; k<length; k++){
cout<<noRepeats[k];
}
cout<<endl;
delete [] noRepeats;
noRepeats=NULL;
return 0;
}
repeatdeletion.h
#ifndef REPEATDELETION_H
#define REPEATDELETION_H
#include <iostream>
using namespace std;
class RepeatDeletion
{
char* c;
char arr[128]={};
bool repeated;
bool isRepeated(char);
public:
RepeatDeletion();
~RepeatDeletion();
char* deleteRepeats(string, int);
};
#endif // REPEATDELETION_H
repeatdeletion.cpp
#include "repeatdeletion.h"
RepeatDeletion::RepeatDeletion()
{
repeated=false;
}
RepeatDeletion::~RepeatDeletion()
{
delete [] c;
c=NULL;
}
bool RepeatDeletion::isRepeated(char c){
bool repeated=false;
if (arr[c]>=1){
repeated=true;
arr[c]++;
}else{
arr[c]++;
}
return repeated;
}
char* RepeatDeletion::deleteRepeats(string str, int len){
c=new char[len];
int j=0;
for (int i=0; i<len; i++){
if (isRepeated(str[i])==false){
c[j]=str[i];
j++;
}
}
return c;
}
Your return character array is not null terminated.
The length function of string does not include \0.
You have two choices
Add null at the end of returned character array, and std::cout the char array directly (instead of char by char)
Output the final length of your char array, and use that as range to print it char by char
Your printing loop loops using the old and unmodified string length. That means you will go outside the characters you added to memory returned by deleteRepeats.
The easiest solution to handle this is to terminate the data as a proper string, and check for the terminator in the loop.
If you want to use a C-string array, they have a null terminator at the end. That means you'll want to (in deleteRepeats) define your character array one character larger than the length:
c=new char[len+1];
And, after the for loop, ensure you put that null terminator in:
c[j] = '\0';
Then, in your calling function, you can just do:
cout << noRepeats;
Even if you don't want to use C strings, you'll need to communicate the new length back to the caller somehow (currently, you're using the original length). The easiest way to do that is (IMNSHO) still using a C-style string and using strlen to get the new length (a).
Otherwise, you're going to need something like a reference parameter for the new length, populated by the function and used by the caller.
(a) But I'd suggest rethinking the way you do things. If you want to be a C++ coder, be a C++ coder. In other words, use std::string for strings since it avoids the vast majority of problems people seem to have with C strings.
That's because in your code you write the following:
cout<<"Your word without any repeating characters: ";
for (int k=0; k<length; k++){
cout<<noRepeats[k];
}
cout<<endl;
Here, length refers to the length of the original string (which you, by the way shouldn't pass to your deleteRepeats method). I would suggest you make deleteRepeats return a string and write something like this:
std::string noRepeats = d.deleteRepeats(s);
std::cout << "Your word without any repeating characters: ";
std::cout << noRepeats << std::endl;
C-style string (char *, if you insist) follow the convention that the last character is '\0', indicating that the string ends. You could also change deleteRepeats by appending '\0', i.e.
char* RepeatDeletion::deleteRepeats(string str){
c = new char[str.size() + 1];
int j = 0;
for (int i = 0; i < str.size(); i++){
if(isRepeated(str[i]) == false){
c[j] = str[i];
j++;
}
}
c[j] = '\0';
return c;
}
and in your main
std::cout << noRepeats << std::endl;
instead of the for loop. But really, you should use std::string, and if possible not mix it with char *. Hope that helps.
for(k=0;k<length;k++)
Here length should be the exact length of noRepeats, but not of s
so :
char* RepeatDeletion::deleteRepeats(string str, int len)
should return the length-after too
use std::unique it does what you want:
std::string s{};
std::cin>>s;
auto it = std::unique(std::begin(s), std::end(s));
s.resize(std::distance(std::begin(s),it));
std::cout << s;
the way it works is to go through the range begin to end and move all the remaining elements forward if the current element is equal to the next. It returns the position of the end of the new string (it in this example) but does not actually shorten the string so on the next line we shorten the string to the length equal to the distance of begin() to it.
see live at http://ideone.com/0CeaHW
Hi everyone well I tried looking for an answer but I couldn't find. (I found how to use it) but the thing is that i just don't know why my code isn't working. Here is my code:
#include <iostream>
#include <string>
using namespace std;
string acorta(string palabra, int carac)
{
string acortado;
acortado=palabra;
if(palabra.length() > carac)
{
return acortado;
}
else
{
acortado.resize(carac);
return acortado;
}
}
int main(int argc, char** argv) {
cout<< acorta("Univesidad",5)<<endl; // here it should show "Unive"
cout<< acorta("Secretariado",10)<<endl; //here it should show "Secretaria"
cout<< acorta("Estudio",11)<<endl; //here it should show "Estudio" since th number is long than the word
return 0;
}
well supposedly the program should receive a string and a integer because it should return the string as long as the int says. For example ("Laptop",4) it should return "Lapt". If the int is larger than the word then it should return the whole word.
The problem is that the program return the whole word when it shouldn't do the. So i think the the problem is that it is not going in to my function. Please correct me if i am wrong.
if(palabra.length() > carac)
You're telling it to return the original string if it's longer than the integer you pass in. You want to invert that:
if(palabra.length() <= carac)
Better yet, don't repeat yourself and no need for unnecessary copies of the parameter, which is already a copy of the original:
if(palabra.length() > carac)
{
palabra.resize(carac);
}
return palabra;
Or, you could make use of the substr function, though if you don't want to do needless substrings, you can tweak it:
return palabra.substr(0, carac);
If you do that, you don't even need a copy of the string anymore:
string acorta(const string &palabra, int carac)
I want to reverse the letters of the words in a string and have to store it in the same array.example: i/p: hi how are you o/p: ih woh era uoy. i wrote this programs but it just prints the same string without reversing and the program is not terminating it continues to print something. i cant findout the mistake. please help me and tell me the correct code.
#include<iostream.h>
#include<conio.h>
#include<stdio.h>
void stre(char (&a1)[20], int j1, int i1)
{
char b[20];
for(int k=i1-j1;k<i1;k++)
b[k]=a1[i1-k-1];
for(k=i1-j1;k<i1;k++);
a1[k]=b[k];
}
void main()
{
clrscr();
int j;
char a[20];
gets(a);
for(int i=0;a[i]!='\0';i++)
{
j++;
if(a[i]==' ')
{
stre(a,j,i);
j=0;
}
}
stre(a,j,i);
for(j=0;j<i;j++)
cout<<a[j];
getch();
}
friends after your answers i removed the semicolon in the for loop and also initialized j=0 but still i am not able to get the required output now for the i/p:hi how are you o/p:ihh hi hhi hhi. still need your help.
for(k=i1-j1;k<i1;k++);
a1[k]=b[k];
The semilcolon after the for loop prevents the last action from occuring multiple times.
try
#include <iostream>
using namespace std;
int main() {
int j =0;
char a[20] = "hi how are you";
char b[20] = "";
int l=0;
for(int i=0;a[i]!='\0';i++){
if(a[i]==' ' ||a[i+1]=='\0'){
cout<<j<<' '<<i;
if(a[i+1]=='\0'){
b[l++] = ' ';
}
for(int k=i;k>=j;k--){
b[l]=a[k];
l++;
}
for(int k=j;k<=i;k++){
cout<<b[k];
a[k] = b[k];
}
cout<<endl;
j = i+1;
}
}
cout << a;
return 0;
}
This for loop is terminated by the semi-colon:
for(k=i1-j1;k<i1;k++);
^^^
Here's a version that is not perfect by any means, but at least, it tries to be more like C++ than C:
http://ideone.com/f5vciW
first: tokenize into words and space sequences
//the spaces should be preserved
std::string test("hi how are you"),reference("ih woh era uoy");
std::vector<std::string> tokens;
tokenize(test,tokens);
then reverse the tokens
for (auto& token : tokens)
std::reverse(token.begin(),token.end());
assemble tokens into a string buffer
std::stringstream buf;
for (auto token : tokens)
buf<<token;
check the result
std::string res=buf.str();
assert(res==reference);
where the tokenizer looks like that:
template <typename TContainer,typename TString>
void tokenize(TString input,TContainer& res)
{
if (input.length()<2) {
res.push_back(input);
return;
}
typename TString::const_iterator pos=input.begin();
bool space_state=std::isspace(input[0],std::locale());
for (typename TString::const_iterator it=input.begin(); it!=input.end();
++it) {
bool is_space=std::isspace(*it,std::locale());
if (is_space!=space_state) {
res.push_back(TString(pos,it));
pos=it;
space_state=is_space;
}
}
//the rest
if (pos!=input.end()) {
res.push_back(
TString(
pos,
static_cast<typename TString::const_iterator>(input.end())
));
}
}
you passed j without assigning the value. so it will be garbage.
I can see two things in your code that may not result in the expected output:
1)
int j;
should be replaced with
int j=0;
And
for(k=i1-j1;k<i1;k++);
a1[k]=b[k];
the semicolon after the for loop needs to be removed.
FYI, this mixing of C and C++ code is not recommended (it's compromising readability). please stick to either one of them.
A similar example is shown on this site. They've also used almost the same approach that you'v e chosen(reversing each word by counting number of spaces) by with the help of stack data structure.
Make sure you have the STL library installed in your environment to run this code. Better run this code on linux platform.
Here's another, shorter version, doing the inversion in-line without using an extra buffer:
http://ideone.com/hs9NZ7
the criterion for the tokenizer is the change in the isspace condition:
auto next_token=
[&](char c) {
return std::isspace(c,loc)!=std::isspace(*pos,loc);
};
using that we can go through the input string and visit the tokens:
for (auto it=std::find_if(pos,test.end(),next_token);
it!=test.end();
it=std::find_if(pos,test.end(),next_token))
reversing them and updating the current position
std::reverse(pos,it);
pos=it;
and not forgetting the leftover token.