Remove prefix and suffix from char array

Hello!

I am working on getting back into school after a year off. I am doing all of my assignments from my last CS class over again and there was one assignment that I could not complete.
I am to take a user supplied sentence, and strip both the suffixes and prefixes from the sentence.

The function removeAffix() will hopefully remove both the suffix and prefix but I am currently testing to remove the prefixes.

I am not sure if I need a temp array to hold the changes to the sentence, or if I can edit the original as I iterate through each character in the sentence and prefixes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <iostream>
#include <cstring>

using namespace std;

const int NUM_ROWS = 3; //Number of prefix and suffix's
const int MAX_AFFIX = 5; //Max length for prefix and suffix
const int MAX_SENTANCE = 201; //Max length for sentance

void intro();
void getPrefix(char [][MAX_AFFIX]);
void getSuffix(char [][MAX_AFFIX]);
void getSentance(char sentance[MAX_SENTANCE]);
void displayPrefix(char prefix[][MAX_AFFIX]);
void displaySuffix(char suffix[][MAX_AFFIX]);
void displaySentance(char sentance[MAX_SENTANCE]);
void formatSentance(char sentance[MAX_SENTANCE]);
// remove

int main()
{
   char prefix[NUM_ROWS][MAX_AFFIX];
   char suffix[NUM_ROWS][MAX_AFFIX];

   intro();
  // getPrefix(prefix);
  // getSuffix(suffix);
  // getSentance(sentance);
  // formatSentance(sentance);
  // displaySentance(sentance);
  // displayPrefix(prefix);
  // displaySuffix(suffix);

   return 0;
}

// Introduce user to the program
void intro()
{
   cout << "\n******************************************\n";
   cout << "Welcome to the root-word finding program!\n";
   cout << "******************************************\n";
   cout << "\nThis program will help you find the root of a word.\n";
   cout << "\nYou will first be asked to input three prefix's then three suffix's.\n";
   cout << "Then you will be asked to type a sentance consisting of 200 characters or less.\n\n";
}

void getPrefix(char prefix[][MAX_AFFIX])
{
   int count = 0;

   for (int i = 0; i < NUM_ROWS; i++)
   {
      cout << "Enter prefix #" << i+1 << ": ";
      cin.get(prefix[i], MAX_AFFIX, '\n');
      cin.ignore(100, '\n');
   }
   while (count < NUM_ROWS)
   {
      for (int i = 0; i < MAX_AFFIX; i++)
      {
         prefix[count][i] = tolower(prefix[count][i]);
      }
      count++;
   }
}
void getSuffix(char suffix[][MAX_AFFIX])
{
   int count = 0;

   cout << endl;
   for (int i = 0; i < NUM_ROWS; i++)
   {
      cout << "Enter suffix #" << i+1 << ": ";
      cin.get(suffix[i], MAX_AFFIX, '\n');
      cin.ignore(100, '\n');
   }  
   while (count < NUM_ROWS)
   {
      for (int i = 0; i < MAX_AFFIX; i++)
      {
         suffix[count][i] = tolower(suffix[count][i]);
      }
      count++;
   }
}
void getSentance(char sentance[MAX_SENTANCE])
{
   cout << "\nEnter a sentance consisting of 200 characters or less.\nType your sentance here: " << endl;
   cin.get(sentance, MAX_SENTANCE, '\n');
   cin.ignore(100, '\n');
}
void displayPrefix(char prefix[][MAX_AFFIX])
{
   cout << endl; // formatting
   for (int i = 0; i < NUM_ROWS; i++)
   {
      cout << prefix[i] << endl;
   }
}
void displaySuffix(char suffix[][MAX_AFFIX])
{
   cout << endl; // formatting
   for (int i = 0; i < NUM_ROWS; i++)
   {
      cout << suffix[i] << endl;
   }
}
void displaySentance(char sentance[MAX_SENTANCE])
{
   cout <<  endl << sentance << endl;
}
void formatSentance(char sentance[MAX_SENTANCE])
{
   int sentanceLength = strlen(sentance);

   for (int i = 0; i < MAX_SENTANCE; i++)
   {
      sentance[i] = tolower(sentance[i]);

      if (ispunct(sentance[i]))
      {
         sentance[i] = '+';
      }
   }
}
void removeAffix(char sentance[MAX_SENTANCE], char prefix[][MAX_AFFIX])
{
   int sentanceLength = strlen(sentance);
   int count = 0;
   int prefixLength = 0;

   while (count < NUM_ROWS)
   {
      prefixLength = strlen(prefix[count]);

      for (int i = 0; i < sentanceLength; i++)
      {
         for (int j = 0; j < prefixLength; j++)
         {
            if ( sentance[i] == prefix[count][j])
            {
               //
            }
         }
      }
      count++;
   }
}
Last edited on
I've somewhat changed the code to give:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <iostream>
#include <cstring>

const size_t NUM_ROWS {3};			// Number of prefix and suffix's
const size_t MAX_AFFIX {5};			// Max length for prefix and suffix
const size_t MAX_SENTANCE {201};	// Max length for sentence

void intro();
void getPrefix(char[][MAX_AFFIX]);
void getSuffix(char[][MAX_AFFIX]);
void getSentance(char sentance[MAX_SENTANCE]);
void displayPrefix(char prefix[][MAX_AFFIX]);
void displaySuffix(char suffix[][MAX_AFFIX]);
void displaySentance(char sentance[MAX_SENTANCE]);
void formatSentance(char sentance[MAX_SENTANCE]);
void removeSuffix(char sentance[MAX_SENTANCE], const char suffix[][MAX_AFFIX]);
void removePrefix(char sentance[MAX_SENTANCE], const char prefix[][MAX_AFFIX]);

int main()
{
	char prefix[NUM_ROWS][MAX_AFFIX] {"abc", "asd", "zxc"};
	char suffix[NUM_ROWS][MAX_AFFIX] {};

	char test[] {"asdabcdefghijkl"};

	std::cout << test << '\n';

	removePrefix(test, prefix);

	std::cout << test << '\n';

	//intro();
}

// Introduce user to the program
void intro()
{
	std::cout << "\n******************************************\n";
	std::cout << "Welcome to the root-word finding program!\n";
	std::cout << "******************************************\n";
	std::cout << "\nThis program will help you find the root of a word.\n";
	std::cout << "\nYou will first be asked to input three prefix's then three suffix's.\n";
	std::cout << "Then you will be asked to type a sentence consisting of 200 characters or less.\n\n";
}

void getPrefix(char prefix[][MAX_AFFIX])
{
	for (size_t i = 0; i < NUM_ROWS; i++) {
		std::cout << "Enter prefix #" << i + 1 << ": ";
		std::cin.get(prefix[i], MAX_AFFIX, '\n');
		std::cin.ignore(1000, '\n');
	}

	for (size_t count {}; count < NUM_ROWS; ++count)
		for (auto& ch : prefix[count])
			ch = tolower(ch);
}

void getSuffix(char suffix[][MAX_AFFIX])
{
	for (size_t i = 0; i < NUM_ROWS; i++) {
		std::cout << "Enter suffix #" << i + 1 << ": ";
		std::cin.get(suffix[i], MAX_AFFIX, '\n');
		std::cin.ignore(1000, '\n');
	}

	for (size_t count {}; count < NUM_ROWS; ++count)
		for (auto& ch : suffix[count])
			ch = tolower(ch);
}

void getSentance(char sentance[MAX_SENTANCE])
{
	std::cout << "\nEnter a sentence consisting of " << MAX_SENTANCE << " characters or less.\nType your sentence here : \n";
	std::cin.get(sentance, MAX_SENTANCE, '\n');
	std::cin.ignore(1000, '\n');
}

void displayPrefix(const char prefix[][MAX_AFFIX])
{
	std::cout << '\n';

	for (size_t i = 0; i < NUM_ROWS; ++i)
		std::cout << prefix[i] << '\n';
}

void displaySuffix(const char suffix[][MAX_AFFIX])
{
	std::cout << '\n';

	for (int i = 0; i < NUM_ROWS; i++)
		std::cout << suffix[i] << '\n';
}

void displaySentance(const char sentance[MAX_SENTANCE])
{
	std::cout << '\n' << sentance << '\n';
}

void formatSentance(char sentance[MAX_SENTANCE])
{
	for (auto ptr {sentance}; ptr && *ptr; ++ptr)
		*ptr = ispunct(*ptr) ? '+' : tolower(*ptr);
}

void removeSuffix(char sentance[MAX_SENTANCE], const char suffix[][MAX_AFFIX])
{
}

void removePrefix(char sentance[MAX_SENTANCE], const char prefix[][MAX_AFFIX])
{
	for (size_t r = 0; r < NUM_ROWS; ++r) {
		auto sent {sentance};
		auto pre {prefix[r]};

		while (*sent && *pre && *sent == *pre)
			++sent, ++pre;

		if (*pre == 0) {
			strcpy(sentance, sent);
			return;
		}
	}
}


What is required for removeSuffix() and removePrefix() ? Does this mean that if any of the provided suffixes and prefixes match the given string, then the found one is removed from the beginning/end of the string?

I've provided some code for removePrefix(). Is this is what is wanted?
Last edited on
removeSuffix() should delete each instance of the three user supplied suffixes in the entire sentence. removePrefix() should do the same for the prefixes.

The resulting sentence should consist of the root of each word in the sentence.

For example, if I enter the sentence : "My relationship with computer science is shaky"
and the user supplies:
three prefixes to remove: com, rela, sci
three suffixes to remove: ship, ter, nce

then the final sentence should look like this : "My tion with p e is shaky"

btw, the terms "auto", "size_t", "pre", and "sent" were all new to me until moments ago. My teacher always stressed using c++ 11 or earlier.
auto was introduced into the language in C++11. It just means figure out what the variable type is based on the context of the statement.

size_t has been in the language as long as I remember. It's just an unsigned integral type used for indicating the size of something. Think unsigned int. It may actually be a different type, but that is the idea.

pre and sent ares just variable names. You know what they are. They are declared auto, so that just means that the compiler figures out what types they are.

Edit:

You might be confuse by the curly braces in lines 113 and 114. This is direct initialization of a variable. It was also introduced in C++11. This method of initializing a variable is better, but others on this forum will have a better explanation as to why than I do.
Last edited on
std::size_t is the largest unsigned int type that the system has. On a 64 bit system, it is usually unsigned 64 bit integer.
https://en.cppreference.com/w/cpp/language/types The Data models section.

With C++23, there is a signed std::size_t type. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0330r8.html

The curly braces with initialisation is value initialisation. The compiler will show an error if there is any narrowing of a type - for example if a function is expecting a float, and a double is provided; or expecting unsigned and a signed type is provided. I like to put braces around function arguments as defensive mechanism in this respect:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void f(long double arg) {
  std::cout << arg << "\n";
}

double a = 10.0;

f({a}); // error long double expected. without braces double val printed, maybe ok if: not out of range, 
         // or doesn't require significant figures

void f(std::size_t arg) {
   std::cout << arg << "\n";
}

int b = -1;
f({b}); // error std::size_t expected.  without braces, a large positive value printed 




Direct initialisation uses parentheses, as in:

int a(10);

But direct initialisation can also use braces since C++11, so it is a little confusing, probably why doug4 referred to it like this.

cppreference wrote:
Initializes an object from explicit set of constructor arguments.




Initiailisation in C++ could be seen as being a little complicated, IMO: there are 11 ways of doing it, and they are interrelated. However I don't mean to imply that it is difficult.

> std::size_t is the largest unsigned int type that the system has.

This is not guaranteed by the standard.
(There is a guarantee that std::size_t would be at least sixteen bits wide).

std::size_t: https://en.cppreference.com/w/cpp/types/size_t


Perhaps as a first revision, consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <iostream>
#include <cstring>

constexpr size_t NUM_ROWS {3};			// Number of prefix and suffix's
constexpr size_t MAX_AFFIX {5};			// Max length for prefix and suffix
constexpr size_t MAX_SENTANCE {201};	// Max length for sentence

void intro();
void getPrefix(char[][MAX_AFFIX]);
void getSuffix(char[][MAX_AFFIX]);
void getSentance(char sentance[MAX_SENTANCE]);
void displayPrefix(char prefix[][MAX_AFFIX]);
void displaySuffix(char suffix[][MAX_AFFIX]);
void displaySentance(char sentance[MAX_SENTANCE]);
void formatSentance(char sentance[MAX_SENTANCE]);
void removeSuffix(char sentance[MAX_SENTANCE], const char suffix[][MAX_AFFIX]);
void removePrefix(char sentance[MAX_SENTANCE], const char prefix[][MAX_AFFIX]);

int main()
{
	char prefix[NUM_ROWS][MAX_AFFIX] {};
	char suffix[NUM_ROWS][MAX_AFFIX] {};
	char sent[MAX_SENTANCE] {};

	getPrefix(prefix);
	getSuffix(suffix);
	getSentance(sent);
	formatSentance(sent);

	for (auto tok {std::strtok(sent, " ")}; tok != nullptr; tok = std::strtok(nullptr, " ")) {
		removePrefix(tok, prefix);
		removeSuffix(tok, suffix);
		std::cout << tok << ' ';
	}

	//intro();
}

// Introduce user to the program
void intro()
{
	std::cout << "\n******************************************\n";
	std::cout << "Welcome to the root-word finding program!\n";
	std::cout << "******************************************\n";
	std::cout << "\nThis program will help you find the root of a word.\n";
	std::cout << "\nYou will first be asked to input three prefix's then three suffix's.\n";
	std::cout << "Then you will be asked to type a sentence consisting of 200 characters or less.\n\n";
}

void getPrefix(char prefix[][MAX_AFFIX])
{
	for (size_t i = 0; i < NUM_ROWS; i++) {
		std::cout << "Enter prefix #" << i + 1 << ": ";
		std::cin.get(prefix[i], MAX_AFFIX, '\n');
		std::cin.ignore(1000, '\n');
	}

	for (size_t count {}; count < NUM_ROWS; ++count)
		for (auto& ch : prefix[count])
			if (!(ch = static_cast<char>(tolower(static_cast<unsigned char>(ch)))))
				break;
}

void getSuffix(char suffix[][MAX_AFFIX])
{
	for (size_t i = 0; i < NUM_ROWS; i++) {
		std::cout << "Enter suffix #" << i + 1 << ": ";
		std::cin.get(suffix[i], MAX_AFFIX, '\n');
		std::cin.ignore(1000, '\n');
	}

	for (size_t count {}; count < NUM_ROWS; ++count)
		for (auto& ch : suffix[count])
			if (!(ch = static_cast<char>(tolower(static_cast<unsigned char>(ch)))))
				break;
}

void getSentance(char sentance[MAX_SENTANCE])
{
	std::cout << "\nEnter a sentence consisting of " << MAX_SENTANCE << " characters or less.\nType your sentence here : \n";
	std::cin.get(sentance, MAX_SENTANCE, '\n');
	std::cin.ignore(1000, '\n');
}

void displayPrefix(const char prefix[][MAX_AFFIX])
{
	std::cout << '\n';

	for (size_t i = 0; i < NUM_ROWS; ++i)
		std::cout << prefix[i] << '\n';
}

void displaySuffix(const char suffix[][MAX_AFFIX])
{
	std::cout << '\n';

	for (int i = 0; i < NUM_ROWS; i++)
		std::cout << suffix[i] << '\n';
}

void displaySentance(const char sentance[MAX_SENTANCE])
{
	std::cout << '\n' << sentance << '\n';
}

void formatSentance(char sentance[MAX_SENTANCE])
{
	for (auto ptr {sentance}; ptr && *ptr; ++ptr)
		*ptr = ispunct(*ptr) ? '+' : static_cast<char>(tolower(static_cast<unsigned char>(*ptr)));
}

void removeSuffix(char sentance[MAX_SENTANCE], const char suffix[][MAX_AFFIX])
{
	const auto senlen {std::strlen(sentance)};

	for (size_t r = 0; r < NUM_ROWS; ++r) {
		const auto strt {sentance + senlen - std::strlen(suffix[r])};

		if (strcmp(strt, suffix[r]) == 0) {
			*strt = 0;
			return;
		}
	}
}

void removePrefix(char sentance[MAX_SENTANCE], const char prefix[][MAX_AFFIX])
{
	for (size_t r = 0; r < NUM_ROWS; ++r) {
		auto sent {sentance};
		auto pre {prefix[r]};

		while (*sent && *pre && *sent == *pre)
			++sent, ++pre;

		if (*pre == 0) {
			strcpy(sentance, sent);
			return;
		}
	}
}



Enter prefix #1: com
Enter prefix #2: rela
Enter prefix #3: sci
Enter suffix #1: ship
Enter suffix #2: ter
Enter suffix #3: nce

Enter a sentence consisting of 201 characters or less.
Type your sentence here :
My relationship with computer science is shaky
my tion with pu e is shaky

Technically, the behavior of strcpy is undefined if the strings overlap like in strcpy(sentance, sent);. Maybe try memmove (which allows overlapping memory).

BTW, why is "sentence" being spelled as "sentance"?
@JLBorges

It is good to see you back on the forum again, I always look forward to your always expert advice :+)

Yes, I should have mentioned that, and I should moderate my statements more: used the word "usually" rather than "is" in that sentence too.

OK - just for the pedantics :) :) , replace L136 with:

 
while (*sentance++ = *sent++);


FYI. It's spelled sentance as that is how it was spelled in the OP!
Last edited on
@seeplus - based on your output, this is exactly what I'm looking for. Since this was for an assignment for a class I took in Fall 2020, we were only supposed to use syntax that was taught up until that point. I will play around with the code a bit and try to understand what exactly is happening with the changes you have made in main and the remove Prefix/Suffix function.

Thanks to all of you for your replies!
it looks like you are in good hands.
I had this as a real world problem, dealing with names (eg Dr. Mr. ... Jr, Sr, III,..)
and used c++ strings but the same logic would work here.
what I ended up doing was:
1)prepend and append a space to the whole string so the 'sentence' begins and ends with a space.
2) find the offending text including the spaces, eg " Dr." or "III " would be fed into strstr (for c-strings) how you set up the spaces here would affect behavior, so be careful with that.
3) process found text from 2 as required. Loop 2-3 as needed.

4) I had an exclusion list. There were some places where the internal space was missing eg "john smithIII) and worse a few names actually end in these eg "yoshii" so I had to exclude the handful of names that were gumming up the works. None of this applies to your code, but again, a real world example.

with strstr (actually find()) doing 90% of the work and a fixed set of prefixes/suffixes, it was a lot smaller than what you guys have.
using c-style arrays, my code above can, of course, be simplified. Consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <cstring>
#include <limits>

constexpr size_t NUM_ROWS {3};			// Number of prefix and suffix's
constexpr size_t MAX_AFFIX {5};			// Max length for prefix and suffix
constexpr size_t MAX_SENTANCE {201};	// Max length for sentence

void getFix(const char*, char[][MAX_AFFIX]);
void getSentance(char sentance[MAX_SENTANCE]);
char* removeFix(char sentance[MAX_SENTANCE], const char prefix[][MAX_AFFIX], const char suffix[][MAX_AFFIX]);

int main()
{
	char prefix[NUM_ROWS][MAX_AFFIX] {};
	char suffix[NUM_ROWS][MAX_AFFIX] {};
	char sent[MAX_SENTANCE] {};

	getFix("Enter prefix", prefix);
	getFix("Enter suffix", suffix);
	getSentance(sent);

	for (auto tok {std::strtok(sent, " ")}; tok != nullptr; tok = std::strtok(nullptr, " "))
		std::cout << removeFix(tok, prefix, suffix) << ' ';
}

void getFix(const char* prm, char fix[][MAX_AFFIX])
{
	for (size_t i = 0; i < NUM_ROWS; ++i) {
		std::cout << prm << " #" << i + 1 << ": ";
		std::cin.get(fix[i], MAX_AFFIX, '\n');
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

		for (auto& ch : fix[i])
			if (!(ch = static_cast<char>(tolower(static_cast<unsigned char>(ch)))))
				break;
	}
}

void getSentance(char sentance[MAX_SENTANCE])
{
	std::cout << "\nEnter a sentence consisting of " << MAX_SENTANCE << " characters or less.\nType your sentence here : \n";
	std::cin.get(sentance, MAX_SENTANCE, '\n');
	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

	for (auto ptr {sentance}; ptr && *ptr; ++ptr)
		*ptr = ispunct(*ptr) ? '+' : static_cast<char>(tolower(static_cast<unsigned char>(*ptr)));
}

char* removeFix(char sentance[MAX_SENTANCE], const char prefix[][MAX_AFFIX], const char suffix[][MAX_AFFIX])
{
	auto sent {sentance};

	for (size_t r = 0, senlen {std::strlen(sent)}; r < NUM_ROWS; ++r) {
		const auto suflen {std::strlen(suffix[r])};

		if (const auto strt {sent + senlen - suflen}; senlen >= suflen && strcmp(strt, suffix[r]) == 0) {
			senlen -= suflen;
			*strt = 0;
		}

		auto pre {prefix[r]};
		auto sent1(sent);

		for (; *sent1 && *pre && *sent1 == *pre; ++sent1, ++pre);

		if (*pre == 0) {
			senlen -= sent1 - sent;
			sent = sent1;
		}
	}

	return sent;
}

Last edited on
For a C++20 way, possibly consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <vector>
#include <string_view>
#include <iostream>
#include <iterator>

struct cStr : public std::string_view {
	constexpr cStr(const char* cs) : std::string_view(cs) {}
	constexpr operator const char* () const noexcept { return data(); }
	constexpr const char* c_str() const noexcept { return data(); }
};

std::string_view fix(std::string_view sv)
{
	constinit static cStr pre[] {"com", "rela", "sci"};
	constinit static cStr suf[] {"ship", "ter", "nce"};

	for (size_t p = 0; p < std::size(pre); )
		if (sv.starts_with(pre[p])) {
			sv.remove_prefix(pre[p].size());
			p = 0;
		} else
			++p;

	for (size_t s = 0; s < std::size(suf); )
		if (sv.ends_with(suf[s])) {
			sv.remove_suffix(suf[s].size());
			s = 0;
		} else
			++s;
	return sv;
}

auto split(const std::string_view& s, char delim)
{
	std::vector<std::string_view> vsv;

	const auto pb {[&](auto st, auto dp) { vsv.emplace_back(fix(std::string_view(s.data() + st, dp - st))); }};

	for (auto delimPosition = s.find(delim), tokenStart = static_cast<size_t>(0); delimPosition != std::string_view::npos; )
		if (pb(tokenStart, delimPosition); (delimPosition = s.find(delim, (tokenStart = ++delimPosition))) == std::string_view::npos)
			pb(tokenStart, s.size());

	return vsv;
}

int main()
{
	constexpr cStr line {"my relationship with computer science is shaky"};
	const auto revised {split(line, ' ')};

	for (const auto& w : revised)
		std::cout << w << ' ';

	std::cout << ' ';
}

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <array>
#include <string_view>
#include <iostream>
#include <iterator>
#include <regex>

std::string drop_affixes(std::string_view w, auto pfxs_beg, auto pfxs_end, auto sfxs_beg, auto sfxs_end)
{
  auto const p = std::find_if(pfxs_beg, pfxs_end, [w](auto prefix) { return w.starts_with(prefix); });  
  if (p != pfxs_end) w.remove_prefix(p->size());
  auto const s = std::find_if(sfxs_beg, sfxs_end, [w](auto suffix) { return w.ends_with(suffix); });
  if (s != sfxs_end) w.remove_suffix(s->size());
  
  return std::string{w};
}

int main()
{
  std::array<std::string_view, 3> constexpr pfxs {"com", "rela", "sci"};
  std::array<std::string_view, 3> constexpr sfxs {"ship", "ter", "nce"};

  auto const fixup_match = [&pfxs, sfxs](std::smatch const& m) 
    { return m[1].str() + drop_affixes(m[2].str(), pfxs.begin(), pfxs.end(), sfxs.begin(), sfxs.end()); };

  auto const word_re = std::regex{R"((\W*)\b(\w+)\b)"}; 
  for (std::string line; std::getline(std::cin, line); )
  {
    auto const begin_matches = std::sregex_iterator{line.begin(), line.end(), word_re};
    auto const end_matches   = std::sregex_iterator{};
    auto const out           = std::ostream_iterator<std::string>{std::cout};
    std::transform(begin_matches, end_matches, out, fixup_match);
  }
}


Here's another approach, although it's horrible in comparison to the others
Topic archived. No new replies allowed.