2014-09-22 3 views
0

я могу получить строку между двумя строками с помощью следующей функции:C: Получение строки, содержащие пробелы между двумя строками

char* parsedData = NULL; 

const char* const parseData(char* theString, char* start, char* end){ 
     if (!theString) return 0;        
     size_t startSize = strlen(start);     
     char* startP = strstr (theString,start);   
     if(!startP) 
      return 0;       
     startP+=startSize;        
     char* endP = strstr ((startP),end);    
     if(!endP) 
      return 0;        
     //free(parsedData);        
     parsedData = NULL; 
     parsedData = (char*) malloc((size_t)(sizeof(char)*(endP-startP)+1));  
     if (parsedData == NULL) { 
      return 0; 
     }  
     int dataPos=0; 
     while (startP != endP){      
      parsedData[dataPos++]= *startP++; 
     } 
     parsedData[dataPos]= '\0';      
     return parsedData;          
} 

Есть две проблемы, которые я имею здесь.

  1. Это работает, когда моя строка не содержит пробелов, но не делает иначе. Когда я печатаю строку, я получаю только (null).

  2. Когда я раскомментирую строку free(), я получаю ошибку munmap_chunk(): invalid pointer: и программа вылетает из строя.

Как это решить?

/**************************************** EDIT 1 ** **************************************/

После ответа Стин я понял проблема 1 связана с отсутствием проверки ошибок в другом месте. Я подтверждаю, что функция работает как с пробелами, так и без них.

/**************************************** EDIT 2 ** **************************************/

Я изменил следующий код предложения Гайда:

const char* const parseData(char* theString, char* start, char* end){ 
    char* tmpstr; 
    if (!theString) return 0;   
    size_t startSize = strlen(start); 
    char* startP = strstr (theString,start); 
    if(!startP) return 0; 
    startP+=startSize; 
    char* endP = strstr ((startP),end); 
    if(!endP) return 0; 
    if (parsedData != NULL){ free(parsedData);} 
    parsedData = NULL; 
    parsedData = (char*) malloc((size_t)(sizeof(char)*(endP-startP)+1)); 
    if (parsedData == NULL) { 
     return 0; 
    } 

    int dataPos=0; 
    while (startP != endP){ 
     parsedData[dataPos++]= *startP++; 
    } 
    parsedData[dataPos]= '\0'; 
    tmpstr = parsedData; 
    return tmpstr; 
} 

Я вызываю функцию таким образом:

const char* const usr1 = parseData(buffer, ":", ","); 
const char* const usr2 = parseData(buffer, ",", "."); 
const char* const usr3 = parseData(buffer, "(", ")"); 

printf("%s, %s, %s\n", usr1, usr2, usr3); 

Но выход всегда:

<usr3>, <usr3>, <usr3>

+0

Работает для меня просто отлично http://ideone.com/wag014 –

+0

'free (parsedData);' находится в правильном месте в коде. Это удобно, если вы поймаете этот возвращенный буфер. –

+2

Вы не должны касаться глобальной переменной этой функции. Просто верните значение локальной переменной указателя (выделенная память находится в куче, поэтому перейдет в область действия). На самом деле вы, вероятно, не должны иметь глобальную переменную вообще, но дело в том, что нести ответственность за то, чтобы ухаживать за указателем на вызывающего. – hyde

ответ

1

Функция работает для меня как с параметрами, так и без них.

Вы должны охранять ваш free(parsedData) с if (parsedData != NULL) иначе вы будете освободив с NULL-указатель на первый проход

Я хотел бы попробовать что-то по этой линии:

const char* const parseData(char* theString, char* start, char* end){ 
    #define PARSE_ELEMENT_MAX_SIZE 256 
    static char parsedData[ PARSE_ELEMENT_MAX_SIZE ]; 

    if (theString == NULL || start == NULL || end == NULL) { 
    return 0;   
    } 
    size_t startSize = strlen(start); 
    char* startP = strstr (theString,start); 
    if(startP == NULL) { 
    return 0; 
    } 
    startP+= startSize; 
    char* endP = strstr (startP, end); 
    if(endP == NULL || endP - startP >= PARSE_ELEMENT_MAX_SIZE) { 
    return 0; 
    } 
    memcpy(parsedData, startP, endP - startP); 
    parsedData[ endP - startP ]= 0; 
    return parsedData; 
} 

Если вы хотите сохранить данных между навязчивыми вызовами, вам нужно будет предоставить вызывающему абоненту собственный буфер и не выделять его в функции parseData:

BOOL parseData(char* theString, char* start, char* end, 
    char *parsedData, size_t MaxSizeOfParsedData){ 

    if (theString == NULL || start == NULL || end == NULL || parsedData == NULL) { 
    return FALSE;   
    } 
    char* startP = strstr (theString,start); 
    if(startP == NULL) { 
    return FALSE; 
    } 
    startP+= strlen(start); 
    char* endP = strstr (startP, end); 
    if(endP == NULL || endP - startP >= MaxSizeOfParsedData) { 
    return FALSE; 
    } 
    memcpy(parsedData, startP, endP - startP); 
    parsedData[ endP - startP ]= 0; 
    return TRUE; 
} 
+2

C-Standard явно разрешает 'NULL' передавать' free() '. – alk

+0

Вы правы о 1. Спасибо, что потратили время, чтобы проверить его. Я попробовал ваше предложение, но с этим изменением функция, похоже, возвращает одно и то же значение при последующих вызовах. Интересно, если это проблема в другом месте, но я ничего не изменил. – Zaxter

+0

Трудно сказать. Вы можете удалить malloc и вернуть данные из массива фиксированного размера (char parsedData [MAX_SIZE]). Если вы столкнулись с проблемами в куче, это устранит проблему из этой функции :) – Steen

1
const char* const findSubStr(char* pSearchStr, char* pStrStart, char* pStrEnd) 
{ 
    // validate parameters 
    if (!pSearchStr) return 0; 
    if (!pStrStart) return 0; 
    if (!pStrEnd) return 0; 
    if (pStrEnd <= pStrStart) return 0; 

    int WorkStrLen = pStrEnd - pStrStart +2; // allows for terminator byte 

    // get work area so can modify original string with terminator byte 
    char* pWorkStr = malloc(WorkStrLen); 
    if(NULL == pWorkStr) return 0; // check for malloc failure 

    // clear work area and copy target string 
    memset(pWorkStr, 0x00, WorkStrLen);  
    memcpy(pWorkStr, pStrStart, (WorkStrLen -1)); // avoid overlaying term byte 

    // find the search string 
    char* pFoundStr = strstr(pWorkStr, pSearchStr); 
    // verify string found 
    if (NULL == pFoundStr) return 0; // search string wasn't found 

    int offset = pFoundStr - pWorkStr; 
    free(pWorkStr); 
    return(&pStrStart[offset]); // return ptr to found substring       
} 
+0

Я не могу использовать эту функцию. Он всегда возвращает null. Всегда возвращается в if (pStrEnd <= pStrStart). Я использую его как "const char * const usr = findSubStr (buffer,": ",", ");". Буфер завершен нулем. Не могли бы вы проверить и обновить? – Zaxter

+0

проверка 'if (pStrEnd <= pStrStart) return 0;' неверно. Он сравнивает физическое положение в памяти указателей начальной строки конца – Steen

Смежные вопросы