इस प्रश्न के दो मुद्दे हैं स्मृति प्रबंधन और थ्रेड सुरक्षा। जैसा कि आप कई पदों से देख सकते हैं, सी में मूल रूप से पूरा करने के लिए यह एक आसान काम नहीं है। मैं एक समाधान चाहता हूं जो है:
- सुरक्षित धागा। (strtok धागा सुरक्षित नहीं है)
- मॉलॉक या इसके किसी भी डेरिवेटिव को नियुक्त नहीं करता है (स्मृति प्रबंधन मुद्दों से बचने के लिए)
- अलग-अलग फ़ील्ड्स पर चेक बाउंड्स चेक करता है (अज्ञात डेटा पर खंड दोष से बचने के लिए)
- मल्टी-बाइट फ़ील्ड विभाजकों के साथ काम करता है (utf-8)
- इनपुट में अतिरिक्त फ़ील्ड को अनदेखा करता है
- अमान्य फ़ील्ड लंबाई के लिए नरम त्रुटि दिनचर्या प्रदान करता है
समाधान मैं आया इन सभी मानदंडों को पूरा करता है। यहां पोस्ट किए गए कुछ अन्य समाधानों की तुलना में शायद यह थोड़ा अधिक काम है, लेकिन मुझे लगता है कि व्यवहार में, अतिरिक्त समाधान अन्य समाधानों के सामान्य नुकसान से बचने के लिए इसके लायक है।
#include <stdio.h>
#include <string.h>
struct splitFieldType {
char *field;
int maxLength;
};
typedef struct splitFieldType splitField;
int strsplit(splitField *fields, int expected, const char *input, const char *fieldSeparator, void (*softError)(int fieldNumber,int expected,int actual)) {
int i;
int fieldSeparatorLen=strlen(fieldSeparator);
const char *tNext, *tLast=input;
for (i=0; i<expected && (tNext=strstr(tLast, fieldSeparator))!=NULL; ++i) {
int len=tNext-tLast;
if (len>=fields[i].maxLength) {
softError(i,fields[i].maxLength-1,len);
len=fields[i].maxLength-1;
}
fields[i].field[len]=0;
strncpy(fields[i].field,tLast,len);
tLast=tNext+fieldSeparatorLen;
}
if (i<expected) {
if (strlen(tLast)>fields[i].maxLength) {
softError(i,fields[i].maxLength,strlen(tLast));
} else {
strcpy(fields[i].field,tLast);
}
return i+1;
} else {
return i;
}
}
void monthSplitSoftError(int fieldNumber, int expected, int actual) {
fprintf(stderr,"monthSplit: input field #%d is %d bytes, expected %d bytes\n",fieldNumber+1,actual,expected);
}
int main() {
const char *fieldSeparator=",";
const char *input="JAN,FEB,MAR,APRI,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC,FOO,BAR";
struct monthFieldsType {
char field1[4];
char field2[4];
char field3[4];
char field4[4];
char field5[4];
char field6[4];
char field7[4];
char field8[4];
char field9[4];
char field10[4];
char field11[4];
char field12[4];
} monthFields;
splitField inputFields[12] = {
{monthFields.field1, sizeof(monthFields.field1)},
{monthFields.field2, sizeof(monthFields.field2)},
{monthFields.field3, sizeof(monthFields.field3)},
{monthFields.field4, sizeof(monthFields.field4)},
{monthFields.field5, sizeof(monthFields.field5)},
{monthFields.field6, sizeof(monthFields.field6)},
{monthFields.field7, sizeof(monthFields.field7)},
{monthFields.field8, sizeof(monthFields.field8)},
{monthFields.field9, sizeof(monthFields.field9)},
{monthFields.field10, sizeof(monthFields.field10)},
{monthFields.field11, sizeof(monthFields.field11)},
{monthFields.field12, sizeof(monthFields.field12)}
};
int expected=sizeof(inputFields)/sizeof(splitField);
printf("input data: %s\n", input);
printf("expecting %d fields\n",expected);
int ct=strsplit(inputFields, expected, input, fieldSeparator, monthSplitSoftError);
if (ct!=expected) {
printf("string split %d fields, expected %d\n", ct,expected);
}
for (int i=0;i<expected;++i) {
printf("field %d: %s\n",i+1,inputFields[i].field);
}
printf("\n");
printf("Direct structure access, field 10: %s", monthFields.field10);
}
नीचे एक उदाहरण संकलन और आउटपुट है। ध्यान दें कि मेरे उदाहरण में, मैंने जानबूझकर "एपीआरआईएल" को वर्तनी दिया ताकि आप देख सकें कि नरम त्रुटि कैसे काम करती है।
$ gcc strsplitExample.c && ./a.out
input data: JAN,FEB,MAR,APRIL,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC,FOO,BAR
expecting 12 fields
monthSplit: input field #4 is 5 bytes, expected 3 bytes
field 1: JAN
field 2: FEB
field 3: MAR
field 4: APR
field 5: MAY
field 6: JUN
field 7: JUL
field 8: AUG
field 9: SEP
field 10: OCT
field 11: NOV
field 12: DEC
Direct structure access, field 10: OCT
का आनंद लें!
strtok
एक ही चीज़ को प्राप्त करने के लिए मानक लाइब्रेरी से फ़ंक्शन का उपयोग कर सकते हैं ।