Replacing spaces in a string with increasing numbers - c++

I need a program to take a string and replace spaces with increasing numbers.
#include <cstring>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
// Get the String
string str = "this essay needs each word to be numbered";
int num = 1;
string x = num;
int i = 0;
// read string character by character.
for (i < str.length(); ++i) {
// Changing the loaded character
// to a number if it's a space.
if (str[i] == ' ') {
str[i] = x;
++num
}
}
// testing outputs
cout << str << endl;
cout << num << endl;
ofstream file;
file.open ("numbered.txt");
file << str;
file.close();
return 0;
}
I had it at the point where it could replace spaces with a letter or symbol and save to a new file but when I tried to make it a number it stopped working. I would need it to say "this1essay2needs3each4word5to6be7numbered

For ease and clarity, change your approach.
Put the string into an istringstream
Extract each space-separated substring and place into an std::vector<string>
Feed the contents of the vector into a stringstream and
use std::to_string(num) to add the numbers between the substrings
e.g.:
std::string str = "this essay needs each word to be numbered";
int num = 1;
std::istringstream istr(str);
std::string temp;
std::vector<std::string> substrs;
while (istr >> temp)
{
substrs.push_back(temp);
}
std::stringstream ostr;
for (auto&& substr : substrs)
{
ostr << substr << std::to_string(num++);
}

Let's break the problem down into parts. We can make a SpaceReplacer object that does the replacement. It has an Output, which it can use as a function to output characters:
template<class Output>
struct SpaceReplacer {
Output output;
int num_spaces;
void input(char c) {
if(c == ' ') {
auto num_as_string = std::to_string(num_spaces);
num_spaces += 1;
for(char digit : num_as_string) {
output(digit);
}
}
else {
output(c);
}
}
};
Every time you input a character, it either outputs the character you input, or it outputs the digits of the number (if the character was a space).
We should write a helper function to make SpaceReplacers:
template<class Output>
SpaceReplacer<Output> makeReplacer(Output output_func) {
return SpaceReplacer<Output>{output_func, 0};
}
Reading one string, returning new string
It's now easy to write a function that replaces spaces in a string.
std::string replaceSpaces(std::string const& input) {
std::string output_string;
// We output chars by appending them to the output string
auto output_func = [&](char c) { output_string += c; };
auto replacer = makeReplacer(output_func);
for(char c : input) {
replacer.input(c);
}
return output_string;
}
Reading input from file, replacing spaces and returning a string
Because we wrote a really generic SpaceReplacer class, we can modify the function so that it'll read input directly from a FILE*
std::string replaceSpaces(FILE* file) {
std::string output_string;
auto output_func = [&](char c) { output_string += c; };
auto replacer = makeReplacer(output_func);
while(true) {
int input_char = fgetc(file);
if(input_char == EOF) {
break;
}
replacer.input(input_char);
}
return output_string;
}
Reading input from one file, immediately appending it to different file with spaces replaced
We can also read directly from one file, and output directly to another file, with no delay. This might be useful if you were processing a very large amount of data.
void replaceSpaces(FILE* input_file, FILE* output_file) {
auto output_func = [=](char c) { fputc(c, output_file); };
auto replacer = makeReplacer(output_func);
while(true) {
int input_char = fgetc(input_file);
if(input_char == EOF) {
break;
}
replacer.input(input_char);
}
}

In this case, you need to use another string for the result.
#include <cstring>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
// Get the String
string result, str = "this essay needs each word to be numbered qwe qwe wqe qwe qwe qwe q";
int num = 0;
int i;
// read string character by character.
for (i=0; i < str.length(); i++) {
// Changing the loaded character
// to a number if it's a space.
if (str[i] == ' ')
result+=std::to_string(++num);
else
result+=str[i];
}
// testing outputs
cout<<result<<endl;
cout<<num;
ofstream file;
file.open ("numbered.txt");
file << result;
file.close();
return 0;
}

You have to replace it with a character, not by a number.
str[i] = num+'0';

Related

How to replace "pi" by "3.14"?

How to replace all "pi" from a string by "3.14"? Example: INPUT = "xpix" ___ OUTPUT = "x3.14x" for a string, not character array.
This doesn't work:
#include<iostream>
using namespace std;
void replacePi(string str)
{
if(str.size() <=1)
return ;
replacePi(str.substr(1));
int l = str.length();
if(str[0]=='p' && str[1]=='i')
{
for(int i=l;i>1;i--)
str[i+2] = str[i];
str[0] = '3';
str[1] = '.';
str[2] = '1';
str[3] = '4';
}
}
int main()
{
string s;
cin>>s;
replacePi(s);
cout << s << endl;
}
There is a ready to use function in the C++ lib. It is called: std::regex_replace. You can read the documentation in the CPP Reference here.
Since it uses regexes it is very powerful. The disadvantage is that it may be a little bit too slow during runtime for some uses case. But for your example, this does not matter.
So, a common C++ solution would be:
#include <iostream>
#include <string>
#include <regex>
int main() {
// The test string
std::string input{ "Pi is a magical number. Pi is used in many places. Go for Pi" };
// Use simply the replace function
std::string output = std::regex_replace(input, std::regex("Pi"), "3.14");
// Show the output
std::cout << output << "\n";
}
But my guess is that you are learning C++ and the teacher gave you a task and expects a solution without using elements from the std C++ library. So, a hands on solution.
This can be implemented best with a temporary string. You check character by character from the original string. If the characters do not belong to Pi, then copy them as is to new new string. Else, copy 3.14 to the new string.
At the end, overwrite the original string with the temp string.
Example:
#include <iostream>
#include <string>
using namespace std;
void replacePi(string& str) {
// Our temporay
string temp = "";
// Sanity check
if (str.length() > 1) {
// Iterate over all chararcters in the source string
for (size_t i = 0; i < str.length() - 1; ++i) {
// Check for Pi in source string
if (str[i] == 'P' and str[i + 1] == 'i') {
// Add replacement string to temp
temp += "3.14";
// We consumed two characters, P and i, so increase index one more time
++i;
}
else {
// Take over normal character
temp += str[i];
}
}
str = temp;
}
}
// Test code
int main() {
// The test string
std::string str{ "Pi is a magical number. Pi is used in many places. Go for Pi" };
// Do the replacement
replacePi(str);
// Show result
std::cout << str << '\n';
}
What you need is string::find and string::replace. Here is an example
size_t replace_all(std::string& str, std::string from, std::string to)
{
size_t count = 0;
std::string::size_type pos;
while((pos=str.find(from)) != str.npos)
{
str.replace(pos, from.length(), to);
count++;
}
return count;
}
void replacePi(std::string& str)
{
replace_all(str, "pi", "3.14");
}

C++ reverse a string but printing numbers first

I was given a project in class and almost have it finished, I am required to take a string of numbers and letters and return that string with the numbers printed first followed by the letters in reverse order (ex. abc123 should return 123cba). As of now my code returns a string with the numbers first and the original order of the letters (ex. abc123 returns 123abc). I would be able to do this with two loops however the assignment asks that my code only iterates though the initial string one time. Here is the code I have so far...
#include <iostream>
#include <string>
#include "QueType.h"
#include "StackType.h"
using namespace std;
int main ()
{
QueType<char> myQueue;
StackType<char> myStack;
string myString="hello there123";
char curchar;
string numbers, letters;
for (int i = 0; i < myString.length(); i++) {
if (isdigit(myString.at(i))) {
myQueue.Enqueue(myString.at(i));
myQueue.Dequeue(curchar);
numbers += curchar;
//cout<<numbers<<endl;
}
else if (islower(myString.at(i))) {
myStack.Push(myString.at(i));
curchar = myStack.Peek();
myStack.Pop();
letters += curchar;
//cout<<curchar<<endl;
}
}
cout<<(myString = numbers + letters)<<endl;
}
In my code, I have two .h files that set up a stack and a queue. With the given string, the code loops through the string looking to see if it sees a letter or number. With a number the spot in the string is then saved to a queue, and with a letter it is saved to the stack.
The only other way i can think of reversing the order of the letters is in the if else statement instead of having char = myStack.Peek() every loop, change it to char += myStack.Peek() however I get weird lettering when that happens.
since you already got the string with letters you can basically reverse it and that's it.
//emplace version:
void reverse_str(std::string& in)
{
std::reverse(in.begin(), in.end());
}
//copy version
std::string reverse_str(std::string in)
{
std::reverse(in.begin(), in.end());
return in;
}
in your case the emplace version would be the best match.
in other cases (e.g. when you want to preserve the original string) the copy version is preferred.
adding an example to make it as clean as possible.
int main()
{
std::string inputstr = "123abc";
std::string numbers{};
std::string letters{};
for(auto c : inputstr)
{
if(isdigit(c))
numbers += c;
else
letters += c;
}
reverse_str(letters); //using the emplace version
std::cout << numbers + letters;
}
Here's my take. It only loops through the string once. I don't have your types, so I'm just using the std versions.
std::string output;
output.reserve( myString.size() );
std::stack<char> stack;
for ( char c : myString ) {
if ( std::isdigit( c ) ) // if it's a number, just add it to the output
output.push_back( c );
else // otherwise, add the character to the stack
stack.push( c );
}
// string is done being processed, so use the stack to get the
// other characters in reverse order
while ( !stack.empty() ) {
output.push_back( stack.top() );
stack.pop();
}
std::cout << output;
working example: https://godbolt.org/z/eMazcGsMf
Note: wasn't sure from your description how to handle characters other than letters and numbers, so treated them the same as letters.
One way to do this is as follows:
Version 1
#include <iostream>
#include <string>
int main() {
std::string s = "abc123";
std::string output;
output.resize(s.size());
int i = output.length() - 1;
int j = 0;
for(char &c: s)
{
if(!std::isdigit(c))
{
output.at(i) = c;
--i;
}
else
{
output.at(j) = c;
++j;
}
}
std::cout<<output<<std::endl;
}
You can also use iterators in the above program to obtain the desired result as shown in version 2.
Version 2
#include <iostream>
#include <string>
int main() {
std::string s = "abfsc13423";
std::string output;
output.resize(s.size());
std::string::reverse_iterator iter = output.rbegin();
std::string::iterator begin = output.begin();
for(char &c: s)
{
if(!std::isdigit(c))
{
*iter = c;
++iter;
}
else
{
*begin = c;
++begin;
}
}
std::cout<<output<<std::endl;
}

extracting digits from input string c++

I'm trying to do parsing to some input string reactions read from file at formula :2W+B=8A+10Z, I'm not interested in characters i need only to split and extract the integer values to put them in a vector i.e vector associated with the reaction here is :[2 1 8 10]
i thought about many things: std::strtok(),isdigital(),find_first_of() but they all didn't work for integer values ... can any body help ??
here my try:
int main()
{
std::string input;
std::getline(std::cin, input);
std::stringstream stream(input);
while(1) {
int n;
stream >> n;
char * pch;
pch = strtok (input," ");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.");
}
}
}
This will do what you want in this particular case. However, i suggest that you look into regex to parse your equation better. You may want to consider all possible cases for your input. This includes \,-,* and other operators that you may want to add in your equation. Also, I'm assuming variables in your equation has only one character.
int main()
{
string input;
getline(std::cin, input);
stringstream stream(input);
char tmp[256];
const char *in = input.c_str();
char str[256];
strcpy(str,in);
int x;
tmp[0]='\0';
char c;
vector<int> vec;
//Scan for the digit
//if it is, store the rest of the string back to str
//if it isn't, store the part of the string before a digit to tmp
while (sscanf(str,"%d%s",&x,str) || sscanf(str,"%[^0123456789]%s",tmp,str) > 1)
{
//check if tmp has the form [variable name]+[a string]
//a string can include another variable name and an operator, = in this case
while(sscanf(tmp,"%c+%[^0123456789]",&c,tmp) > 1)
vec.push_back(1);
if (tmp[0]=='\0')
vec.push_back(x);
tmp[0]='\0';
}
//just in case there're more special cases
while(sscanf(str,"%c+%[^0123456789]",&c,str) > 1)
vec.push_back(1);
for(int i = 0; i < vec.size(); i++)
cout << vec[i] << endl;
}
Output:
2
1
8
10
See comments for explanation.
EDIT
Be careful when you have a special case 2W+B=8A+10Z+C+D. Notice the last C D should both have coefficients 1. This could happen in the middle of the equation too.
Here is another solution:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string equ;
vector<int> digits;
cout << "enter your equation: \n";
cin >> equ;
for (auto i : equ)
{
if (isdigit(i))
{
digits.push_back(stoi(string{i}));
}
}
for (auto& i : digits)
{
cout << i << endl;
}
system("pause");
return 0;
}
You could simply do something like this, for comments see code
#include <iostream>
#include <string>
#include <vector>
std::vector<int> Split(std::string str)
{
std::vector<int> result; // will contain the different ints
// set pointer to first character in the string
char const* pch = str.c_str();
std::string digit; // buffer to keep digits if more than one
int sign = 1; // each number has a sign -1 or 1
for (; *pch; ++pch)
{
if (std::isdigit(*pch)) // if a digit, put in temp buffer
{
digit += *pch;
}
else if (std::isalpha(*pch)) // if not a digit evaluate the ones we have
{
if (digit.empty()) // none so assume 1 before letter e.g. W+2B
{
result.push_back(1*sign);
}
else
{
result.push_back(stoi(digit)*sign);
digit = "";
}
}
else // determine sign of number
{
digit = "";
if (*pch == '+')
{
sign = 1;
}
else if (*pch == '-')
{
sign = -1;
}
}
}
return result;
}
int main()
{
using namespace std;
string expr{"-2W+B=-8A+10Z"};
auto digits = Split(expr);
for (auto& digit : digits)
{
cout << digit << endl;
}
return 0;
}

How to read string from stdin until meet blank lines

Consider a simple program. It must take string from stdin and save to variable.
It is not stated how many lines of input will be taken, but program must terminate if meet newline.
For example:
stdin:
abc
abs
aksn
sjja
\n
I tried but it doesn't work. Here is my code:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
// Constant
#define max 100000
struct chuoi
{
char word[10];
};
chuoi a[max];
void readStr()
{
int i=0;
while ( fgets(a[i].word, 10,stdin) != NULL)
{
if (a[i].word[0] == ' ') break;
a[i].word[strlen(a[i].word)-1] = '\0'; //replaced \n by \0
i++;
}
//length = i;
}
int main()
{
readStr();
return 0;
}
So, how to solve this problem?
One alternative here is to use std::getline to get each line. If the line is empty, or the input fails, then exit the loop.
void readStr()
{
std::string str;
while ( std::getline(std::cin, str) && str.length() )
{
// use the string...
}
}
Adding the std::getline and use of std::vector to your sample code, and keeping with the spirit of your original sample;
#include <string>
#include <iostream>
#include <vector>
const std::size_t Max = 100000;
struct chuoi
{
explicit chuoi(std::string const& str) : word(str)
{
}
std::string word;
};
void readStr(std::vector<chuoi>& a)
{
std::string str;
while ( std::getline(std::cin, str) && str.length() )
{
a.push_back(chuoi(str));
}
}
void writeStr(std::vector<chuoi> const& a)
{
for (auto i = a.begin(); i != a.end(); ++i) {
std::cout << i->word << std::endl;
}
}
int main()
{
std::vector<chuoi> a;
a.reserve(Max);
readStr(a);
writeStr(a);
return 0;
}
To solve you immediate problem, minimal changes in the code can be made as follows;
void readStr()
{
int i = 0;
while ( fgets(a[i].word, 10, stdin) != NULL)
{
a[i].word[strlen(a[i].word) - 1] = '\0'; // transform the end of line character to NULL
if (strlen(a[i].word) == 0) {
break;
}
i++;
}
}
If the standard input will always be used (stdin), the gets function can also be used;
while ( gets(a[i].word) != NULL)
{
if (strlen(a[i].word) == 0) {
break;
}
i++;
}
Notes;
fgets reads until the "enter" key on the stdin but includes the new line character
gets also reads until the return, but excludes the new line character
Both functions NULL terminate the input
Be careful of the form of gets it does not check for buffer overflow conditions
I would do something like this:
#include <string>
#include <iostream>
int main()
{
std::string line; // will contain each line of input
// Stop when line is empty or when terminal input has an error
while(std::getline(std::cin, line) && !line.empty())
{
// do stuff with line
}
}

Printing input string words in reverse order

Using if and while/do-while, my job is to print following user's inputs (string value) in reverse order.
For example:
input string value : "You are American"
output in reverse order : "American are You"
Is there any way to do this?
I have tried
string a;
cout << "enter a string: ";
getline(cin, a);
a = string ( a.rbegin(), a.rend() );
cout << a << endl;
return 0;
...but this would reverse the order of the words and spelling while spelling is not what I'm going for.
I also should be adding in if and while statements but do not have a clue how.
The algorithm is:
Reverse the whole string
Reverse the individual words
#include<iostream>
#include<algorithm>
using namespace std;
string reverseWords(string a)
{
reverse(a.begin(), a.end());
int s = 0;
int i = 0;
while(i < a.length())
{
if(a[i] == ' ')
{
reverse(a.begin() + s, a.begin() + i);
s = i + 1;
}
i++;
}
if(a[a.length() - 1] != ' ')
{
reverse(a.begin() + s, a.end());
}
return a;
}
Here is a C-based approach that will compile with a C++ compiler, which uses the stack to minimize creation of char * strings. With minimal work, this can be adapted to use C++ classes, as well as trivially replacing the various for loops with a do-while or while block.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_LENGTH 1000
#define MAX_WORD_LENGTH 80
void rev(char *str)
{
size_t str_length = strlen(str);
int str_idx;
char word_buffer[MAX_WORD_LENGTH] = {0};
int word_buffer_idx = 0;
for (str_idx = str_length - 1; str_idx >= 0; str_idx--)
word_buffer[word_buffer_idx++] = str[str_idx];
memcpy(str, word_buffer, word_buffer_idx);
str[word_buffer_idx] = '\0';
}
int main(int argc, char **argv)
{
char *line = NULL;
size_t line_length;
int line_idx;
char word_buffer[MAX_WORD_LENGTH] = {0};
int word_buffer_idx;
/* set up line buffer - we cast the result of malloc() because we're using C++ */
line = (char *) malloc (MAX_LINE_LENGTH + 1);
if (!line) {
fprintf(stderr, "ERROR: Could not allocate space for line buffer!\n");
return EXIT_FAILURE;
}
/* read in a line of characters from standard input */
getline(&line, &line_length, stdin);
/* replace newline with NUL character to correctly terminate 'line' */
for (line_idx = 0; line_idx < (int) line_length; line_idx++) {
if (line[line_idx] == '\n') {
line[line_idx] = '\0';
line_length = line_idx;
break;
}
}
/* put the reverse of a word into a buffer, else print the reverse of the word buffer if we encounter a space */
for (line_idx = line_length - 1, word_buffer_idx = 0; line_idx >= -1; line_idx--) {
if (line_idx == -1)
word_buffer[word_buffer_idx] = '\0', rev(word_buffer), fprintf(stdout, "%s\n", word_buffer);
else if (line[line_idx] == ' ')
word_buffer[word_buffer_idx] = '\0', rev(word_buffer), fprintf(stdout, "%s ", word_buffer), word_buffer_idx = 0;
else
word_buffer[word_buffer_idx++] = line[line_idx];
}
/* cleanup memory, to avoid leaks */
free(line);
return EXIT_SUCCESS;
}
To compile with a C++ compiler, and then use:
$ g++ -Wall test.c -o test
$ ./test
foo bar baz
baz bar foo
This example unpacks the input string one word at a time,
and builds an output string by concatenating in reverse order.
`
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
string inp_str("I am British");
string out_str("");
string word_str;
istringstream iss( inp_str );
while (iss >> word_str) {
out_str = word_str + " " + out_str;
} // while (my_iss >> my_word)
cout << out_str << endl;
return 0;
} // main
`
This uses exactly one each of if and while.
#include <string>
#include <iostream>
#include <sstream>
void backwards(std::istream& in, std::ostream& out)
{
std::string word;
if (in >> word) // Read the frontmost word
{
backwards(in, out); // Output the rest of the input backwards...
out << word << " "; // ... and output the frontmost word at the back
}
}
int main()
{
std::string line;
while (getline(std::cin, line))
{
std::istringstream input(line);
backwards(input, std::cout);
std::cout << std::endl;
}
}
You might try this solution in getting a vector of string's using the ' ' (single space) character as a delimiter.
The next step would be to iterate over this vector backwards to generate the reverse string.
Here's what it might look like (split is the string splitting function from that post):
Edit 2: If you don't like vectors for whatever reason, you can use arrays (note that pointers can act as arrays). This example allocates a fixed size array on the heap, you may want to change this to say, double the size when the current word amount has reached a certain value.
Solution using an array instead of a vector:
#include <iostream>
#include <string>
using namespace std;
int getWords(string input, string ** output)
{
*output = new string[256]; // Assumes there will be a max of 256 words (can make this more dynamic if you want)
string currentWord;
int currentWordIndex = 0;
for(int i = 0; i <= input.length(); i++)
{
if(i == input.length() || input[i] == ' ') // We've found a space, so we've reached a new word
{
if(currentWord.length() > 0)
{
(*output)[currentWordIndex] = currentWord;
currentWordIndex++;
}
currentWord.clear();
}
else
{
currentWord.push_back(input[i]); // Add this character to the current word
}
}
return currentWordIndex; // returns the number of words
}
int main ()
{
std::string original, reverse;
std::getline(std::cin, original); // Get the input string
string * arrWords;
int size = getWords(original, &arrWords); // pass in the address of the arrWords array
int index = size - 1;
while(index >= 0)
{
reverse.append(arrWords[index]);
reverse.append(" ");
index--;
}
std::cout << reverse << std::endl;
return 0;
}
Edit: Added includes, main function, while loop format
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
// From the post
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
return split(s, delim, elems);
}
int main ()
{
std::string original, reverse;
std::cout << "Input a string: " << std::endl;
std::getline(std::cin, original); // Get the input string
std::vector<std::string> words = split(original, ' ');
std::vector<std::string>::reverse_iterator rit = words.rbegin();
while(rit != words.rend())
{
reverse.append(*rit);
reverse.append(" "); // add a space
rit++;
}
std::cout << reverse << std::endl;
return 0;
}
This code here uses string libraries to detect the blanks in the input stream and rewrite the output sentence accordingly
The algorithm is
1. Get the input stream using getline function to capture the spacecs. Initialize pos1 to zero.
2. Look for the first space in the input stream
3. If no space is found, the input stream is the output
4. Else, get the position of the first blank after pos1, i.e. pos2.
5. Save the sub-string bewteen pos1 and pos2 at the beginning of the output sentence; newSentence.
6. Pos1 is now at the first char after the blank.
7. Repeat 4, 5 and 6 untill no spaces left.
8. Add the last sub-string to at the beginning of the newSentence. –
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string sentence;
string newSentence;
string::size_type pos1;
string::size_type pos2;
string::size_type len;
cout << "This sentence rewrites a sentence backward word by word\n"
"Hello world => world Hello"<<endl;
getline(cin, sentence);
pos1 = 0;
len = sentence.length();
pos2 = sentence.find(' ',pos1);
while (pos2 != string::npos)
{
newSentence = sentence.substr(pos1, pos2-pos1+1) + newSentence;
pos1 = pos2 + 1;
pos2 = sentence.find(' ',pos1);
}
newSentence = sentence.substr(pos1, len-pos1+1) + " " + newSentence;
cout << endl << newSentence <<endl;
return 0;
}