C++, String to Array of Characters with my professor's limitations
C++, String to Array of Characters with my professor's limitations
I'm learning C++, and I have no idea how I'm supposed to do the following.
In an assignment, we need to write a function that checks if the first two characters of a string are the same as the last two.
These are the limitations:
You cannot use std::string
class or string function such as strlen
. You must use either array or pointer for this function.
std::string
strlen
I tried this:
bool haveTheSameTwoChars(string str) {
char arr = str;
if (sizeof(arr) < 3) {
return false;
}
else if (arr[0] == arr[sizeof(arr) - 3] && arr[1] == arr[sizeof(arr) - 2]) {
return true;
}
else {
return false;
}
}
But it won't accept str
into the array.
str
However, if I were to put something in quotes in the place of str
, it accepts it just fine, despite them both being strings.
str
What am I doing wrong?
std::string
std::string
also the
sizeof
operator does not determine the length of a string. Strings (c-strings) are null-terminated, i.e. the last element of a string is zero/null.– theKidOfArcrania
Jul 3 at 6:53
sizeof
Well, you are actually going to use both (array and pointer). You will hold your string in an array of
char
and you will use a pointer (or two) to compare the first/last and (first+1)/(last-1) chars.– David C. Rankin
Jul 3 at 7:13
char
You can't use
std::string
...**but can you use std::vector<char>
** ;)– JHBonarius
Jul 3 at 7:48
std::string
std::vector<char>
char arr = "str";
works because the array size is determined from the string literal at compile time, just like if you write int arr = {1,2,3};
.– molbdnilo
Jul 3 at 8:07
char arr = "str";
int arr = {1,2,3};
5 Answers
5
Well, here's the breakdown of your problem:
You need to take input as an array or a pointer. For example:
bool isMatched( const char* str )
{
// ...
}
Now, you need to calculate the length of your string yourself. Revise the loops and devise something that gives you the length of a null terminated string. C-strings are null-terminated i.e. ''
so you can end your loop when you encounter null character. For example:
''
int len = 0;
while ( str[len] != '' ) len++;
That's just an idea. Do your own research and calculate the string length correctly.
The rest is just a comparison of first and last two characters using if
. :)
if
I'm sure you can put things together and revise your study material a bit to solve this.
Best of luck!
Happy coding!
Why the down vote?
– Azeem
Jul 3 at 7:29
When you're not allowed strlen
, it is a strong hint that the problem can be solved without caring about the length of the string.
strlen
Let's do that:
First, you should have the prototype (no string
s allowed, right?)
string
bool haveTheSameTwoChars(const char* str)
Then, verify that the string has at least two characters
if (!str || !str[0] || !str[1])
return false;
Then you find the end of the string:
const char* end = str;
while (*end)
end++;
Then move back two characters, so end
points to the first of the last two characters:
end
end -= 2;
(This is safe since we first checked that there are at least two characters.)
Then compare
return str[0] == end[0] && str[1] == end[1];
Personally I think the 2 character case should always return
true
, but this is nicely set out, +1.– Bathsheba
Jul 3 at 8:06
true
@Bathsheba before doing
end -= 2
, you could do if ((end - str) == 2)
and return true to handle the 2-character case.– Shadow2531
Jul 4 at 5:42
end -= 2
if ((end - str) == 2)
Your professor wants you to use a const char*
as the function parameter, that is, model a string as a pointer to the first character in the string, where the string finishes with a 0. (We call this NUL-termination).
const char*
So your function is
bool haveTheSameTwoChars(const char* s)
You then need to roll your own version of strlen
1 to calculate the number of characters in the string up to and not including the NUL
:
strlen
NUL
#include <cstddef> // for std::size_t
std::size_t strlen(const char *s) {
const char *p = s;
while (*s) ++s;
return s - p;
}
After which, it's a simple case, given the length l
say, of dealing with a couple of edge cases and the general case:
l
l
false
l
true
l
l
Note that C++ does not support variable length arrays, so char arr = str;
is not valid C++, and sizeof
is a compile-time operator so would only give you the size of an actual array type, not an array that's decayed to a pointer type.
char arr = str;
sizeof
1 No professional programmer would dream of doing that. A compiler might optimise strlen
down to a machine word-based algorithm, i.e. consider multiple bytes simultaneously.
strlen
Here is some sample code for your purpose
bool haveTheSameTwoChars(const char* p) {
if(!p || !*p)
return false;
int len = -1;
while(p[++len]);
if(p[0] == p[len-2] &&
p[1] == p[len-1])
return true;
return false;
}
This will return true if the string is "ABxxxAB" and false if "ABxxxBA". Rest you can tweak according to your desire.Thanks
That returns true for the string "teteth".
– Shadow2531
Jul 4 at 4:54
@Shadow2531 I request you to check once again by calling the function as haveTheSameTwoChars("teteth");
– paper.plane
Jul 4 at 6:09
Oops, sorry. You're all good.
– Shadow2531
Jul 4 at 6:43
Another approach uses a loop and a single pointer to iterate over each line saving the first and second characters to compare against the next to last (penultimate) and last (ultimate) characters in the string.
By using simple iteration over the character array, as long as it is nul-terminated, you don't have to worry about a separate loop to find the length, you simply grab/save the first two characters, and then iterate to the end of your string saving the prev/last characters as you go. When you hit the end of your string, all you need to do is compare the first against the last and the second against the next to last, e.g.
/* function iterates pointer through chars in 'line' saving
* the 1st & 2nd chara in 'beg` and 'next' and the penultimate and
* ultimate characters in 'prev' & 'last' and compares. returns 1 if
* 1st matches ultimate AND 2nd matches penultimate, 0 otherwise.
*/
int begmatchend (const char *line)
{
const char *p = line; /* pointer to line */
char beg = *p++, /* save for 1st char */
next = *p++, /* save for 2nd char */
prev = *p++, /* save for next to last char */
last = *p++; /* save for last char */
while (*p) { /* iterate over line setting prev/last as you go */
prev = last;
last = *p++;
}
if (beg == last && next == prev) /* test whether equal */
return 1;
return 0;
}
Then for a simple test, you can just feed your programs lines from a file calling begmatchend
on each line and then output indication of which lines matched. Something simple like the following is one way:
begmatchend
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstddef>
#define MAXC 1024
/* function iterates pointer through chars in 'line' saving
* the 1st & 2nd chara in 'beg` and 'next' and the penultimate and
* ultimate characters in 'prev' & 'last' and compares. returns 1 if
* 1st matches ultimate AND 2nd matches penultimate, 0 otherwise.
*/
int begmatchend (const char *line)
{
const char *p = line; /* pointer to line */
char beg = *p++, /* save for 1st char */
next = *p++, /* save for 2nd char */
prev = *p++, /* save for next to last char */
last = *p++; /* save for last char */
while (*p) { /* iterate over line setting prev/last as you go */
prev = last;
last = *p++;
}
if (beg == last && next == prev) /* test whether equal */
return 1;
return 0;
}
int main (int argc, char **argv) {
char line[MAXC] = "";
size_t n = 0;
std::ifstream f (argc > 1 ? argv[1] : "/dev/stdin");
if (!f.is_open()) {
std::cerr << "error: file open failed.n";
return 1;
}
while (f.getline (line, MAXC, 'n')) {
if (begmatchend ((const char *)line))
std::cout << "line[" << std::setw(3) << n <<
"] 1st/ultimate matched, 2nd/penultimate matched.n";
n++;
}
return 0;
}
Example Input
$ cat dat/linesbegend.txt
all good vikings go to valhalla
be a tide that will flow and eb
a quick brown fox jumps over the lazy dog
we can find the begin and end - eew
Example Use/Output
$ ./bin/beg_end_match dat/linesbegend.txt
line[ 0] 1st/ultimate matched, 2nd/penultimate matched.
line[ 1] 1st/ultimate matched, 2nd/penultimate matched.
line[ 3] 1st/ultimate matched, 2nd/penultimate matched.
Look things over and let me know if you have any questions.
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
if you are not suppose to use the
std::string
class, why is the first parameter passed into the function astd::string
object?– theKidOfArcrania
Jul 3 at 6:51