C ++: How to split a line into smaller lines of a smaller size?

In C ++, how do I split a string into a smaller, smaller string?

For example, I have the line "012345678" and I want her to split it into 5 smaller lines, and this should return me something like "01", "23", "45", "67", "8",

I am having trouble determining the length of smaller lines. In the previous example, the original line is size 9, and I want to split it into 5 smaller lines, so each smaller line, except the last, should be 9/5 = 1 long, and then the last will be 9 - 1 * 4 = 5, which is unacceptable.

Thus, the formal definition of this problem is : the original string is split into EXACTLY n substrings, and no two substrings should differ by more than 1.

My focus is not on the C ++ syntax or library. This is how to design an algorithm so that the returned string is almost equal in size.

+6
source share
6 answers

In divide the N elements into M parts with a length within one unit, you can use the formula (N*i+N)/M - (N*i)/M as the length of the i'th part, as shown in the figure below.

  #include <string> #include <iostream> using namespace std; int main() { string text = "abcdefghijklmnopqrstuvwxyz"; int N = text.length(); for (int M=3; M<14; ++M) { cout <<" length:"<< N <<" parts:"<< M << "\n"; int at, pre=0, i; for (pre = i = 0; i < M; ++i) { at = (N+N*i)/M; cout << "part " << i << "\t" << pre << "\t" << at; cout << "\t" << text.substr(pre, at-pre) << "\n"; pre = at; } } return 0; } 

For example, when M is 4 or 5, the code above gives:

  length:26 parts:4 part 0 0 6 abcdef part 1 6 13 ghijklm part 2 13 19 nopqrs part 3 19 26 tuvwxyz length:26 parts:5 part 0 0 5 abcde part 1 5 10 fghij part 2 10 15 klmno part 3 15 20 pqrst part 4 20 26 uvwxyz 
+5
source

My decision:

 std::vector<std::string> split(std::string const & s, size_t count) { size_t minsize = s.size()/count; int extra = s.size() - minsize * count; std::vector<std::string> tokens; for(size_t i = 0, offset=0 ; i < count ; ++i, --extra) { size_t size = minsize + (extra>0?1:0); if ( (offset + size) < s.size()) tokens.push_back(s.substr(offset,size)); else tokens.push_back(s.substr(offset, s.size() - offset)); offset += size; } return tokens; } 

Test code:

 int main() { std::string s; while (std::cin >> s) { std::vector<std::string> tokens = split(s, 5); //output std::copy(tokens.begin(), tokens.end(), std::ostream_iterator<std::string>(std::cout, ", ")); std::cout << std::endl; } } 

Input:

 012345 0123456 01234567 012345678 0123456789 01234567890 

Conclusion:

 01, 2, 3, 4, 5, 01, 23, 4, 5, 6, 01, 23, 45, 6, 7, 01, 23, 45, 67, 8, 01, 23, 45, 67, 89, 012, 34, 56, 78, 90, 

Online Demo: http://ideone.com/gINtK

This solution, as a rule, makes the markers even, i.e. All tokens may not be the same size.

+4
source

It is enough to know the length of the substrings; Suppose m is the size() your string:

 int k = (m%n == 0)? n : nm%n; 

Then k substrings must have length m/n and nk length m/n+1 .

+1
source

Try substr .

0
source

You get iterators for where you want to split it, and then use them to build new lines. For instance:

 std::string s1 = "string to split"; std::string::iterator halfway = s1.begin() + s1.size() / 2; std::string s2(s1.begin(), halfway); std::string s3(halfway, s1.end()); 
0
source

Assume that the string length is L and should be divided into substrings n .

 # Find the next multiple of `n` greater than or equal to `L` L = 9 n = 5 LL = n * (L / n) if LL < L: LL += n # Split a string of length LL into n equal sizes. The string is at # most (n-1) longer than L. lengths = [(LL / n) for x in range (n)] # Remove one from the first (or any) (LL-L) elements. for i in range (LL-L): lengths [i] = lengths [i] - 1 # Get indices from lengths. s = 0 idx = [] for i in lengths: idx.append (s) s = s + i idx.append (L) print idx 

EDIT: OK, OK, I forgot that it should be C ++.

EDIT: Here it is ...

 #include <vector> #include <iostream> unsigned int L = 13; unsigned int n = 5; int main () { int i; unsigned int LL; std::vector<int> lengths, idx; /* Find the next multiple of `n` greater than or equal to `L` */ LL = n * (L / n); if (LL < L) LL += n; /* Split a string of length LL into n equal sizes. The string is at most (n-1) longer than L. */ for (i = 0; i < n; ++i) lengths.push_back (LL/n); /* Remove one from the first (or any) (LL-L) elements. */ for (i = 0; i < LL - L; ++i) --lengths [i]; /* Get indices from lengths. */ int s = 0; for (auto &ii: lengths) { idx.push_back (s); s += ii; } idx.push_back (L); for (auto &i : idx) std::cout << i << " "; std::cout << std::endl; return 0; } 
0
source

Source: https://habr.com/ru/post/901972/


All Articles