Initial Check to see if a Substring is within range - c++

I am in the beginnings of learning C++ and I am wondering if there is a way to assert that a substring can be created from a String, given a range. My String will vary in size each iteration. I am trying to create six substrings from that original String. With this variation in size, I am sometimes trying to access indexes of the String that do not exist for that particular iteration.
For example, if my String in iteration 1 is 11 characters
My first substring is from 3 characters - valid
My second substring is the next 3 characters - valid
My third substring is the next 5 characters - valid
My fourth substring is the next 4 characters - not valid - crashes program
My fifth substring - not valid, out of range
My sixth substring - not valid, out of range
I am wondering if there is a small check I can do to assert the length is valid. It's worth noting, I suppose, that I have not set any default values to these substrings. They are declared as:
string subS1
string subS2
string subS3
...
...
string subS6
Would setting all 6 substrings to null upon declaration alleviate this issue and for any valid substring, the value will just be overwritten?
Thanks in advance
subS1 = str.substr(0, 3); // Could be valid range
subS2 = str.substr(3, 3); // Could be valid range
subS3 = str.substr(6, 5); // Could be valid range
subS4 = str.substr(11, 4); // Could be valid range
subS5 = str.substr(15, 4); // Could be valid range
subS6 = str.substr(19); // from the nineteenth character to the end

Algorithm--->
step 1: Get the length of string in current iteration in variable size.
step 2: Write this code in itertaion.
int i=0;
i= str.substr(start,end).length();
if( i>size) then,
std::cout<<"index exceeded";

Either check the size of str before extracting the string, or rely on std::string::substr's len parameter:
Number of characters to include in the substring (if the string is
shorter, as many characters as possible are used). A value of
string::npos indicates all characters until the end of the string.
Example:
#include <iostream>
#include <string>
int main ()
{
std::string str="Alexander the Great";
std::string str2 = str.substr (16, 25);
std::cout << str2 << '\n'; // eat
return 0;
}
It won't crash, it will just use as many characters as possible.
This however:
std::string str2 = str.substr (20, 25);
should crash, so do it like this in this case:
std::string str2 = ""; // initialise to empty string, that is the NULL you are saying I guess
if(str.size() > 20)
str2 = str.substr (20, 25);
// 'str2' will be an empty string

Related

How std::find_last_of actually works?

string s = "I Like C++ Tutorial";
cout << s.find_last_of("Like");
I know that find_last_of returns the last character that matches, however, it returns 16, which is the position of the letter i in Tutorial, But I'm confused because I'm searching for the last position of Like not i, I tried to remove i from the string. It returns 5 as I expected. But the question is why did it return 16?
find_last_of finds the last character equal to one of characters in the given character sequence.
The character sequence is "Like". The last L is at position 3, the last i is at position 16, the last k is at position 4 and the the last e is at position 5. So it returned the 16, the greatest of these values.
If the character sequence was "like" instead of "Like", it would have returned 18 because the last l is at position 18.
In case no letter in the character sequence that matches any letter in the string, npos is returned.
std::find_last_of
Finds the last character equal to one of characters in str
this means when searching the string "I Like C++ Tutorial" for the string "Like" the last character that apears in both strings is "i" wich is at position 16.
when searching for a complete string use std::find
std::string s("I Like C++ Tutorial");
std::cout << s.find("Like"); // prints 2
if you want to find the last occurence of the string use std::rfind
std::string s("I Like C++ Tutorial Like");
std::cout << s.rfind("Like"); // prints 20
to get the position of the last character in the last match you just have to add the length of the string:
std::string s("I Like C++ Tutorial Like");
std::string s2("Like");
std::cout << s.rfind(s2) + s2.length(); // prints 24

Iterations of while loop returns strange values

I have two questions:
Assume the characters entered by the user in input are all contained in alphabet:
If my input starts with "A", the first character in my output is "A", but if I start with any other character in alphabet, the output is the original character shifted to the right by 3. If my input starts with "A", why does my output also start at "A" and not at "D"?
If my input is a string that has spaces (e.g. "Stack Overflow"), why is the first word the only component of my output? (How is the computer interpreting this?) I understand C++ considers new lines, spaces, and tabs to be whitespace, but I thought if the space was in a string, it would be treated as a character. How can I modify my code so the space and the rest of my input is included (preferably shifted) in my output?
using namespace std;
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ##$%^&*()"; //a 62 character string
string input, output;
int shift = 3, index = 0;
cin >> input;
while(index < input.length()){
if(alphabet.find(input[index]) != NULL){
output += alphabet[(alphabet.find(input[index]) + shift) % 62];
}
index++;
}
If my input starts with "A", the first character in my output is "A", but if I start with any other character in alphabet, the output is the original character shifted to the right by 3. If my input starts with "A", why does my output also start at "A" and not at "D"?
It doesn't. It skips the "A" and does not add it to the output at all!
This is because std::string::find() DOES NOT return a pointer, it returns an index. If it does not find a match, it returns std::string::npos (-1). Comparing NULL to an index treats the NULL as index 0. So, when find() does find "A", it returns 0, which you then compare as equal to NULL (0) and thus skip adding "D" to the output. All of the other input characters make find() return indexes other than 0, so they don't compare equal to NULL and so you shift all of them (including ones that cause find() to return npos, you shift all of those to index 2).
If my input is a string that has spaces (e.g. "Stack Overflow"), why is the first word the only component of my output? (How is the computer interpreting this?) I understand C++ considers new lines, spaces, and tabs to be whitespace, but I thought if the space was in a string, it would be treated as a character. How can I modify my code so the space and the rest of my input is included (preferably shifted) in my output?
operator>> reads whitespace-delimited words. It first skips leading whitespace (unless std::noskipws is used), and then it reads until it encounters whitespace. To read a string with spaces in it, use std::getline() instead.
With that said, try this instead:
using namespace std;
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ##$%^&*()"; //a 62 character string
string input, output;
const int shift = 3;
getline(cin, input);
for (string::size_type index = 0; index < input.length(); ++index) {
string::size_type found_index = alphabet.find(input[index]);
if (found_index != string::npos) {
output += alphabet[(found_index + shift) % alphabet.size()];
}
}
/*
Or, using C++11 or later:
for (char c : input) {
auto found_index = alphabet.find(c);
... (same as above) ...
}
*/
Also, how does one format variables when asking questions on StackOverflow so that they're in little code blocks within writing a question? I see that on other people's posts, but I don't know how to do it, and it makes things far more readable.
Blocks of code can be indented by 4 spaces. The toolbar on StackOverflow's editor has a button for formatting code blocks. Just select the code and press the button.
Code inline of other text can be wrapped in `` quotes.
Click on the ? button on the right side of the editor's toolbar to see the supported formatting markup.

How to use std::stod properly

I am working on writing a simple linear line calculator. For example, a user can enter two equations (strings) such as y=5x+3 and y=-3x+6. The most basic feature of this calculator is that it will return the intersection point of these two lines.
The obstacle I can't seem to figure out is how to parse the string into two pieces of data: the slope, and the y-intercept. This is a simple calculator, so the format of both lines will be y=mx+b, however, both the slope and/or y-intercept may be non-integer numbers (i.e. floats).
I came across a function in the string library called stod, which converts a number in a string to a numerical value (am I understanding this correctly?).
http://www.cplusplus.com/reference/string/stod/
My question is, will this function do the job? If so, how exactly do I use the "idx" parameter? I don't quite understand it.
If this isn't going to work, how can I parse this user-entered data?
both equations are strings (y=mx+b)
m and b have private variables dedicated in storing the decimal value (i.e. double m_ and double b_ are private member variables)
This is how the idx parameter works:
#include <string>
#include <iostream>
int main(void)
{
std::string data = "y=5.9568x+3.14"; //say you have a string like this..
double y, x, m, b;
y = 0;
x = 0;
std::size_t offset = 0; //offset will be set to the length of characters of the "value" - 1.
m = std::stod(&data[2], &offset); //So we want to get the value "5.9568
b = std::stod(&data[offset + 3]); //When we reach this line, offset has a value of 6
std::cout<<b;
return 0;
}
So now you're asking why does it have a value of 6? Well because:
5.9568 is exactly: 6 characters in length. Thus on the next line when we do
b = std::stod(&data[offset + 3]);
we are actually feeding it a pointer to address of x + 3.. and that turns out to be right at the beginning of the 3.14.
In other words it's equivalent to:
std::stod(&data[9]);
So that idx parameter is actually the index/length of the double in characters within the string. If the string is:
str = "3.14159"
Then std::stod(str, &idx) will make idx equal to: 6.
if the string is:
str = "y = 1024.789" then std::stod(&str[4], &idx) will make idx equal to: 8 STARTING FROM &str[4]..
Here's something simple with no error checking to get you started:
Assuming your input string is always exactly of the form y=mx+b and you wish to parse it to obtain the numerical values of m and b you can first tokenize the string with y, =, x, and as delimiters.
An example of a tokenizing function can be found here. Here it is reproduced:
void tokenize(const std::string &str,
std::vector<std::string> &tokens,
const std::string &delimiters)
{
// Skip delimiters at beginning.
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
// Find first "non-delimiter".
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
while (std::string::npos != pos || std::string::npos != lastPos)
{
// Found a token, add it to the vector.
tokens.push_back(str.substr(lastPos, pos - lastPos));
// Skip delimiters. Note the "not_of"
lastPos = str.find_first_not_of(delimiters, pos);
// Find next "non-delimiter"
pos = str.find_first_of(delimiters, lastPos);
}
}
The first argument is the string to tokenize, the second is a reference to a vector<string> which the function will put the tokens in, and the third argument is a string containing all the delimiter characters. You can use it with the delimiters mentioned above like this:
string s = "y=-3x + 10";
vector<string> tokens;
tokenize(s, tokens, "y=x ");
For the example string above tokens will contain the following strings: -3, +, and 10.
Now you can iterate over tokens and call stod() on each token. You can put the results of stod() in a vector<double>:
vector<double> doubles;
for (vector<string>::iterator iter = tokens.begin(); iter != tokens.end(); ++iter) {
try {
doubles.push_back(stod(*iter)); // size_t* idx is an optional argument
} catch (...) {
// handle exceptions here. stod() will throw an exception
// on the "+" token but you can throw it away
}
}
Now doubles should have exactly 2 elements -- one for the slope and another for the intercept. Assuming the slope came first (the string was of the form y=mx+b instead of y=b+mx) then you can extract them from doubles:
double m = doubles[0];
double b = doubles[1];
Parsing the initial string is more complicated if the user is allowed different forms like y=b+mx (in that case the intercept came first), and much more complicated if the user can enter even stranger (but valid) forms like x*m+b=y (now you can't just assume that the number before the x character is the slope). It's not clear from your question exactly what alternate forms are considered valid, but nonetheless this should get you started.
Finally, as to your question about *idx, stod() puts into it the position of the first character after the number it parsed. This allows you to easily parse multiple numbers in a single string by skipping the number that was just parsed. Using the example at your reference link with some added comments:
std::string orbits ("365.24 29.53");
std::string::size_type sz; // alias of size_t
double earth = std::stod (orbits,&sz);
// sz now holds the position of the first character after 365.24, which is whitespace
// the next call to stod() will start from the sz position
double moon = std::stod (orbits.substr(sz));

middle function

I need a function middle that accepts a string and returns the middle character if there are an odd number of characters and the two middle characters if there are a even number of characters in the string in C++ for a program I am writing unfortunately I cannot find anything pre-made for an example thats in c++
std::string middleCharacters(const std::string &str)
{
if (str.length() <= 0) return ""; // For an empty string, return an empty string (customize this as desired)
return str.substr((str.length() - 1) / 2, 2 - str.length() % 2);
}
For proof that this works: http://ideone.com/vId2l

How to find the length of the string which also contains string terminating character in between. Example: ABC\0ABC

How to find the length of the string which also contains string terminating character in between. Example: ABC\0ABC. Is there any inbuilt function present which returns the length?
If the Input string is: ABC\0ABC
Output: 8
Since the end of a C-style string is only detectable because it ends in a '\0' character, what you're asking isn't solvable in a general way. If, like in your example, you know there's exactly one '\0' character in the string, then you can simply do:
x = strlen(string); // length of string before the first '\0'
x += strlen(string + x + 1) + 1; // plus the length of the string after
// the first '\0' plus the '\0' itself.