Dividere stringa

venerdì 28 novembre 2008 - 16.15

ilario Profilo | Senior Member

ciao

conoscete una funzione che mi divida una stringa in sub stringhe (array) con un numero max di caratteri, tenendo conto di non spezzare la parola

ciao e grazie
ilario

llamanna Profilo | Junior Member

Se ho capito bene il problema potresti usare la funzione
String.Split
Laura.
http://lauralamanna.blogspot.com/

freeteo Profilo | Guru

Ciao,
non so cosa tu intenda per "non spezzare la parola", se hai bisogno di una larghezza fissa probabilmente la parola la spezzi.

Ad ogni modo, potresti pensare ad usare una Regular Expression, che ti aiuta nella definizione di corrispondenze complesse nelle stringhe, ad esempio per la divisione in 3 pezzetti di una stringa il codice sarebbe questo:

Regex regex = new Regex(@"\w{3}",RegexOptions.Multiline); foreach (Match m in regex.Matches("strnga")) { ... }

poi ovviamente puoi affinare di più con la sintassi delle regex che permette cose veramente interessanti:
http://it.wikipedia.org/wiki/Regex
http://www.regular-expressions.info/
http://msdn.microsoft.com/en-us/library/6wzad2b2(VS.85).aspx


Ciao.

Matteo Raumer
[MVP Visual C#]
http://blogs.dotnethell.it/freeteo

ilario Profilo | Senior Member

ciao

mi serve questa funzione per poter spezzare una riga da stampare in più righe se la sua lunghezza eccede lo spazio
potrei risolvere con substring , ogni tot caratteri gli inserisco un newline , il problema è che non è bello spezzare la parola a caso e andare a capo
stavo studiando una funzione dove controlla se l'ultimo carattere è uno spazio e quindi spezza, altrimenti torna indietro riducendo il numero dei caratteri fino a che trovi lo spazio e li mando a capo

nel frattempo mi leggo anche i tuoi suggerimenti

grazie
ilario

ilario Profilo | Senior Member

ciao

la funzione split ti divide la stringa ma in base a un carattere, potrei utilizzare lo spazio, ma a questo punto mi da tante righe quante le parole nella stringa

grazie comunque

ilario


alexmed Profilo | Guru

Ciao

L'oggetto Graphics mette a disposizione una funzione che potrebbe fare al caso tuo:


Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Guardala un pò e fammi sapere.
Ciao

ilario Profilo | Senior Member

mi sono fatto questa piccola funzione

Private Function SistemaRiga(ByVal Testo As String, ByVal Maxcaratteri As String) As String
Dim StartPosition As Integer = 0

If Maxcaratteri < Testo.Length Then

While StartPosition + Maxcaratteri < Testo.Length

StartPosition = StartPosition + Maxcaratteri

' controllo se c'e uno spazio altrimenti indietreggio di un carattere finche non trovo uno spazio (inizio parola)
While Testo.Substring(StartPosition, 1) <> " " 'chr(32)

StartPosition -= 1

End While

Testo = Testo.Insert(StartPosition + 1, Environment.NewLine)


End While
SistemaRiga = Testo

Exit Function
End If

SistemaRiga = Testo

End Function

va benessimo, l'unica cosa è che se ho una parola più lunga del massimo del carattere si blocca
mi date un sugerimento su come rimediare

ciao ilario

Anonimo Profilo | Senior Member

Ho provato a scriverne una io

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Fammi sapere
Ciao!
Riccardo

ilario Profilo | Senior Member

ciao

avevo pensato anch'io al rettangolo,
ma purtroppo posso sapere solo la larghezza, non l'altezza

grazie comunque

ilario

ilario Profilo | Senior Member

ciao

ho provato la tua funzione , ma deve esserci qualche passaggio non corretto
(più tardi me la studio bene), perchè va altre il numero max di caratteri

ho fatto una prova così
3 textbox i un form di cui 2 multiline e un button

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
TextBox1.Text = "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco ..."

End Sub
Public Function InserisciNewLine(ByVal str As String, ByVal maxLen As Integer) As String
If maxLen > str.Length Then
Return str
Else
If Not str(maxLen - 1).Equals(" ") Then
Dim firstSpace As Integer = str.IndexOf(" ", maxLen - 1)
If firstSpace <> -1 Then
str = str.Insert(firstSpace, Environment.NewLine).Remove(firstSpace + 2, 1)
If str.Substring(firstSpace + 2).Length > maxLen Then
Return str.Substring(0, firstSpace + 2) + InserisciNewLine(str.Substring(firstSpace + 2), maxLen)
End If
End If
End If
Return str
End If
End Function


Private Function SistemaRiga(ByVal Testo As String, ByVal Maxcaratteri As String) As String
Dim StartPosition As Integer = 0

If Maxcaratteri < Testo.Length Then

While StartPosition + Maxcaratteri < Testo.Length

StartPosition = StartPosition + Maxcaratteri

' controllo se c'e uno spazio altrimenti indietreggio di un carattere finche non trovo uno spazio (inizio parola)
While Testo.Substring(StartPosition, 1) <> " " 'chr(32)

StartPosition -= 1

End While

Testo = Testo.Insert(StartPosition + 1, Environment.NewLine)


End While
SistemaRiga = Testo

Exit Function
End If

SistemaRiga = Testo

End Function

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
TextBox2.Text = InserisciNewLine(TextBox1.Text, 25)
TextBox3.Text = SistemaRiga(TextBox1.Text, 25)
End Sub

come noterai la mia (textbox3) si ferma prima del 25 carattere la tua va oltre
comunque me la studio e vedo se riesco a prendere spunto

grazie mille

ilario

Anonimo Profilo | Senior Member

>stavo studiando una funzione dove controlla se l'ultimo carattere
>è uno spazio e quindi spezza, altrimenti torna indietro riducendo
>il numero dei caratteri fino a che trovi lo spazio e li mando
>a capo

Ah ecco perchè: la mia scorre in avanti fino a quando trova lo spazio mentre la tua scorre indietro.. vabè possono tornare utili entrambe a seconda dei casi
Ho modificato la tua e sembrerebbe che non dia più errore, in effetti entrava in un ciclo infinito, provala per bene:

Private Function SistemaRiga(ByVal Testo As String, ByVal Maxcaratteri As Integer) As String Dim StartPosition As Integer = 0 If Maxcaratteri < Testo.Length Then While StartPosition + Maxcaratteri < Testo.Length StartPosition = StartPosition + Maxcaratteri While StartPosition > -1 AndAlso Testo.Substring(StartPosition, 1) <> " " StartPosition -= 1 End While If StartPosition = -1 Then Return Testo End If Testo = Testo.Insert(StartPosition + 1, Environment.NewLine) End While Return Testo End If Return Testo End Function

Ciao!
Riccardo

alexmed Profilo | Guru

Ciao
Fermo restando che approvo il lavoro che state facendo, ovvero sperimentare nuove strade, io ho seguito quella del rettangolo risolvendo il problema relativo all'incognita dell'altezza.

Questo è quello che ho partorito:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Per quello che l'ho testata sembrerebbe funzionare.
Ciao

ilario Profilo | Senior Member

purtroppo va in errore se la lunghezza della parola supera il limite del maxcaratteri si blocca

nell'esempio prova a sostituire la stringa con questa

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut laboreetdoloremagnaaliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco ...

ho semplicemente tolto degli spazi per far allungare oltre 1 25 caratteri una parola


con la modifica che mi hai fatto

If StartPosition = -1 Then
Return Testo
End If

prima di arrivare all'inizio della stringa uno spazio lo trova
quindi va in errore

dovrei riuscire a dirgli che se i rientri di un carattere ( startposition-1) superano il maxcaratteri (in questo caso 25) si deve bloccare e la startposition deve ritornare startposition + maxcaratteri, in modo tale da spezzare la parola a metà

spero di essermi riuscito a spiegare

ciao
ilario


ilario Profilo | Senior Member

l'ho provata ed effettivamente funziona bene

devrò trasformarla in una funzione che mi restituisca le misure del rettangolo e il nr di linee in esso contenute

poi ti faccio sapere nel frattempo ti ringrazio

in ogni caso voglio riuscire a farla anche nell'altro modo, perchè funziona, l'unica è che se trova una parola più lunga del numero max dei caratteri va in tilt

ciao
ilario


alexmed Profilo | Guru

Ciao di nuovo
Ho dato ancora uno sguardo alla vostra soluzione ed ho notato solo adesso che lavorate sulla Text.Length
Ma quardiamo queste coppie di stringhe:

iiiiiiiiii
oooooooooo

alessandro
ALESSANDRO

Sono composte tutte e due dallo stesso numero di caratteri ma hanno lunghezza diversa.
Quindi la vostra funzione funziona solo se viene utilizzato un carattere monospace (Courier New) e non varia la dimensione del carattere.

Per quanto riguarda il numero max di caratteri guarda qui.
http://it.wikipedia.org/wiki/Precipitevolissimevolmente
Ciao

ilario Profilo | Senior Member

ciao Alessandro

<Ho dato ancora uno sguardo alla vostra soluzione ed ho notato solo adesso che lavorate sulla Text.Length

guardando la tua soluzione mi ero accorto di questo difetto, infatti stavo studiando la tua per trasformarla in una funzione che mi ritorni un rettangolo o l'altezza e il numero di linee devo ancora decidere

grazie ancora
ilario

ilario Profilo | Senior Member

ciao Alessandro

per il mio scopo ho utilizzato il tuo codice per fare questa funzione e funziona molto bene

la funzione mi restituisce il nr delle linee del testo, così aumento poi la posizione y per le righe successive

Public Function StampaTesto(ByVal Testo As String, ByVal LarghezzaRettangolo As Integer, ByVal Carattere As Font, ByVal Colore As SolidBrush, ByVal Allineamento As StringFormat, ByVal PosizioneX As Integer, ByVal PosizioneY As Integer, ByVal e As System.Drawing.Printing.PrintPageEventArgs) As Integer

Dim split_string() As String = Testo.Split(" ")

'Misuro la lunghezza della stringa da stampare
Dim string_size As SizeF = e.Graphics.MeasureString(Testo, Carattere)



'Verifico che non ci siano parole più lunghe della larghezza del rettangolo.
'In caso affermativo aggiungo una linea
Dim count As Integer = 1
For i As Integer = 0 To split_string.GetUpperBound(0)
Dim string_size_split As SizeF = e.Graphics.MeasureString(split_string(i), Carattere)
If string_size_split.Width > LarghezzaRettangolo Then
count += 1
End If
Next

'Calcolo l'altezza del rettangolo
'Dividendo la lunghezza della stringa per la larghezza del rettangolo in pratica ottengo il numero di righe
Dim numLine As Integer = Math.Ceiling((string_size.Width / LarghezzaRettangolo)) + count
'Moltiplico il numero di linee per l'altezza del carattere
Dim AltezzaRettangolo As Integer = numLine * Carattere.Height

'crea il rettangolo di stampa
Dim rettangolo As New RectangleF(PosizioneX, PosizioneY, LarghezzaRettangolo, AltezzaRettangolo)


'stampa il testo
e.Graphics.DrawString(Testo, Carattere, Colore, rettangolo, Allineamento)


Return numLine

End Function


grazie mille, alla prossima

ilario

alexmed Profilo | Guru

Ciao
>grazie mille, alla prossima
alla prossima!

ilario Profilo | Senior Member

mi togli solo una curiosità

se la funzione la provo su paint di un form con Dim count As Integer = 1 il numero delle linea è corretto,


se la provo con ByVal e As System.Drawing.Printing.PrintPageEventArgs il numero è maggiore di 1 e devo inserire Dim count As Integer = 0

è possibile o sbaglio qualcosa


Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5