Reputation: 3
I have to write a c++ function with the following specifications:
unique
Deletes the duplicated charters between the two parameter pointers. The string remains on its original place.
param first - pointer to the beginning of the string
param last - pointer to the data after the last charter
return - pointer to the first charater of the new data series
If the input is "H\0elllo C+++++ +!#", the output is "H\0elo C+ +!#". I canot figure out how to ignore the terminating null in the middle. This is my best approach so far:
char *sajat::unique(char *first, char *last){
char* moving = first + 1;
char* follower = first;
while (moving != last)
{
char *sentinel = first;
if (*follower == *moving)
{
counter++;
sentinel = follower; //here was the duplication
while (follower != last)
{
*follower = *moving;
follower++;
moving++;
}
sentinel = follwer;
moving = follower + 1;
}
moving++;
follower++;
}
return first - counter;
}
So this code is obviously wrong...but it can identify successfully the duplication. (I know it is homework and shame on me....but i have been trying to solve it for hours. Sorry for the messed up code.)
Upvotes: 0
Views: 262
Reputation: 148920
You are given here a char array that is not a C string because it can contain null characters. That means you should forget everething you could know about C strings when processing it.
It is given by 2 pointers, one at the start, one past the end. As it is to be processed in place, the start pointer will not change, so your function should just return the new end pointer (still same definition: one past the last kept character).
Once this is said, you current code is much too complex. You only have to read the string one char at a time, compare the current character with the previous one and keep it only if they are different. A simple way is to use 2 pointers, one for reading and one for writing, increment the read pointer on each iteration and increment the write pointer only if the character has to be kept. As for the previous value, an idiomatic way is to initialize it to an int value that cannot be represented by a character.
The function reduces to:
char *sajat::unique(char *first, char *last){
char *rd = first, *wr = first;
int prev = UCHAR_MAX + 1; // cannot be a character value
while (rd != last) {
if (prev != *rd) {
prev = *wr++ = *rd;
}
rd++;
}
return wr;
}
Demo code:
#include <iostream>
#include <string>
#include <climits>
char *unique(char *first, char *last){
char *rd = first, *wr = first;
int prev = UCHAR_MAX + 1; // cannot be a character value
while (rd != last) {
if (prev != *rd) {
prev = *wr++ = *rd;
}
rd++;
}
return wr;
}
int main() {
char tst[] = "H\0elllo C+++++ +!#";
char *last = unique(tst, tst+sizeof(tst) - 1); // reject the terminating null
std::cout << std::string(tst, last) << std::endl; // first display the result as a string
for (char *ix=tst;ix<last; ix++) { // then every character in hexa
std::cout << std::hex << " " << (unsigned int)(unsigned char) *ix;
}
std::cout << std::endl;
return 0;
}
On my ASCII system it shows:
Helo C+ +!#
48 0 65 6c 6f 20 43 2b 20 2b 21 23
Upvotes: 1