The function below does exactly what I want it to (there is a main to
test it as well.) However, I'm curious about ideas of making it better.
Anyone interested in critiquing it?
void formatText( const string& in, int charsPerLine, int lines,
vector< string >& out )
{
out.resize( 1 );
out[0] = "";
int prev = 0;
int pos = charsPerLine;
int lineCount = 0;
while ( pos < in.size() ) {
pos = in.find_last_of ( " -", pos );
if ( pos < prev ) {
pos = prev + charsPerLine - 1;
out.back() += in.substr( prev, pos - prev );
out.back() += '-';
prev = pos;
}
else if ( in[pos] == '-' ) {
++pos;
out.back() += in.substr( prev, pos - prev );
prev = pos;
}
else {
out.back() += in.substr( prev, pos - prev );
prev = pos + 1;
}
out.back() += (char)0x0A;
pos += charsPerLine;
++lineCount;
if ( lines <= lineCount ) {
out.back().eras e( out.back().size () - 1 );
out.push_back( "" );
lineCount = 0;
}
}
out.back() += in.substr( prev );
}
int main()
{
string in = "hello";
vector< string out;
formatText( in, 24, 4, out );
assert( out.size() == 1 );
assert( out[0] == "hello" );
in = "Put up with it and you will get more of it.";
formatText( in, 24, 4, out );
assert( out.size() == 1 );
assert( out[0] == "Put up with it and you\nwill get more of it." );
in = "The mind of a bigot is like the pupil of the eye. The more
light you shine on it, the more it will contract.";
formatText( in, 24, 4, out );
assert( out.size() == 2 );
assert( out[0] == "The mind of a bigot is\nlike the pupil of
the\neye. The more light you\nshine on it, the more" );
assert( out[1] == "it will contract." );
in = "Floccinaucinih ilipili-fication";
formatText( in, 24, 4, out );
assert( out.size() == 1 );
assert( out[0] == "Floccinaucinih ilipili-\nfication" );
in = "Floccinaucinih ilipilification ";
formatText( in, 24, 4, out );
assert( out.size() == 1 );
assert( out[0] == "Floccinaucinih ilipilifi-\ncation" );
} 11 1773
"Alf P. Steinbach" <al***@start.no wrote:
However, I'm curious about ideas of making it better.
Anyone interested in critiquing it?
void formatText( const string& in, int charsPerLine, int lines,
vector< string >& out )
{
out.resize( 1 );
out[0] = "";
int prev = 0;
int pos = charsPerLine;
int lineCount = 0;
while ( pos < in.size() ) {
pos = in.find_last_of ( " -", pos );
if ( pos < prev ) {
pos = prev + charsPerLine - 1;
out.back() += in.substr( prev, pos - prev );
out.back() += '-';
prev = pos;
}
else if ( in[pos] == '-' ) {
++pos;
out.back() += in.substr( prev, pos - prev );
prev = pos;
}
else {
out.back() += in.substr( prev, pos - prev );
prev = pos + 1;
}
out.back() += (char)0x0A;
pos += charsPerLine;
++lineCount;
if ( lines <= lineCount ) {
out.back().eras e( out.back().size () - 1 );
out.push_back( "" );
lineCount = 0;
}
}
out.back() += in.substr( prev );
}
I rewrote it as follows, but I'm afraid that removed the desired UB:
I modified your re-write so it passes all the tests:
void formatText(
string const& in,
int charsPerLine,
int lines,
vector< string >& out )
{
vector<string result( 1 );
size_t prev = 0;
size_t pos = charsPerLine;
int lineCount = 0;
while ( pos < in.size() )
{
pos = in.find_last_of ( " -", pos );
if ( pos == string::npos || pos < prev )
{
pos = prev + charsPerLine - 1;
result.back() += in.substr( prev, pos - prev );
result.back() += '-';
prev = pos;
}
else if ( in.at( pos ) == '-' )
{
++pos;
result.back() += in.substr( prev, pos - prev );
prev = pos;
}
else
{
result.back() += in.substr( prev, pos - prev );
prev = pos + 1;
}
result.back() += '\n';
pos += charsPerLine;
++lineCount;
if ( lines <= lineCount )
{
result.back().e rase( result.back().s ize() - 1 );
result.push_bac k( "" );
lineCount = 0;
}
}
result.back() += in.substr( prev );
out.swap( result );
}
I see two basic differences in your code from mine...
1) You define 'pos' and 'prev' as unsigned values which exposed the UB.
2) You do all the work in the vector 'result' rather than the 'out'
parameter. I assume that is to insure that 'out' is unchanged if the
function throws?
The logic, however seems identical to mine. Can you think of any
improvements to the logic?
On Oct 22, 12:11 am, "Daniel T." <danie...@earth link.netwrote:
The function below does exactly what I want it to (there is a main to
test it as well.) However, I'm curious about ideas of making it better.
Anyone interested in critiquing it?
Well, just from the code, I have great difficulty even
understanding it. I'm not even sure what it is supposed to do.
If you're trying to break up text into lines, I don't really
understand the output; what is each entry in the vector (since
the entries themselves have line breaks)? Without a
specification of what the function is supposed to do, you can't
begin to write it, write a test for it, or ask anyone to review
it.
Otherwise: in general, if the problem is breaking up text into
lines of a maximum width, with line breaks only at word
boundaries (or other specified places), then the usual solution
would be to break the problem up into parts: a class which
breaks the input up into words, and a class which puts the words
into the destintation, adding line breaks as needed.
--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
"Alf P. Steinbach" <al***@start.no wrote:
* Daniel T. -Alf P. Steinbach:
The logic, however seems identical to mine. Can you think of any
improvements to the logic?
formatText( "123456 123456", 6, 4, result );
Thanks. Not only did it show an anomaly in the code, but it exposed an
error in one of the other tests! Still no ideas on reducing the
complexity of the code though?
void formatText(
string const& in,
int charsPerLine,
int lines,
vector< string >& out )
{
vector<string result( 1 );
size_t prev = 0;
size_t pos = charsPerLine;
int lineCount = 0;
while ( pos < in.size() )
{
pos = in.find_last_of ( " -", pos );
if ( pos == string::npos || pos < prev )
{
pos = prev + charsPerLine - 1;
result.back() += in.substr( prev, pos - prev );
result.back() += '-';
prev = pos;
}
else if ( in.at( pos ) == '-' )
{
++pos;
result.back() += in.substr( prev, pos - prev );
prev = pos;
}
else
{
result.back() += in.substr( prev, pos - prev );
prev = pos + 1;
}
result.back() += '\n';
pos = prev + charsPerLine;
++lineCount;
if ( lines <= lineCount )
{
result.back().e rase( result.back().s ize() - 1 );
result.push_bac k( "" );
lineCount = 0;
}
}
result.back() += in.substr( prev );
out.swap( result );
}
int main()
{
string in = "hello";
vector< string out;
formatText( in, 24, 4, out );
assert( out.size() == 1 );
assert( out[0] == "hello" );
in = "Put up with it and you will get more of it.";
formatText( in, 24, 4, out );
assert( out.size() == 1 );
assert( out[0] == "Put up with it and you\nwill get more of it." );
in = "The mind of a bigot is like the pupil of the eye. The more
light you shine on it, the more it will contract.";
formatText( in, 24, 4, out );
assert( out.size() == 2 );
assert( out[0] == "The mind of a bigot is\nlike the pupil of
the\neye. The more light you\nshine on it, the more it" );
assert( out[1] == "will contract." );
in = "Floccinaucinih ilipili-fication";
formatText( in, 24, 4, out );
assert( out.size() == 1 );
assert( out[0] == "Floccinaucinih ilipili-\nfication" );
in = "Floccinaucinih ilipilification ";
formatText( in, 24, 4, out );
assert( out.size() == 1 );
assert( out[0] == "Floccinaucinih ilipilifi-\ncation" );
formatText( "123456 123456", 6, 4, out );
assert( out.size() == 1 );
assert( out[0] == "123456\n123456 " );
}
James Kanze <ja*********@gm ail.comwrote:
On Oct 22, 12:11 am, "Daniel T." <danie...@earth link.netwrote:
The function below does exactly what I want it to (there is a
main to test it as well.) However, I'm curious about ideas of
making it better. Anyone interested in critiquing it?
Well, just from the code, I have great difficulty even
understanding it. I'm not even sure what it is supposed to do.
That's why I posted it. I don't generally make functions with that high
a complexity and so I was wondering if someone could make some
suggestions on the logic to see if the complexity can be reduced.
As far as what it's supposed to do... It is supposed to pass all the
tests that were included. I.E., proper execution will exit normally, if
an assert fires, then there is a problem. (Note, due to Alf's helpful
critique I have modified one of the tests and added another.)
If you're trying to break up text into lines, I don't really
understand the output; what is each entry in the vector (since the
entries themselves have line breaks)?
Each entry in the vector is a page.
Without a specification of what the function is supposed to do, you
can't begin to write it, write a test for it, or ask anyone to
review it.
The function is supposed to take a string of text and break it up into a
number of pages. Each page is supposed to be no more than charsPerLine
wide and no more than lines high. The code must be able to hyphenate any
word wider than charsPerLine (although not necessarily at the proper
place according to English grammar,) and the function must be able to
recognize when a very long word is already hyphenated so it won't add
unnecessary hyphens.
Otherwise: in general, if the problem is breaking up text into
lines of a maximum width, with line breaks only at word boundaries
(or other specified places), then the usual solution would be to
break the problem up into parts: a class which breaks the input up
into words, and a class which puts the words into the destintation,
adding line breaks as needed.
Can you show me code demonstrating this? Would such code be less complex
than what I already have? I'm interested in reducing the cyclomatic
complexity if possible.
"Alf P. Steinbach" <al***@start.no wrote:
* Daniel T.:
"Alf P. Steinbach" <al***@start.no wrote:
* Daniel T. -Alf P. Steinbach:
The logic, however seems identical to mine. Can you think of any
improvements to the logic?
formatText( "123456 123456", 6, 4, result );
Thanks. Not only did it show an anomaly in the code, but it exposed an
error in one of the other tests! Still no ideas on reducing the
complexity of the code though?
That /was/ my idea for simplifying the code: should be much simpler if
you fix that.
I fixed that, but my fix didn't change the cyclomatic complexity...
I fail to see any changes in the formatText function (but then, I only
glanced at it, I presume you'd have explained it if you fixed it)?
The only thing I can think to change is that the function performs two
different jobs through the loop. It breaks the string up into lines, and
it breaks lines up into pages. I could seperate these two jobs into two
functions; "breakLines " and "breakPages ". Oh well, I have other
functions to write. Thanks for the help.
Daniel T. wrote:
James Kanze <ja*********@gm ail.comwrote:
>On Oct 22, 12:11 am, "Daniel T." <danie...@earth link.netwrote:
The function below does exactly what I want it to (there is a
main to test it as well.) However, I'm curious about ideas of
making it better. Anyone interested in critiquing it?
Well, just from the code, I have great difficulty even understandin g it. I'm not even sure what it is supposed to do.
That's why I posted it. I don't generally make functions with that high
a complexity and so I was wondering if someone could make some
suggestions on the logic to see if the complexity can be reduced.
As far as what it's supposed to do... It is supposed to pass all the
tests that were included. I.E., proper execution will exit normally, if
an assert fires, then there is a problem. (Note, due to Alf's helpful
critique I have modified one of the tests and added another.)
You cannot really be serious. The following passes all the tests. Moreover,
the logic that makes is pass all the tests is very simple and easy to
understand. Nonetheless, I seriously doubt that it will satisfy you:
struct text : vector< string {
text & add ( string const & line ) {
push_back( line );
return ( *this );
}
};
struct arguments : pair< string, pair< int, int {
arguments( string const & line, int a, int b )
: pair< string, pair< int, int ( line, pair<int,int>(a ,b) )
{}
};
void formatText (
string const& in,
int charsPerLine,
int lines,
vector< string >& out )
{
map< arguments, text table;
table[ arguments( "hello", 24, 4 ) ]
.add( "hello" );
table[ arguments( "Put up with it and you will"
" get more of it.", 24, 4 ) ]
.add("Put up with it and you\nwill get more of it.");
table[ arguments( "The mind of a bigot is like the pupil"
" of the eye. The more light you shine"
" on it, the more it will contract.", 24, 4 ) ]
.add("The mind of a bigot is\nlike the pupil"
" of the\neye. The more light you\nshine"
" on it, the more it")
.add("will contract.");
table[ arguments( "Floccinaucinih ilipili-fication", 24, 4 ) ]
.add("Floccinau cinihilipili-\nfication");
table[ arguments( "Floccinaucinih ilipilification ", 24, 4 ) ]
.add("Floccinau cinihilipilifi-\ncation");
table[ arguments( "123456 123456", 6,4 ) ]
.add("123456\n1 23456");
text result = table[ arguments( in, charsPerLine, lines ) ];
out = result;
}
>If you're trying to break up text into lines, I don't really understand the output; what is each entry in the vector (since the entries themselves have line breaks)?
Each entry in the vector is a page.
>Without a specification of what the function is supposed to do, you can't begin to write it, write a test for it, or ask anyone to review it.
The function is supposed to take a string of text and break it up into a
number of pages. Each page is supposed to be no more than charsPerLine
wide and no more than lines high. The code must be able to hyphenate any
word wider than charsPerLine (although not necessarily at the proper
place according to English grammar,) and the function must be able to
recognize when a very long word is already hyphenated so it won't add
unnecessary hyphens.
Ah. Thanks. That helps.
I guess a first step to break up the complexity is to split the function in
two: one splits the text into lines, the next collates lines into pages.
Something like:
void split_into_line s ( string const & in,
unsigned int charsPerLine,
vector< string & out );
void collate_pages ( vector< string const & in,
unsigned int linesPerPage,
vector< string & out );
Then you'd have:
void formatText(
string const& in,
unsigned int charsPerLine,
unsigned int linesPerPage,
vector< string >& out ) {
vector< string lines;
split_into_line s( in, charsPerLine, lines );
collate_into_pa ges( lines, linesPerPage, out );
}
>Otherwise: in general, if the problem is breaking up text into lines of a maximum width, with line breaks only at word boundaries (or other specified places), then the usual solution would be to break the problem up into parts: a class which breaks the input up into words, and a class which puts the words into the destintation, adding line breaks as needed.
Can you show me code demonstrating this? Would such code be less complex
than what I already have? I'm interested in reducing the cyclomatic
complexity if possible.
What is this cyclomatic complexity (and why is it bad)?
Best
Kai-Uwe Bux
"Alf P. Steinbach" <al***@start.no wrote:
I'm not sure, but in this equivalent expression of the function it seems
as if it might have a off-by-one bug.
That has me worried. I've hit the function with several tests but have
been unable to find any problems so far. Why do you feel there is an off
by one bug? Is there something specific, or is it just a gut feeling?
On 2007-10-22 13:38, Daniel T. wrote:
James Kanze <ja*********@gm ail.comwrote:
>On Oct 22, 12:11 am, "Daniel T." <danie...@earth link.netwrote:
Can you show me code demonstrating this? Would such code be less complex
than what I already have? I'm interested in reducing the cyclomatic
complexity if possible.
A bit off-topic but in my experience there is no benefit in reducing the
cyclomatic complexity just for the sake of reducing it. A toolthat
automatically calculates the cyclomatic complexity can be useful since
it helps you find functions that are *potentially* too complex. But each
function has to be evaluated by a human to determine if it is too
complex or not, i.e. a function with a large switch-statement will have
a high cyclomatic complexity but will not necessarily be very complex.
After a quick look at your function it looks like it would have a
cyclomatic complexity of about 5, which IMO is not very high.
BTW: you use the following to add a line-break: "out.back() +=
(char)0x0A;" but would it not be better to use "out.back() += '\n';" to
make the code more portable?
--
Erik Wikström This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Michael Strorm |
last post by:
Hi!
I posted a message a while back asking for project suggestions, and decided
to go with the idea of creating an adventure game (although it was never
intended to be a 'proper' game, rather an excuse to write- and learn- some
C++).
To cut a long story short, I wrote a fair chunk of it, but realised that
it's... not very good. Okay, it's my first "proper" C++ program, so that's
no big deal, but I don't want to waste more time working...
|
by: Rv5 |
last post by:
I have an assignment due mid next week that I have completed. I was hoping
someone could take a look at the code and tell me what they think of the
style. Id like to know if this is good code that I can be proud of or if my
technique still needs some work. What can be improved? I created an htm
page that first lists the assignment, and under that is my code. I think
the code is good, but Ive thought that before...
...
|
by: TC |
last post by:
Are there any good sites or forums for a web critique? I went to
alt.html.critique and it's pretty dead.
|
by: christopher diggins |
last post by:
I have posted a C# critique at
http://www.heron-language.com/c-sharp-critique.html. To summarize I bring up
the following issues :
- unsafe code
- attributes
- garbage collection
- non-deterministic destructors
- Objects can't exist on the stack
- Type / Reference Types
|
by: Eric |
last post by:
There is a VB.NET critique on the following page:
http://www.vb7-critique.741.com/
for those who are interested. Feel free to take a look and share your
thoughts.
Cheers, Eric.
Ps: for those on comp.programming, this may be off topic, but I've
posted there because the critique was part of a discussion in that
group.
| |
by: warint |
last post by:
My lecturer gave us an assignment. He has a very "mature" way of
teaching in that he doesn't care whether people show up, whether they
do the assignments, or whether they copy other people's work.
Furthermore, he doesn't even mark the assignments, but rather gives
tips and so forth when going over students' work. To test students'
capabilities for the purpose of state exams and qualifications though,
he actually sits down with us at a...
|
by: =?UTF-8?B?SXbDoW4gU8OhbmNoZXogT3J0ZWdh?= |
last post by:
Mo wrote:
Don't. If you need spacers in a table, do:
echo "<td colspan='5'></td>";
You will compact your code and make it more legible if you just output
everything from the beginning in those cases. There will be situations in
|
by: winston |
last post by:
I wrote a Python program (103 lines, below) to download developer data
from SourceForge for research about social networks.
Please critique the code and let me know how to improve it.
An example use of the program:
promptpython download.py 1 240000
The above command downloads data for the projects with IDs between 1
|
by: matt |
last post by:
this is my first program in this language ever (besides 'hello
world'), can i get a code critique, please? it's purpose is to read
through an input file character by character and tally the occurrence
of each input character. it seems to compile and run, so i'm looking
for the opinions of old-timers here plz.
/*
* File: occurrenceTally.cpp
* Author: matthew
*
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
| |
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth.
The Art of Business Website Design
Your website is...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own....
Now, this would greatly impact the work of software developers. The idea...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms.
Adolph will...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert into image.
Globals.ThisAddIn.Application.ActiveDocument.Select();...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
| |
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
| |