I have the string:
string str = "1234567890";
//Magic code
cout<<str<<endl;
Which i want to output: 12 34 56 78 90
I assume std has some neat feature/function to help solve this. How do I that in the most convenient way?
The std::string::insert with a for loop could help you to insert spaces into an std::string very easely:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string str = "1234567890";
for(auto it = str.begin(); it != str.end(); it += min<int>(str.end() - it, 2))
it = (it != str.begin() ? str.insert(it, ' ') + 1 : it);
cout << str << endl;
}
The std::string::insert returns an iterator pointing to the character inserted, therefore it has to be incremented to step over the inserted character.
Because std::string has a random-access iterator it can be incremented or decremented more than by one. The min<int>(str.end() - it, 2) ensures that the next step won't go out of bounds.
A more general approach. Define a function that inserts a given character char_to_insert into a given string s every interval characters, excluding beginning and end of string:
std::string insert_char(const std::string& s, char char_to_insert, size_t interval)
{
// corner cases
if (!interval || !s.length()) return s;
// compute number of characters to insert
auto number_of_chars_to_insert = (s.length()-1)/interval;
// compute total length
auto output_length = s.length() + number_of_chars_to_insert;
// pre-allocate output string with all characters equal to char_to_insert
std::string retval(output_length, char_to_insert);
// cycle input string, keeping track of position in input and output strings
size_t pos = 0, pos_in_input = 0;
for (const auto& c : s)
{
// copy from input to output
retval[pos++] = c;
// advance in output every interval chars
if ((++pos_in_input) % interval == 0)
++pos;
}
return retval;
}
Then:
int main()
{
std::string s = "1234567890";
for (size_t i = 1; i != 5; ++i)
std::cout << insert_char(s, ' ', i) << std::endl;
return 0;
}
The output:
1 2 3 4 5 6 7 8 9 0
12 34 56 78 90
123 456 789 0
1234 5678 90
There is no built-in to do what you want.
Instead, the most convenient solution is probably to iterate through the string and output pairs of digits as you go:
string str = "1234567890";
for (auto it = str.begin(); it != str.end(); ++it){
std::cout << *(it);
if (++it != str.end()){
std::cout << *it << " ";
}
}
std::cout << std::endl;
Or non-iterator version:
string str = "1234567890";
for (idx = 0; idx < str.length(); idx += 2){
std::cout << str.substr(idx, 2) << " ";
}
std::cout << std::endl;
Both of these examples will have a trailing space on the line, but I've left it in to keep the examples simpler.
Related
I was trying out a solution to a question, when I came across this code snippet written in C++:
string s;
cin >> s;
vector<int> r;
for (string t: {"twone", "one", "two"}) {
for (size_t pos = 0; (pos = s.find(t, pos)) != string::npos;) {
s[pos + t.length() / 2] = '?';
r.push_back(pos + t.length() / 2);
}
}
cout << r.size() << endl;
for (auto rr: r)
cout << rr + 1 << " ";
cout << endl;
I am new to the language and was unable to understand what is happening in the second (nested) for loop and the 3rd for loop. Can someone help me to understand?
The first and the third loops are range-based for loops.
The first loop iterates over a container of strings. So t takes successively the value "twone", "one", and "two"
The second loop searches for all the occurences of t in the string s (each search starts from position pos of the previous occurence found). As long as a element is found it does:
s[pos + t.length() / 2] = '?';
r.push_back(pos + t.length() / 2);
The push_back() stores the position of the middle of each occurence found in a vector of integers.
The third loop iterates over this vector of stored positions and prints the elements (the positions count starts at 0, the +1 shifts the printed positions as if the count would start with 1).
One of the main ways to try and understand complex code is to try and simplify it. It also helps to know what the involved functions do, so a reference to std::string::find is helpful to read.
First of all, lets skip the body and concentrate only on the loop itself:
for (size_t pos = 0; (pos = s.find(t, pos)) != string::npos;) {
}
All for loops could be seen as a while loop, and while loops could be somewhat easier to understand and follow, so we convert it to such a while loop:
size_t pos = 0;
while (pos = s.find(t, pos)) != string::npos)
{
}
This might not help so much as it's the condition that is most likely the hard part to understand, so then we simplify that as well:
size_t pos = 0;
pos = s.find(t, pos);
while (pos != string::npos)
{
pos = s.find(t, pos);
}
The initialization of pos could then be further simplified:
size_t pos = s.find(t);
while (pos != string::npos)
{
pos = s.find(t, pos);
}
Now the loop itself is a simple as it could be, and looking at it we see that basically attempt to find the sub-string t inside the string s. The loop continues as long as the sub-string t is found inside s.
Now that we deconstructed the loop itself, let's take a look at the loop-body, and what it does:
s[pos + t.length() / 2] = '?';
r.push_back(pos + t.length() / 2);
First of all lets pull out the common sub-expression into a temporary variable:
auto new_pos = pos + t.length() / 2;
s[new_pos] = '?';
r.push_back(new_pos);
The first statement
s[new_pos] = '?';
replaces the middle character of the sub-string t inside s with the character '?'.
The second statement
r.push_back(new_pos);
pushes the position of the '?' into the vector r.
Now lastly we put the inner loop (explained above) into the context of the outer loop:
for (string t: {"twone", "one", "two"})
This is a range-based for loop which loops over all elements in the container on the right-hand side of the :. That is, the loop will iterate three times, with t being equal to "twone", "one" and "two" in that order.
So loops will search for "twone", "one" and "two" inside the string s, replace the middle character of the sub-strings ("twone", "one" and "two") inside s with a single '?' character, and push the position of that '?' character into the vector r.
For example if the input in s is "someone with the number two" then the result will the the string "someo?e with the number t?o", and the vector r should contain the values 5 and 25 (which will be printed as 6 and 26 because of the + 1).
Here's an example shoing exactly that.
Just run the code inserting in it an output pf intermediate results.
Here is a demonstrative program.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string s;
std::cin >> s;
std::vector<int> r;
for ( const std::string &t : { "twone", "one", "two" } )
{
for ( std::string::size_type pos = 0; (pos = s.find( t, pos ) ) != std::string::npos; )
{
s[pos + t.length() / 2] = '?';
std::cout << pos << ": " << s << '\n';
r.push_back( pos + t.length() / 2 );
}
}
std::cout << r.size() << '\n';
for ( const auto &rr: r ) std::cout << rr + 1 << " ";
std::cout << '\n';
}
Let's assume that the user entered string onetwoone. So the inner loop searches in the entered string all occurrences of words "twone", "one", "two" sequentially.
For the given string the word "twone" is not found.
The word "one" is found at position 0. This statement
s[pos + t.length() / 2] = '?';
the middle character of the found word in the entered string by the sign '?'.
Thus this added statement
std::cout << pos << ": " << s << '\n';
outputs
0: o?etwoone
The position of the sign '?' (the number 1) is stored in the vector.
Then within the loop the word "one" is found second time. And again the middle character of the found word is substituted for '?'. So this statement
std::cout << pos << ": " << s << '\n';
outputs
6: o?etwoo?e
The position of the sign '?' (the number 7) is stored in the vector.
So at this moment we have the following output
0: o?etwoone
6: o?etwoo?e
The word "one" is not found any more.
The word "two" is occurred only once in the given string. SO the output is
3: o?et?oo?e
The position of '?' equal to 4 is stored in the vector.
Now at this moment we have the following output
0: o?etwoone
6: o?etwoo?e
3: o?et?oo?e
produced by the inner loop.
So as a result three occurrences of the words are found in the entered string.
Thus these statements
std::cout << r.size() << '\n';
for ( const auto &rr: r ) std::cout << rr + 1 << " ";
output
3
2 8 5
The last values correspond to expressions rr + 1 that is to stored positions of the sign '?' plus 1.
I am writing a code where I take user user text input, convert it to binary, store each binary character in an element in an array and then print A or T for 0 and G or C for 1 at random. But the ATGC seem to not follow this rule and they come at random for every digit; 0 and 1. So If the binary is 0010101 I need output as ATGACTG. Also when I store the binary in an int variable, the zero in front of it vanishes. Is there a way to keep it?
#include <iostream>
#include <cstdlib>
#include <bitset>
#include <string>
#include <ctime>
int main()
{
using namespace std;
int p, i=0, a[100000];
int s;
string myString;
int binary;
cout << "Type your text: ";
std::getline (std::cin,myString);
for (std::size_t k=0; k < myString.size(); ++k)
{
std::bitset<8> y(myString[k]);
std::string dna = y.to_string();
binary = atoi(dna.c_str());
cout << binary;
while (binary != 0)
{
a[i] = binary % 10;
binary = binary / 10;
i++;
}
}
std::cout << std::endl;
srand(time(0));
for (int j = (i-1); j>-1; j--)
{
if (a[j] == 0)
{
p = rand() %2;
if (p==0)
cout<< "A";
else
cout<< "T";
}
if (a[j] == 1)
{
s = rand() %2;
if (s == 0)
cout<< "G";
else
cout<< "C";
}
else
{
cout << "";
}
}
}
I don't know why exactly you wrote so much wrong code, but I've managed to extract (and change) the code that actually does the job.
#include <iostream>
#include <string>
#include <bitset>
#include <ctime>
int main()
{
int i = 0, a[8];
std::string myString;
std::cout << "Type your text: " << std::endl;
std::getline(std::cin, myString);
for(auto x : std::bitset<8>(myString).to_string())
a[i++] = x == '1';
std::cout << std::endl;
srand(time(0));
for(int j = 0; j < i; ++j)
if(a[j] == 0)
std::cout << (rand() % 2 ? "T" : "A");
else if(a[j] == 1)
std::cout << (rand() % 2 ? "C" : "G");
std::cout << std::endl;
}
And here's neater version of main:
int main()
{
std::vector<int> a; // using std::vector
std::bitset<8> bs;
std::cout << "Type your text: " << std::endl;
std::cin >> bs; // std::bitset can be read from stream via operator>>
for(auto x : bs.to_string())
a.push_back(x == '1');
std::cout << std::endl;
srand(time(0));
for(auto x : a)
if(x == 0)
std::cout << (rand() % 2 ? "T" : "A");
else if(x == 1)
std::cout << (rand() % 2 ? "C" : "G");
std::cout << std::endl;
}
Just ask if you want an explanation on some specific part.
I told you not to convert the string to an integer. You didn't listen. This is why leading 0 vanishes.
Your output seams to be completely random because you reverse the order of characters in the sequence when reading the information from a.
Here is how I'd solve your problem: run online
#include <iostream>
#include <string>
#include <bitset>
#include <ctime>
#include <cstdlib>
int main()
{
std::cout << "Type your text: " << std::endl;
std::string in_str;
std::getline(std::cin, in_str);
std::string binary_str;
for(int i = 0; i < in_str.size(); ++i)
{
char c = in_str.at(i);
binary_str.append(std::bitset<8>(c).to_string());
}
std::cout << binary_str << std::endl;
srand(time(0));
for(int i = 0; i < binary_str.size(); ++i)
{
char c = binary_str.at(i);
if(c == '0')
std::cout << (rand() % 2 ? "T" : "A");
else
std::cout << (rand() % 2 ? "C" : "G");
}
std::cout << std::endl;
}
If you have any questions, ask me in the comments.
Edit: the OP asked me to explain all mistakes in his program.
Where did all those zeros gone?
To answer this question I'll have to explain all things your program does line-by-line.
Here you convert a symbol to a bitset:
std::bitset<8> y(myString[k])
For example: if k is 'a', then the y would be 01100001.
Here you convert the bitset to a string:
std::string dna = y.to_string();
In our example the dna would be "01100001".
Here you convert the string to an integer:
binary = atoi(dna.c_str());
A very simplified version of what atoi does:
binary = 0;
for(int i = 0; i < dna.size(); ++i)
binary = binary * 10 + (dna.at(i) - '0')
In our example the binary would be 1100001.
Note: that's NOT where you loose zeros. At this point you are still able to extract them because you know that you need to extract 8 digits. So you can append leading zeros to up it's length to 8.
The next line is where you actually loose zeros the first time because cout doesn't know that you want to print 8 digits.
cout << binary;
In our example it would print 1100001.
And here you loose zeros again because you stop extracting digits as soon as binary == 0 even if you extracted less than 8 digits. Also note that you are actually reversing what the function atoi just did with the only difference that you don't get your leading zeros back and the reverse order of bits (see the next paragraph):
while (binary != 0)
{
a[i] = binary % 10;
binary = binary / 10;
i++;
}
Why the output is "random"?
Here you are iterating through myString in the standard order
for (std::size_t k=0; k < myString.size(); ++k)
e.g. if myString is "abc" than
in the first iteration myString[k] would be 'a'
in the second iteration myString[k] would be 'b'
in the third iteration myString[k] would be 'c':
But in this loop you extract digits in reverse order:
while (binary != 0)
{
a[i] = binary % 10;
binary = binary / 10;
i++;
}
eg if binary is 1100001
in the 1st iteration you extract 1 and binary becomes 110000
in the 2nd iteration you extract 0 and binary becomes 11000
in the 3rd iteration you extract 0 and binary becomes 1100
in the 4th iteration you extract 0 and binary becomes 110
in the 5th iteration you extract 0 and binary becomes 11
in the 6th iteration you extract 1 and binary becomes 1
in the 7th iteration you extract 1 and binary becomes 0
Now you end up with an array where bits inside a character code are reversed, but different characters are stored in the array in the normal order.
e.g. If the input string was "abc", then a would become:
1,0,0,0,0,1,1, 0,1,0,0,0,1,1, 1,1,0,0,0,1,1
reversed 'a' reversed 'b' reversed 'c'
If you iterate through a in normal order, the order of bits inside character codes would be reversed. If you iterate through a in reverse order, you get the reversed order of characters.
As a rule of thumb: don't program by guessing, program by thinking.
Further reading
The Zen of Python. Most of this aphorisms are applicable to every programming language with the exception of Brainfuck
Raw C arrays are evil
I am currently trying to read information from an .txt file and essentially store this appropriately. Data from the input file would look something like this
10 10 10 10 10 10 20 20 20 15 15 15 15 15 15 15 20 30 20 15 15 10 10 10
765DEF 01:01:05:59 enter 17
ABC123 01:01:06:01 enter 17
765DEF 01:01:07:00 exit 95
ABC123 01:01:08:03 exit 95
My question is that, assuming I have read "01:01:05:59" into a string, how do I parse this to store the numbers in an int variable. In addition, all I really need is the third pair of numbers in that string(from the left) and I was also wondering how to skip the first two and last pair of numbers in that string. I have read on delimiters but I'm a little confused on how to use them. The code I have so far is shown below and is basically that information to strings.
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main()
{
int arr[25];
ifstream File;
File.open("input.txt");
for (int a = 0; a < 25; a++)
{
File >> arr[a];
}
for (int i = 0; i < 25; i++)
{
cout << arr[i] << " ";
}
cout << endl;
string license, datetime;
File >> license >> datetime; // reads in license plate and datetime information into two separte strings
cout << license << endl << datetime;
system("pause");
}
Background:
If we know the start and end indices (or the length) of the sub-string we need, then we can read it by using std::string::substr.
Its usage is as follows:
#include <string>
...
std::string foo = "0123456789stack:overflow";
// start index = 4, length = 2
std::string subStr1 = foo.substr(4,2); // result = "45"
// start index = 3, end index = 5 => length = 5 - 3 + 1 = 3
std::string subStr2 = foo.substr(3,3); // result = "345"
// The first parameter is the start index whereas the second one is
// the length of the wanted sub-string.
// If only the start index is known:
std::string subStr2 = foo.substr(9); // result = "9stack:overflow"
// In that case we get the rest of the string starting from the start index 9.
For more information on that please refer to: http://www.cplusplus.com/reference/string/string/substr/
Suggested solution to the OP:
Since you said "all I really need is the third pair of numbers" then you need two characters starting from index 6:
std::string a = "01:01:05:59";
std::string sub = a.substr(6, 2); // will give you "05"
then convert them using:
int number = std::stoi(sub);
These steps can be shortened to:
int number = std::stoi( a.substr(6, 2) );
Further references:
First part: http://en.cppreference.com/w/cpp/string/basic_string/substr
Second part: How to parse a string to an int in C++?
PS: if you want to use character array instead of std::string then you just can get the characters with their corresponding indices. For example: i = 6 and i = 7 in your specific case. Then, get yourArray[6]=0 and yourArray[7]=5. Then perform integer conversion on them.
Could you do:
int num = std::stoi(string.substr(6, 2);
assuming I have read "01:01:05:59" into a string
One easy way is using streams:
#include <iostream>
#include <sstream>
int main()
{
int n[4];
std::istringstream iss("02:30:41:28");
if (iss >> n[0] && iss.get() == ':' &&
iss >> n[1] && iss.get() == ':' &&
iss >> n[2] && iss.get() == ':' &&
iss >> n[3] >> std::ws && iss.eof())
std::cout << n[0] << ' ' << n[1] << ' ' << n[2] << ' ' << n[3] << '\n';
else
std::cerr << "parsing error\n";
}
On ideone.com
How do you read lines from a vector and compare their lengths? I have pushed strings inside a vector and now would like to find the longest line and use that as my output. I have this as my code all the way up to comparing the strings:
ifstream code_File ("example.txt");
size_t find_Stop1, find_Stop2, find_Stop3, find_Start;
string line;
vector<string> code_Assign, code_Stop;
if (code_File.is_open()) {
while ( getline(code_File,line)) {
find_Start = line.find("AUG"); // Finding all posssible start codes
if (find_Start != string::npos) {
line = line.substr(find_Start);
code_Assign.push_back(line); //adding line to Code_Assign
find_Stop2 = line.find("UGA"); // Try and find stop code.
if (find_Stop2 != string::npos) {
line = line.substr(line.find("AUG"), find_Stop2);
code_Stop.push_back(line); // Adding it to code_Stop vector
}
find_Stop1 = line.find("UAA"); // finding all possible stop codes.
if (find_Stop1 != string::npos) {
line = line.substr(line.find("AUG"), find_Stop1); // Assign string code_1 from start code to UGA
code_Stop.push_back(line); //Adding to code_Stop vector
}
find_Stop3 = line.find("UAG"); // finding all possible stop codes.
if (find_Stop3 != string::npos) {
line = line.substr(line.find("AUG"), find_Stop3);
code_Stop.push_back(line); //Adding to code_Stop vector
}
}
}
cout << '\n' << "Codes to use: " << endl;
for (size_t i = 0; i < code_Assign.size(); i++)
cout << code_Assign[i] << endl;
cout << '\n' << "Possible Reading Frames: " << endl;
for (size_t i = 0; i < code_Stop.size(); i++)
cout << code_Stop[i] << endl;
cout << endl;
std::vector<std::string>::iterator longest = std::max_element(code_Stop.begin(), code_Stop.end, compare_length);
std::string longest_line = *longest; // retrieve return value
code_File.close();
}
else cout << "Cannot open File.";
to try and clarify my current output is this all in the code_Stop vector:
Possible Reading Frames:
AUG GGC CUC GAG ACC CGG GUU UAA AGU AGG
AUG GGC CUC GAG ACC CGG GUU
AUG AAA UUU GGG CCC AGA GCU CCG GGU AGC GCG UUA CAU
and I would just like to get the longest line.
Note, I am just learning about vectors, so please be kind...I have been getting a lot of help from this board and really much appreciated.
Ed. I changed the code to show where I have put it and it is giving me "Program received signal: 'EXC_BAD_ACCESS'". What have I done?
This should work:
#include <string>
#include <vector>
#include <algorithm>
bool compare_length(std::string const& lhs, std::string const& rhs) {
return lhs.size() < rhs.size();
}
int main() {
std::vector<std::string> lines; // fill with data
std::vector<std::string>::iterator longest = std::max_element(
lines.begin(), lines.end(),
compare_length);
std::string longest_line = *longest; // retrieve return value
}
compare_length is a function that compares the length of two given strings. It returns true if the first string is shorter than the second one, and false otherwise.
std::max_element is a standard-algorithm that find the largest element in a sequence using the specified comparison-function. lines.begin() and lines.end() return iterators to the beginning and the end of the sequence lines, thus specifying the range the algorithm should scan.
I want to make a program that will read some number in string format and output it like this: if the number is 12345 it should then output 12 23 34 45 . I tried using the substr() function from the c++ string library, but it gives me strange results - it outputs 1 23 345 45 instead of the expected result. Why ?
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main(void)
{
string a;
cin >> a;
string b;
int c;
for(int i=0;i<a.size()-1;++i)
{
b = a.substr(i,i+1);
c = atoi(b.c_str());
cout << c << " ";
}
cout << endl;
return 0;
}
If I am correct, the second parameter of substr() should be the length of the substring. How about
b = a.substr(i,2);
?
As shown here, the second argument to substr is the length, not the ending position:
string substr ( size_t pos = 0, size_t n = npos ) const;
Generate substring
Returns a string object with its contents initialized to a substring of the current object. This substring is the character sequence that starts at character position pos and has a length of n characters.
Your line b = a.substr(i,i+1); will generate, for values of i:
substr(0,1) = 1
substr(1,2) = 23
substr(2,3) = 345
substr(3,4) = 45 (since your string stops there).
What you need is b = a.substr(i,2);
You should also be aware that your output will look funny for a number like 12045. You'll get 12 20 4 45 due to the fact that you're using atoi() on the string section and outputting that integer. You might want to try just outputing the string itself which will be two characters long:
b = a.substr(i,2);
cout << b << " ";
In fact, the entire thing could be more simply written as:
#include <iostream>
#include <string>
using namespace std;
int main(void) {
string a;
cin >> a;
for (int i = 0; i < a.size() - 1; i++)
cout << a.substr(i,2) << " ";
cout << endl;
return 0;
}
Another interesting variant question can be:
How would you make "12345" as "12 23 34 45" without using another string?
Will following do?
for(int i=0; i < a.size()-1; ++i)
{
//b = a.substr(i, 2);
c = atoi((a.substr(i, 2)).c_str());
cout << c << " ";
}
substr(i,j) means that you start from the index i (assuming the first index to be 0) and take next j chars.
It does not mean going up to the index j.
You can get the above output using following code in c
#include<stdio.h>
#include<conio.h>
#include<string.h>
int main()
{
char *str;
clrscr();
printf("\n Enter the string");
gets(str);
for(int i=0;i<strlen(str)-1;i++)
{
for(int j=i;j<=i+1;j++)
printf("%c",str[j]);
printf("\t");
}
getch();
return 0;
}
Possible solution without using substr()
#include<iostream>
#include<string>
using namespace std;
int main() {
string c="12345";
int p=0;
for(int i=0;i<c.length();i++) {
cout<<c[i];
p++;
if (p % 2 == 0 && i != c.length()-1) {
cout<<" "<<c[i];
p++;
}
}
}
Possible solution with string_view
void do_it_with_string_view( void )
{
std::string a { "12345" };
for ( std::string_view v { a }; v.size() - 1; v.remove_prefix( 1 ) )
std::cout << v.substr( 0, 2 ) << " ";
std::cout << std::endl;
}
The string constructor can be used to get a copy of a substring.
string(const string& str, size_t pos, size_t n)
For example...
b = string(a, i, 2); // substring of a from position i, including 2 characters
This differs from substr in that the length n cannot be omitted. I offer this only as an alternative, not as an improvement.