Is there a pretty solution of a GetPositionAtOffset() equivalent which only counts text insertion positions instead of all symbols?
Motivation example in C#:
TextRange GetRange(RichTextBox rtb, int startIndex, int length) {
TextPointer startPointer = rtb.Document.ContentStart.GetPositionAtOffset(startIndex);
TextPointer endPointer = startPointer.GetPositionAtOffset(length);
return new TextRange(startPointer, endPointer);
}
Edit: Until now i "solved" it this way
public static TextPointer GetInsertionPositionAtOffset(this TextPointer position, int offset, LogicalDirection direction)
{
if (!position.IsAtInsertionPosition) position = position.GetNextInsertionPosition(direction);
while (offset > 0 && position != null)
{
position = position.GetNextInsertionPosition(direction);
offset--;
if (Environment.NewLine.Length == 2 && position != null && position.IsAtLineStartPosition) offset --;
}
return position;
}
As far as I'm aware, there isn't. My suggestion is that you create your own GetPositionAtOffset method for this purpose. You can check which PointerContext the TextPointer is adjacent to by using:
TextPointer.GetPointerContext(LogicalDirection);
To get the next TextPointer which points to a different PointerContext:
TextPointer.GetNextContextPosition(LogicalDirection);
Some sample code I used in a recent project, this makes sure that the pointer context is of type Text, by looping until one is found. You could use this in your implementation and skip an offset increment if it is found:
// for a TextPointer start
while (start.GetPointerContext(LogicalDirection.Forward)
!= TextPointerContext.Text)
{
start = start.GetNextContextPosition(LogicalDirection.Forward);
if (start == null) return;
}
Hopefully you can make use of this information.
Could not find effective solution to this problem for a long time.
Next piece of code works in my case with the highest performance. Hope it will help somebody as well.
TextPointer startPos = rtb.Document.ContentStart.GetPositionAtOffset(searchWordIndex, LogicalDirection.Forward);
startPos = startPos.CorrectPosition(searchWord, FindDialog.IsCaseSensitive);
if (startPos != null)
{
TextPointer endPos = startPos.GetPositionAtOffset(textLength, LogicalDirection.Forward);
if (endPos != null)
{
rtb.Selection.Select(startPos, endPos);
}
}
public static TextPointer CorrectPosition(this TextPointer position, string word, bool caseSensitive)
{
TextPointer start = null;
while (position != null)
{
if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
{
string textRun = position.GetTextInRun(LogicalDirection.Forward);
int indexInRun = textRun.IndexOf(word, caseSensitive ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase);
if (indexInRun >= 0)
{
start = position.GetPositionAtOffset(indexInRun);
break;
}
}
position = position.GetNextContextPosition(LogicalDirection.Forward);
}
return start; }
Related
We are merging a Word template document that contains merge fields using Gembox Document. We noticed when some of the field values contain special characters \t or \n, an exception occurs...
An error occured - Text cannot contain new line (' '), carriage return
(' ') or tab (' ') characters. If you want to break the text or insert
a tab, insert SpecialCharacter instance with specific
SpecialCharacterType to the parent's InlineCollection.
We found this post which describes a solution to the issue, but we are not seeing how to apply that to our scenario.
This is our code which throws the exception...
public static void Merge(DocumentModel word, PricingSummaryModel model)
{
word.MailMerge.FieldMerging += (sender, e) =>
{
if (e.FieldName.Contains("CustomField."))
{
var trove = FindCustomFieldValueTrove(e.FieldName, model);
var value = ProcessCustomField(e.FieldName, e.Field.GetInstructionText(), trove);
e.Inline = new Run(e.Document, value) { CharacterFormat = e.Field.CharacterFormat.Clone() };
e.Cancel = false;
}
};
word.MailMerge.Execute(model);
}
We can fix the problem by removing any special characters first...
But then we lose the special characters of course. For our scenario, how can this be done? We aren't "constructing" a document as referenced in the aforementioned post. Rather we are starting with a Word template and essentially mail merging field values for the fields.
You'll need to handle those special characters and add the appropriate element(s) to the e.Inlines collection.
For example, try this:
var value = ProcessCustomField(e.FieldName, e.Field.GetInstructionText(), trove);
int startIndex = 0, currentIndex = 0, length = value.Length;
for (; currentIndex < length; currentIndex++)
{
char c = value[currentIndex];
if (c == '\t' || c == '\n')
{
e.Inlines.Add(
new Run(e.Document, value.Substring(startIndex, currentIndex - startIndex))
{ CharacterFormat = e.Field.CharacterFormat.Clone() });
e.Inlines.Add(
new SpecialCharacter(e.Document, c == '\t' ? SpecialCharacterType.Tab : SpecialCharacterType.LineBreak)
{ CharacterFormat = e.Field.CharacterFormat.Clone() });
startIndex = currentIndex + 1;
}
else if (currentIndex == length - 1)
e.Inlines.Add(
new Run(e.Document, value.Substring(startIndex, currentIndex - startIndex + 1))
{ CharacterFormat = e.Field.CharacterFormat.Clone() });
}
e.Cancel = false;
as mentioned in the titled, my function doesn't end well. I am trying to do the following :
" Implement, with the DC method, a function which has this interface :
Returns the majority element of the given sequence if one such exists
PARAMETERS
sequence Valid pointer to an array of elements
sequenceLength Size of the array
*
RETURN
element A pointer to one element corresponding to the majority
element or NULL if no such element exists
const Element getMajElDC(const Element* const * sequence, size_t sequenceLength); "
Actually, I just tried to implement this solution : http://www.ece.northwestern.edu/~dda902/336/hw4-sol.pdf
And here's my way to do it :
const Element* getMajElDC(const Element* const * sequence, size_t,sequenceLength){
printf("1\n");
const Element* element_tmp_right;
const Element* element_tmp_left;
int occurence_left = 0;
int occurence_right = 0;
if (sequenceLength == 1)
return sequence[1];
int mid = (int)sequenceLength/2;
element_tmp_left = getMajElDC(sequence,mid);
if (sequenceLength%2 == 0)
element_tmp_right = getMajElDC(&sequence[mid],mid);
element_tmp_right = getMajElDC(&sequence[mid],mid+1);
if (element_tmp_left == NULL && element_tmp_right != NULL)
return element_tmp_right;
if (element_tmp_right == NULL && element_tmp_left != NULL)
return element_tmp_left;
if (element_tmp_right == NULL && element_tmp_left == NULL)
return NULL;
if (areEqual(element_tmp_left,element_tmp_right))
return element_tmp_left;
for (int i=0;i<sequenceLength;i++){
if( areEqual(sequence[i],element_tmp_left))
occurence_left++;
if (areEqual(sequence[i],element_tmp_right))
occurence_right++;
}
if (occurence_left > mid+1)
return element_tmp_left;
else if (occurence_left > mid+1)
return element_tmp_left;
else
return NULL;
}
When I try to run it in codeblocks, the .exe just stopworking. Just like if the function was endless. That's why I placed a printf in the beginning : I wanted to see how many times the " 1 " would appear in the application windows and it appears so many times that everything goes crazy.
I tried to look into the base case of the recursion, but nothing seems wrong with it...
I am truly lost my poor knowledge of C, does anyone see where the problem is ?
Ps : the areEqual() function is just a given function, here's its implementation but there is nothing special with it :
bool areEqual(const Element* a, const Element* b)
{
return a->value == b->value;
}
with
struct element_t
{
int value;
};
typedef struct element_t Element;
To end my question, I tell you in advance that I'm sorry if a crucial information is missing : It is the first time I use this website, please be indulgent !
You have to use debugger it will show you immediately where the problem is.
BTW look closer this code:
if (sequenceLength == 1)
return sequence[1];
int mid = (int)sequenceLength/2;
element_tmp_left = getMajElDC(sequence,mid);
if (sequenceLength%2 == 0)
element_tmp_right = getMajElDC(&sequence[mid],mid);
element_tmp_right = getMajElDC(&sequence[mid],mid+1);
You close the recursion when sequenceLength == 1, but if getMajElDC has been called with sequenceLength=0 it will never return.
Consider to modify:
if (sequenceLength == 1)
return sequence[1];
to:
if (sequenceLength <= 1)
return sequence[1];
consider this code snippet:
int mid = (int)sequenceLength/2;
element_tmp_left = getMajElDC(sequence,mid);
if (sequenceLength%2 == 0)
element_tmp_right = getMajElDC(&sequence[mid],mid);
element_tmp_right = getMajElDC(&sequence[mid],mid+1);
notice that the third call to getMajElDC is always called regardless of the value of sequenceLength. I suspect that you wanted to write this:
if (sequenceLength%2 == 0)
element_tmp_right = getMajElDC(&sequence[mid],mid);
else
element_tmp_right = getMajElDC(&sequence[mid],mid+1);
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
The title is pretty explicit and below are couple of samples input/output. Note that the regexps used are supposed to match from beginning to end of the string.
'abc' =~ 'abc' (match)
'abc' =~ 'a*bc' (match)
'aaaaaaabc' =~ 'c*bc' (no match)
'aaaaaaabc' =~ 'a.*bc' (match)
'abbbbaaaaaabc' =~ 'ab*a*b*c' (match)
'abbbbaaaaaabc' =~ 'ab*a*h*bc' (match)
'bbd' =~ 'b*bbd' (match)
'bbd' =~ '.*bbd' (match)
'bbd' =~ '.*cbd' (no match)
'' =~ '.*' (match)
My implementation for this is located at:
https://github.com/jpbillaud/piexposed/blob/master/string/string_match_regexp.c
Now I was wondering if anybody would think about a more interesting way to solve this using DP, Finite Automata or whatever else.
Take a look at this implementation of a regular expression matcher by Rob Pike, taken from the book The Practice of Programming. It's absolutely beautiful code, in just 35 lines of C it happens to meet all the requirements in the question (and a bit more!). Quoting from the article referenced above:
/* match: search for regexp anywhere in text */
int match(char *regexp, char *text)
{
if (regexp[0] == '^')
return matchhere(regexp+1, text);
do { /* must look even if string is empty */
if (matchhere(regexp, text))
return 1;
} while (*text++ != '\0');
return 0;
}
/* matchhere: search for regexp at beginning of text */
int matchhere(char *regexp, char *text)
{
if (regexp[0] == '\0')
return 1;
if (regexp[1] == '*')
return matchstar(regexp[0], regexp+2, text);
if (regexp[0] == '$' && regexp[1] == '\0')
return *text == '\0';
if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
return matchhere(regexp+1, text+1);
return 0;
}
/* matchstar: search for c*regexp at beginning of text */
int matchstar(int c, char *regexp, char *text)
{
do { /* a * matches zero or more instances */
if (matchhere(regexp, text))
return 1;
} while (*text != '\0' && (*text++ == c || c == '.'));
return 0;
}
I've never tried to write a regex before, so I figured I'd give it a shot. I elided some of the boring stuff. Here's my (completely untested or compiled) version:
class Regex {
public:
Regex(const string& pattern) {
// Sanity check pattern:
if ((!pattern.empty() && pattern[0] == '*') ||
adjacent_find(pattern.begin(), pattern.end(), both_are_repeats) != pattern.end()) {
// throw exception
}
for (string::const_iterator curr(pattern.begin()), end(pattern.end()); curr != end; ) {
char current_match = *curr;
++curr;
// Fold any number of the following characters that are current_match or '*' into
// a single Node.
int stars = 0, count = 1;
for (; curr != end; ++curr) {
if (*curr == current_match) {
++count;
} else if (*curr == '*') {
++stars;
} else {
break;
}
}
rewritten_pattern_.push_back(Node(current_match, count - stars, stars > 0));
}
}
// We could do this iteratively and avoid a stack overflow, but the recursion solution is
// a lot easier to write, so it's good enough for SO :)
bool matches(const string& value) const {
return matches_internal(value.begin(), value.end(), rewritten_pattern_.begin(), rewritten_pattern_.end());
}
private:
static bool matches_internal(string::const_iterator value_curr,
string::const_iterator value_end,
vector<Node>::const_iterator pattern_curr,
vector<Node>::const_iterator pattern_end) {
for (; pattern_curr != pattern_end; ++pattern_curr) {
// For each pattern Node, we first verify that the required count of letters is there,
// then we handle the repeats, if specified. After this section, value_curr should
// be advanced past the required elements of the Node.
if (distance(value_curr, value_end) < pattern_curr->count) return false;
string::const_iterator current_pattern_count_end = value_curr;
advance(current_pattern_count_end, pattern_curr->count);
if (pattern_curr->value == '.') {
value_curr = current_pattern_count_end;
} else {
for (; value_curr != current_pattern_count_end; ++value_curr) {
if (*value_curr != pattern_curr->value) {
return false;
}
}
}
// We've handled the required charaters, now handle the repeats, if any:
if (pattern_curr->repeats) {
if (pattern_curr->value == '.') {
// Here's the tricky case that will have to involve some backtracking. We aren't sure
// how much of the string the .* should consume, we have to try all potential positions
// and only match if any position matches. Since most regex impls are greedy
// by default, we'll start potentially matching the whole string and move our way backward.
++pattern_curr;
for (string::const_iterator wildcard_match_end = value_end;
wildcard_match_end != value_curr;
--wildcard_match_end) {
if (matches_internal(wildcard_match_end, value_end, pattern_curr, pattern_end)) {
return true;
}
}
return false;
} else {
// If this isn't a wildcard, we can just consume all of the same value.
for (; value_curr != value_end && *value_curr == pattern_curr->value; ++value_curr) {}
}
}
}
// After all the patterns are consumed, we only match if we have consumed the value also.
return value_curr == value_end;
}
static bool both_are_repeats(char i, char j) {
return i == '*' && j == '*';
}
struct Node {
// put constructor and copy constructor here
char value;
int count;
bool repeats;
}
vector<Node> rewritten_pattern_;
};
I was trying to add new row to my database table and it seams that everything is going well in the application WPF and when i close the application the database has not changed(new record was not added in the database ) I tried to use dataadapters so here is my class that i use and the code behing
DD.cs
namespace WpfApplication2
{
class DD
{
private Database1DataSetTableAdapters.Table1TableAdapter _cpuAdapter = null;
protected Database1DataSetTableAdapters.Table1TableAdapter Adapter
{
get
{
if (_cpuAdapter == null)
_cpuAdapter = new Database1DataSetTableAdapters.Table1TableAdapter();
return _cpuAdapter;
}
}
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Insert, true)]
public bool AddCPU(string Naslov, string Avtor, string Lokacija, int Broj, string
Zabeleska, string Izdava)
{
Database1DataSet.Table1DataTable cpus = new Database1DataSet.Table1DataTable();
Database1DataSet.Table1Row cpu = cpus.NewTable1Row();
cpu.Naslov = Naslov;
if (Naslov == null) cpu.SetNaslovNull();
else cpu.Naslov = Naslov;
if (Avtor == null) cpu.SetAvtorNull();
else cpu.Avtor = Avtor;
if (Zabeleska == null) cpu.SetZabeleskaNull();
else cpu.Zabeleska = Zabeleska;
if (Izdava == null) cpu.SetIzdavaNull();
else cpu.Izdava = Izdava;
if (Broj == null) cpu.SetBrojNull();
else cpu.Broj = Broj;
if (Lokacija == null) cpu.SetLokacijaNull();
else cpu.Lokacija = Lokacija;
cpus.AddTable1Row(cpu);
int rowsAffected = Adapter.Update(cpus);
// Return true if precisely one row was inserted, otherwise false
return rowsAffected == 1;
}
HERE IS THE CODE BEHIND
it's an event on button click
string n, a, z,t,l;
int b;
l = txtLokacija.Text;
t = txtBroj.Text;
b = Convert.ToInt32(t);
n = txtNaslov.Text;
a = txtAvtor.Text;
z = txtZabeleska.Text;
t = "NONE";
txtZabeleska.Clear();
DD obj1=new DD();
obj1.AddCPU(n,a,l,b,z,t);
I found IT....when i finished the application and published then it seemed everything ok the database was working properly..i;ve restarted the PC and the newly added record
Basically I'm creating an indoor navigation system in J2ME. I've put the location details in a .txt file i.e.
Locations names and their coordinates.
Edges with respective start node and end node as well as the weight (length of the node).
I put both details in the same file so users dont have to download multiple files to get their map working (it could become time consuming and seem complex).
So what i did is to seperate the deferent details by typing out location Names and coordinates first, After that I seperated that section from the next section which is the edges by drawing a line with multiple underscores.
Now the problem I'm having is parsing the different details into seperate arrays by setting up a command (while manually tokenizing the input stream) to check wether the the next token is an underscore.
If it is, (in pseudocode terms), move to the next line in the stream, create a new array and fill it up with the next set of details.
I found a some explanation/code HERE that does something similar but still parses into one array, although it manually tokenizes the input. Any ideas on what to do? Thanks
Text File Explanation
The text has the following format...
<--1stSection-->
/**
* Section one has the following format
* xCoordinate;yCoordinate;LocationName
*/
12;13;New York City
40;12;Washington D.C.
...e.t.c
_________________________ <--(underscore divider)
<--2ndSection-->
/**
* Its actually an adjacency list but indirectly provides "edge" details.
* Its in this form
* StartNode/MainReferencePoint;Endnode1;distance2endNode1;Endnode2;distance2endNode2;...e.t.c
*/
philadelphia;Washington D.C.;7;New York City;2
New York City;Florida;24;Illinois;71
...e.t.c
package filereader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.Vector;
public class FileReader {
String locationSection;
String edgeSection;
Vector locations;
Vector edges;
public FileReader(String fileName) {
// read the contents into the string
InputStream is = getClass().getResourceAsStream(fileName);
StringBuffer sb = new StringBuffer();
int ch;
try {
while ((ch = is.read()) != -1) {
sb.append((char) ch);
}
} catch (IOException e2) {
e2.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
String text = sb.toString();
// separate locations and edges
String separator = "_________________________";
// read location section, without last end-of-line char
int endLocationSection = text.indexOf(separator) - 1;
locationSection = text.substring(0, endLocationSection);
// read edges section, without end-of-line char after separator
int startEdgeSection = endLocationSection + separator.length() + 3;
edgeSection = text.substring(startEdgeSection, text.length());
// parse locations and edges
locations = getLocationsVector(locationSection);
edges = getEdgesVector(edgeSection);
}
// parse locations section
public Vector getLocationsVector(String section) {
Vector result = new Vector();
int startLine = 0;
int endLine = section.indexOf('\n');
while (endLine != -1) {
String line = section.substring(startLine, endLine);
result.addElement(parseLocationsLine(line, ';'));
startLine = endLine + 1;
if (endLine == section.length() - 1)
break;
endLine = section.indexOf('\n', startLine);
// if no new line found, read to the end of string
endLine = (-1 == endLine) ? section.length() - 1 : endLine;
}
return result;
}
// parse edges section
public Vector getEdgesVector(String section) {
Vector result = new Vector();
int startLine = 0;
int endLine = section.indexOf('\n');
while (endLine != -1) {
String line = section.substring(startLine, endLine - 1);
result.addElement(parseEdgesLine(line, ';'));
startLine = endLine + 1;
if (endLine == section.length() + 1)
break;
endLine = section.indexOf('\n', startLine);
// if no new line found, read to the end of string
endLine = (-1 == endLine) ? section.length() + 1 : endLine;
}
return result;
}
// parse locations line
public Hashtable parseLocationsLine(String value, char splitBy) {
Hashtable result = new Hashtable();
int xCEnd = value.indexOf(splitBy);
int yCEnd = value.indexOf(splitBy, xCEnd + 1);
result.put("x", value.substring(0, xCEnd));
result.put("y", value.substring(xCEnd + 1, yCEnd));
result.put("location", value.substring(yCEnd + 1,
value.length() - 1));
return result;
}
// parse edges line
public Hashtable parseEdgesLine(String value, char splitBy) {
Hashtable result = new Hashtable();
int snEnd = value.indexOf(splitBy);
result.put("startnode", value.substring(0, snEnd));
int n = 1;
int start = snEnd + 1;
int enEnd = value.indexOf(splitBy, snEnd + 1);
int dstEnd = value.indexOf(splitBy, enEnd + 1);
while (enEnd != -1 && dstEnd != -1) {
result.put("endnode" + String.valueOf(n),
value.substring(start, enEnd));
result.put("distance" + String.valueOf(n), value.substring(
enEnd + 1, dstEnd));
start = dstEnd + 1;
enEnd = value.indexOf(splitBy, start);
if (dstEnd == value.length())
break;
dstEnd = value.indexOf(splitBy, enEnd + 1);
// if last endnode-distance pair, read to the end of line
dstEnd = (-1 == dstEnd) ? value.length() : dstEnd;
n++;
}
return result;
}
// getters for locations and edges
public Vector getLocations() {
return locations;
}
public Vector getEdges() {
return edges;
}
}
and somewhere in application screen:
fr = new FileReader("/map.txt");
Vector vct1 = fr.getLocations();
for (int i = 0; i < vct1.size(); i++) {
Hashtable location = (Hashtable) vct1.elementAt(i);
Enumeration en = location.keys();
String fv = "";
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
String value = (String)location.get(key);
fv = fv + value + "-";
}
this.add(new LabelField(fv));
}
Vector vct2 = fr.getEdges();
for (int i = 0; i < vct2.size(); i++) {
Hashtable location = (Hashtable) vct2.elementAt(i);
Enumeration en = location.keys();
String fv = "";
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
String value = (String)location.get(key);
fv = fv + value + "-";
}
this.add(new LabelField(fv));
}
it will be easy to get values from hashtable by keys:
(String)location.get("x")
(String)location.get("y")
(String)location.get("location")
(String)edge.get("startnode")
(String)edge.get("endnode1")
(String)edge.get("distance1")
(String)edge.get("endnode2")
(String)edge.get("distance2")
...