Copying selected character from string - c++

My input string is
\\?\bac#dos&ven_bb&prod_open-v&rev_5001#1&7f6ac24&0&353020304346333030363338#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
Required output is
bac\dos&ven_bb&prod_open-v&rev_5001\1&7f6ac24&0&353020304346333030363338_0
I have written a following code but is not working...need help is figuring out the problem.
Forgive my ignorance :) Also let me know if there is any better and efficient way to do it.
The rule for the output string is
In the second string i am removing all the "\" and "?" .And where is see the "#" i replace it with "\". and the second string is only till you see the charater "{" but does not include "#" at the end of it.
THanks
int main()
{
char s[] = "\\?\bac#dos&ven_bb&prod_open-v&rev_5001#1&7f6ac24&0&353020304346333030363338#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}";
char s1[] = {0};
printf("OUtput string is : ");
for(int i = 0; s[i] != '{'; i++)
{
if(s[i] != '\\' && s[i] != '?')
{
int j = 0;
if(s[i] == '#')
{
s1[j] = '\\';
continue;
}
s1[j] = s[i];
j++;
}
}
for(int i = 0; s1[i] != '\0'; i++)
{
cout<<s1[i];
}
getch();
}

I would suggest looking into using the std::string::replace() function. There is plenty of online documentation on this. Take a look at some of the other functions that std::string has to offer as they might be of use too. If you are using c++, the use of std::string is usually preferable to tinkering with char arrays and indices.

Note the fixed scope of j. In your version you were always assigning to s1[0].
for(int i = 0, j = 0; s[i] != '{'; i++)
{
if(s[i] != '\\' && s[i] != '?')
{
// int j = 0;
if(s[i] == '#')
{
s1[j] = '\\';
}
else
{
s1[j] = s[i];
}
j++;
}
}
The other thing is to allocate enough space for the new string. Since you haven't specified the size char s1[] = {0}; declares an array of size 1. You need to do something like:
char s1[sizeof(s)] = { 0 }; // the size of the old array, since we don't know how long the new one will be
But since you tagged the Q C++, take advantage of of dynamically resizable std::string.
std::string s = ".......";
std::string s1;
for(int i = 0; s[i] != '{'; i++)
{
if(s[i] != '\\' && s[i] != '?')
{
if(s[i] == '#')
s1 += '\\';
else
s1 += s[i];
}
}

Your s1 buffer needs to be increased, as it stands now there is no room for the new string.
E.g.
char* s1 = calloc(strlen(s)+1,sizeof(char)); // same size should be enough, free(s1) later
the calloc ensures that it is \0 terminated, in your code you forgotten to add the \0 so the printout act erratically.

Related

Strings Code not Working

Using the C++ language, the function LetterChanges(str) takes the str parameter being passed and modifies it using the following algorithm.
Replace every letter in the string with the letter following it in the
alphabet (ie. c becomes d, z becomes a). Then capitalize every vowel
in this new string (a, e, i, o, u) and finally return this modified
string.
#include <iostream>
using namespace std;
string LetterChanges(string str) {
// code goes here
string str2 = "abcdefghijklmnopqrstuvwxyz";
int j;
for (int i = 0; str[i] != '\0'; i++) {
for (j = 0; str2[j] != '\0'; j++) {
if (str[i] == str2[j]) {
str[i] = str2[j + 1];
}
}
}
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == 'a') {
str[i] = 'A';
}
else if (str[i] == 'e') {
str[i] = 'E';
}
else if (str[i] == 'i') {
str[i] = 'I';
}
else if (str[i] == 'o') {
str[i] = 'O';
}
else if (str[i] == 'u') {
str[i] = 'U';
}
}
return str;
}
int main() {
// keep this function call here
cout << LetterChanges(gets(stdin));
return 0;
}
I am trying to run this code but it is not giving the desire output please help..
The Function
Let's start with your first loop:
for (int i = 0; str[i] != '\0'; i++) {
for (j = 0; str2[j] != '\0'; j++) {
if (str[i] == str2[j]) {
str[i] = str2[j + 1];
}
}
}
There are a couple things here. Firstly, we don't even need to deal with str2. Characters in C++ use ASCII encoding, meaning we can actually do something like str[i]++ to change an 'a' to a 'b' or an 'e' to an 'f', etc...
Also, I'd advise against using str[i] != '\0'. We're using the standard library strings instead of c-strings for a reason, so we might as well make our lives easier and use str.size(). Along these same lines, I'd suggest str.at(i) as opposed to str[i] as the former will do bounds checking for us.
Lastly, if you include cctype, then we can use the isalpha function to make sure we're only modifying alphabetic characters (no numbers or spaces, etc..).
Thus your first loop can become:
for (int i = 0; i < str.size(); i++) {
if(isalpha(str.at(i)){
if(str.at(i) == 'z') str.at(i) = 'a'; //special case
else str.at(i)++;
}
}
As far as your second loop, you don't even need it! We can actually incorporate everything straight into the first one. As long as we make sure to do the vowel modification after we've changed the individual letters.
A conversion from lowercase to uppercase can be done with some ASCII math as well. The difference between the lowercase and uppercase letters is 'A'-'a', so if we add that to any lowercase letter, it'll give us its uppercase version!
With all of this, we can modify your code to:
for (int i = 0; i < str.size(); i++) {
if(isalpha(str.at(i)){ //Make sure it's a letter!
if(str.at(i) == 'z') str.at(i) = 'a'; //special case
else str.at(i)++;
if(str.at(i) == 'a' | str.at(i) == 'e' | str.at(i) == 'i'
| str.at(i) == 'o' | str.at(i) == 'u') {
str.at(i) += 'A' - 'a';
}
}
Your Main
There's only one thing to fix here. Don't use gets for input. If you're looking for a single word, use the extraction operator, >>, or if you want a whole line, use getline.
string word, line;
getline(cin, line);
cin >> word;
cout << LetterChanges(line) << endl;
cout << LetterChanges(word) << endl;

C++ split string to vector<string>

The function I am using is
vector<string> tokenise(string s){
}
Firstly, I intend to split the string into substrings, in which case the string is always arithmetic expression (e.g. "100+5") and there could be some whitespaces.
"100+5" is needed to convert to "100", "+", "5"
After conversion, the substrings will be stored in a vector and return it. I am struggling with the fist step and using the subscript to loop over a string. The type of the value returned is char, so there is no way to put it in the vector.
You could just call the string's substring method, after figuring out the range of characters that are either digits, arithmetic characters, or unwanted.
You mentioned - The type of the value returned is char, so there is no way to put it in the vector.
You have some function that returns a character. You want to then insert the equivalent string into the vector.
Assuming your vector is defined as
std::vector<std::string> broken_strings;
So you can do it as follows.
char ch = ...; // Here comes the character that you get from the function.
std::string str(1, ch);
broken_strings.push_back(str);
Then you can return broken_strings.
Edit:
OP mentions that he wants to tokenize algebraic expressions.
So it will have to be done it a different way.
Following is a simple approach.
std::vector<std::string> broken;
std::string temp;
for ( int i = 0; i<s.length() ;i++){
char ch = s[i];
if (ch == ' ')
continue;
else if (ch >= '0' && ch <='9')
temp += ch;
else{
if (temp.length() != 0)
broken.push_back(temp);
temp = "";
temp += ch;
broken.push_back(temp);
temp = "";
}
}
if (temp.length() != 0)
broken.push_back(token);
return broken;
You can see the demo of the same here
Ideone
vector<string> tokenise(string s)
{
vector<string> v;
string number;
for(int i = 0; i < s.length(); ++i)
{
if((s[i] >= '0') && (s[i] <= '9'))
{
number += string(1, s[i]);
}
else if(s[i] == '.')
{
number += string(1, s[i]);
}
else if((s[i] == '+') || (s[i] == '-') || (s[i] == '*') || (s[i] == '/'))
{
if(number.size())
{
v.push_back(number);
number.clear();
}
v.push_back(string(1, c));
}
}
if(number.size())
{
v.push_back(number);
number.clear();
}
return v;
}

Removing stopwords from char array

I'm trying to make a function that removes a pre-defined word (a char array) from a char array. It sort of works and removes the word from a char array, but it only works if the words are separated by spaces. I want to make it so it removes the word from a group of words not separated by spaces, but I don't know how. I'm stuck on this and would appreciate any help.
int i, j = 0, k = 0, count = 0;
char str[1024] = "thisisthestringtobealtered."; // works using spaces
char key[256] = "the"; // I want "the" to be removed in str
char str1[10][20];
void removeWordFromString(){
/* Converts the string into 2D array */
for (i = 0; str[i] != '\0'; i++) {
if (str[i] == ' ') {
str1[k][j] = '\0';
k++;
j = 0;
}
else {
str1[k][j] = str[i];
j++;
}
}
str1[k][j] = '\0';
/* Compares the string with given word */
for (i = 0; i < k + 1; i++) {
if (strcmp(str1[i], key) == 0) {
for (j = i; j < k + 1; j++)
strcpy(str1[j], str1[j + 1]);
k--;
}
}
for (i = 0; i < k + 1; i++) {
printf("%s ", str1[i]);
}
}
A possible solution for this problem would be using strncmp().
This function allows you to compare substrings.
Start like this:
Compare the initial string with the key with num = length of the key.
If it does match cut the substring out
move one character into the initial string and compare again.
Loop until you have less characters in the initial string left than your key is long.
void removeWordFromString(){
/* Converts the string into 2D array */
int ckey=0;
i=0;
while(str[i] != '\0')
{
while(str[i] == key[ckey] && key[ckey] != '\0')
{
str1[k][j] = str[i];
j++;
i++;
ckey++;
}
if ( key[ckey] == '\0' )
{
str1[k][j-strlen(key)] = '\0';
k++;
j = 0;
ckey=0;
}
else{
str1[k][j] = str[i];
j++;
i++;
ckey=0;
}
}
str1[k][j] = '\0';
for (i = 0; i < k + 1; i++) {
printf("%s ", str1[i]);
}
}
Replace the above function in your code.
I would go for a readable algorithm.
Find the place in the string where the key occurs.
while I can find such a place, then
remove this occurrence
look for the next.
Or in code:
char str[1024] = "thisisthestringtobealtered."; // works using spaces
char key[256] = "the"; // I want "the" to be removed in str
void removeWordFromString(){
char* p = strstr(str, key);
while (p) {
// Move from end of key, to start of key, the number of characters we can
// find after the key, plus a null terminator. Memmove because the string
// overlaps itself.
memmove(p, p + strlen(key), strlen(p) - strlen(key) + 1);
p = strstr(str, key);
}
}
Note that this solution is very code-size-efficient and probably too clever to pass as first-year programmer code. I hope this makes it useful to you for learning while ineligible for handing in as a code exercise solution :-)

String error output [duplicate]

This question already has answers here:
C++ Remove punctuation from String
(12 answers)
Closed 9 years ago.
I got a code. It should give me an output that will erase the middle character between 'z' and 'p'. for example: zipZap("zipXzap"): expected [zpXzp] but found [z pXz p]
std::string zipZap(const std::string& str){
string a = str;
string b = "";
size_t len = str.length();
for (size_t i = 0; i < len; i++){
if (str[i] == 'z')
if (str[i+2] == 'p')
a[i+1] = ' ';
}
return a;
}
When i replaced a[i+1] = ''; it gave me an error.
You are not removing the chars, you are replacing them with ' '.
There are many ways to do this. One simple way is to build a new string, only adding chars when the proper conditions are met:
std::string zipZap(const std::string& str)
{
string a;
size_t len = str.length();
for (size_t i = 0; i < len; i++) {
// Always add first and last chars. As well as ones not between 'z' and 'p'
if (i == 0 || i == len-1 || (str[i-1] != 'z' && str[i+1] != 'p')) {
a += str[i];
}
}
return a;
}
Use string.erase() :
std::string zipZap(const std::string& str){
std::string a = str;
std::string b = "";
size_t len = str.length();
for (size_t i = 0; i < len; i++){
if (a[i] == 'z')
if (a[i+2] == 'p')
a.erase(i+1,1);
}
return a;
}
You're completely right that you cant replace an element of the string with ''.
A string is an array of chars, and '' is not a char at all. It is nothing.
If we look at the cplusplus page for a string
http://www.cplusplus.com/reference/string/string/
We see that we can use erase(iterator p) to "Erase characters from string (public member function)"
So if we change:
for (size_t i = 0; i < len; i++){
if (str[i] == 'z')
if (str[i+2] == 'p')
a.erase(a.begin() + i + 1);
We're closer now, but we can see that len is no longer the same as str.length(). the length of a is now actually 1 char shorter than len. To remedy this however we can simply add:
for (size_t i = 0; i < len; i++){
if (str[i] == 'z')
if (str[i+2] == 'p')
a.erase(a.begin() + i + 1);
len -= 1;
Hope that helps
If you #include <regex>, you can do a regular expression replacement.
std::string zipZap(const std::string& str){
regex exp("z.p");
string a = str;
a = regex_replace(a, exp "zp");
return a;
}

Remove spaces from a string in C++

I am currently learning C++. I am trying to code a method to remove white spaces form a string and return the string with no spaces
This is my code:
string removeSpaces(string input)
{
int length = input.length();
for (int i = 0; i < length; i++) {
if(input[i] == ' ')
input.erase(i, 1);
}
return input
}
But this has a bug as it won't remove double or triple white spaces.
I found this on the net
s.erase(remove(s.begin(),s.end(),' '),s.end());
but apparently this is returning an iterator (if I understand well)
Is there any way to convert the iterator back to my string input?
Most important is this the right approach?
std::string::erase returns an iterator, but you don't have to use it. Your original string is modified.
string removeSpaces(string input)
{
input.erase(std::remove(input.begin(),input.end(),' '),input.end());
return input;
}
std::remove_if along with erase would be much easier (see it live):
input.erase(remove_if(input.begin(), input.end(), isspace),input.end());
using std::isspace had the advantage it will capture all types of white space.
Let's assume your input has a double space, for example "c++[ ][ ]is[ ]fun" ([ ] represents a single space). The first space has index 3 (numeration starts from 0) and the second space, is of course index 4.
In your for loop, when you hit i == 3 you erase the first space. The next iteration of the loop takes i == 4 as the index. But is the second space at index 4 now ? No! Removing the first space changed the string into "c++[ ]is[ ]fun": the space to remove is at index 3, again!
The solution can be to remove spaces right-to-left:
for (int i = length-1; i >= 0; --i) {
if(input[i] == ' ')
input.erase(i, 1);
}
This solution has the benefit of being simple, but as Tony D points out, it's not efficient.
this should also work -- std::replace( input.begin(), input.end(), ' ', ''); You need to include <algorithm>
this code should work
string removeSpaces(string input)
{
int length = input.length();
for (int i = 0; i < length; i++) {
if(input[i] == ' ')
{
input.erase(i, 1);
length--;
i--;
}
}
return input
}
Reason: if it gets space in the string it will reduce the length of the string, so you have to change the variable: "length" accordingly.
I tried to write something to.
This function take a string and copy to another temporary string all the content without extra spaces.
std::string trim(std::string &str){
int i = 0;
int j = 0;
int size = str.length();
std::string newStr;
bool spaceFlag = false;
for(int i = 0;i < size; i++){
if(str[i] == ' ' && (i+1) < size && str[i+1] == ' '){
i++;
spaceFlag = true;
continue;
}
if(str[i] == ' '){
newStr += " ";
continue;
}
if(str[i] == '\t' && i != 0){
str[i] = ' ';
newStr += " ";
}
else{
newStr += str[i];
if(spaceFlag){
newStr += " ";
spaceFlag = false;
}
}
}
str = newStr;
return str;
}
#include<iostream>
#include<string.h>
using namespace std;
void trimSpace(char s[])
{
int i=0, count=0, j=0;
while(s[i])
{
if(s[i]!=' ')
s[count++]=s[i++];
else {
s[count++]=' ';
while(s[i]==' ')
i++;
}
}
s[count]='\0';
cout<<endl<<" Trimmed String : ";
puts(s);
}
int main()
{
char string[1000];
cout<<" Enter String : ";
gets(string);
trimSpace(string);
return 0;
}