Lo siento, mi C/C++ no es tan bueno, pero el siguiente código parece basura incluso para mí. También tiene un error: falla cuando str = "07/02/2010" termina por '\ 0' -. Creo que, en lugar de corregir un error, podría ser reescrito. En Python es solo 'kas\nhjkfh kjsdjkasf'.split()
. Sé que este es el código C-ish, ¡pero no puede ser tan complicado dividir una cadena! Manteniéndome en la misma firma, y sin utilizar bibliotecas adicionales, ¿cómo puedo mejorarlo, hacerlo corto y dulce? Puedo decir que este código huele, por ejemplo debido a la cláusula else todo el camino al final.Una mejor manera de dividir una cadena en una matriz de cadenas en C/C++ utilizando espacios en blanco como un delimitador
línea que falla:
_tcsncpy_s(
s.GetBuffer((int) (nIndex-nLast)),
nIndex-nLast,
psz+nLast,
(size_t) (nIndex-nLast)
);
con la cadena "07/02/2010" terminado por '\ 0' que tratará de escribir 11 caracteres en una memoria intermedia que está a sólo 10 caracteres de longitud.
FUNCIÓN COMPLETA:
#define
// This will return the text string as a string array
// This function is called from SetControlText to parse the
// text string into an array of CStrings that the control
// Gadgets will attempt to interpret
BOOL CLVGridDateTimeCtrl::ParseTextWithCurrentFormat(const CString& str, const CGXStyle* pOldStyle, CStringArray& strArray)
{
// Unused:
pOldStyle;
// we assume that the significant segments are seperated by space
// Please change m_strDelim to add other delimiters
CString s;
LPCTSTR psz = (LPCTSTR) str;
BOOL bLastCharSpace = FALSE;
DWORD size = str.GetLength()+1;
// (newline will start a new row, tab delimiter will
// move to the next column).
// parse buffer (DBCS aware)
for (DWORD nIndex = 0, nLast = 0; nIndex < size; nIndex += _tclen(psz+nIndex))
{
// check for a delimiter
if (psz[nIndex] == _T('\0') || _tcschr(_T("\r\n"), psz[nIndex]) || _tcschr(_T(" "), psz[nIndex])
||!_tcscspn(&psz[nIndex], (LPCTSTR)m_strDelim))
{
s.ReleaseBuffer();
s.Empty();
// abort parsing the string if next char
// is an end-of-string
if (psz[nIndex] == _T('\0'))
{
if (psz[nIndex] == _T('\r') && psz[nIndex+1] == _T('\n'))
nIndex++;
_tcsncpy_s(s.GetBuffer((int) (nIndex-nLast)),
nIndex-nLast,
psz+nLast,
(size_t) (nIndex-nLast));
CString temStr = s;
strArray.Add(temStr);
temStr.Empty();
break;
}
else if (_tcscspn(&psz[nIndex], (LPCTSTR)m_strDelim) == 0 && !bLastCharSpace)
{
if (psz[nIndex] == _T('\r') && psz[nIndex+1] == _T('\n'))
nIndex++;
_tcsncpy_s(s.GetBuffer((int) (nIndex-nLast)),
nIndex-nLast,
psz+nLast,
(size_t) (nIndex-nLast));
CString temStr = s;
strArray.Add(temStr);
temStr.Empty();
bLastCharSpace = TRUE;
// abort parsing the string if next char
// is an end-of-string
if (psz[nIndex+1] == _T('\0'))
break;
}
// Now, that the value has been copied to the cell,
// let's check if we should jump to a new row.
else if (_tcschr(_T(" "), psz[nIndex]) && !bLastCharSpace)
{
if (psz[nIndex] == _T('\r') && psz[nIndex+1] == _T('\n'))
nIndex++;
_tcsncpy_s(s.GetBuffer((int) (nIndex-nLast)),
nIndex-nLast,
psz+nLast,
(size_t) (nIndex-nLast));
CString temStr = s;
strArray.Add(temStr);
temStr.Empty();
bLastCharSpace = TRUE;
// abort parsing the string if next char
// is an end-of-string
if (psz[nIndex+1] == _T('\0'))
break;
}
nLast = nIndex + _tclen(psz+nIndex);
}
else
{
// nLast = nIndex + _tclen(psz+nIndex);
bLastCharSpace = FALSE;
}
}
if (strArray.GetSize())
return TRUE;
else
return FALSE;
}
EDIT: m_strDelim = _T(",");
y esta variable miembro se utiliza sólo en esta función. Supongo que ahora veo el punto de la tokenización: trata de analizar una fecha y una hora ... ¡Espera, hay más! Aquí está el código que llama a esta función a continuación. Por favor, ayúdame a mejorar esto también. Algunos de mis colegas afirman que C# los hace no más productivos que C++. Solía sentirme como un idiota por no poder decir lo mismo de mí.
// SetControlText will attempt to convert the text to a valid date first with
// the help of COleDateTime and then with the help of the Date control and the
// current format
BOOL CLVGridDateTimeCtrl::ConvertControlTextToValue(CString& str, ROWCOL nRow, ROWCOL nCol, const CGXStyle* pOldStyle)
{
CGXStyle* pStyle = NULL;
BOOL bSuccess = FALSE;
if (pOldStyle == NULL)
{
pStyle = Grid()->CreateStyle();
Grid()->ComposeStyleRowCol(nRow, nCol, pStyle);
pOldStyle = pStyle;
}
// allow only valid input
{
// First do this
CLVDateTime dt;
if (str.IsEmpty())
{
;
// if (Grid()->IsCurrentCell(nRow, nCol))
// Reset();
bSuccess = TRUE;
}
else if (dt.ParseDateTime(str,CLVGlobals::IsUSDateFormat()) && (DATE) dt != 0)
{
SetDateTime(dt);
if (m_bDateValueAsNumber)
str.Format(_T("%g"), (DATE) dt);
else
str = dt.Format();
bSuccess = TRUE;
}
else
{
// parse the string using the current format
CStringArray strArray;
if (!ParseTextWithCurrentFormat(str, pOldStyle, strArray))
return FALSE;
UpdateNullStatus(m_TextCtrlWnd);
SetFormat(m_TextCtrlWnd, *pOldStyle);
int nArrIndex = 0;
for(int i=0; i<m_TextCtrlWnd.m_gadgets.GetSize(); i++)
{
int val = m_TextCtrlWnd.m_gadgets[i]->GetValue();
// s.Empty();
if(m_TextCtrlWnd.m_gadgets[i]->IsKindOf(RUNTIME_CLASS(SECDTNumericGadget)))
{
// TRACE(_T("The value %s\n"), strArray[nArrIndex]);
((CLVDTNumericGadget*)m_TextCtrlWnd.m_gadgets[i])->m_nNewValue = _ttoi(strArray[nArrIndex]);
nArrIndex++;
if (nArrIndex>strArray.GetUpperBound())
break;
}
else if(m_TextCtrlWnd.m_gadgets[i]->IsKindOf(RUNTIME_CLASS(SECDTListGadget)) && val!=-1)
{
int nIndex = ((CLVDTListGadget*)m_TextCtrlWnd.m_gadgets[i])->FindMatch(strArray[nArrIndex], ((CLVDTListGadget*)m_TextCtrlWnd.m_gadgets[i])->GetValue()+1);
if (nIndex!=-1)
{
// TRACE(_T("The value %s\n"), strArray[nArrIndex]);
((CLVDTListGadget*)m_TextCtrlWnd.m_gadgets[i])->SetValue(nIndex);
nArrIndex++;
if (nArrIndex>strArray.GetUpperBound())
break;
}
}
CLVDBValue dbDate = m_TextCtrlWnd.GetDateTime();
if (dbDate.IsNull())
str = _T("");
else
{
CLVDateTime dt = (CLVDateTime)dbDate;
if (m_bDateValueAsNumber)
str.Format(_T("%g"), (DATE) dt);
else
str = dt.Format();
}
}
bSuccess = TRUE;
}
}
if (pStyle)
Grid()->RecycleStyle(pStyle);
return bSuccess;
}
+1, pero estoy seguro de que alguien tendrá una loca solución de C++ que incluye una sintaxis bizarra para quitarte tus votos ganadores. –
Esta es una buena solución para C. Si desea usar C++, no hay nada "loco" en codificar las fortalezas del idioma. – Cogwheel
Si 'strtok' es la respuesta correcta, generalmente ha hecho una pregunta incorrecta. –