Простой способ извлечь часть пути к файлу? - PullRequest
1 голос
/ 04 января 2009

Я не очень хорош в C, и я всегда зацикливаюсь на простых задачах по обработке строк (вот почему я люблю Perl!).

У меня есть строка, содержащая путь к файлу, например "/ Volumes / Media / Music / Arcade Fire / Black Mirror.aac". Мне нужно извлечь имя диска («Носитель» или, предпочтительно, «/ Тома / Носитель») из этого пути.

Любая помощь будет принята с благодарностью, так же, как я пытаюсь вернуть услугу по вопросам Perl!

  • Jim

Ответы [ 5 ]

3 голосов
/ 04 января 2009

Я думаю, что sscanf может быть уместным:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void test(char const* path) {
    int len;
    if(sscanf(path, "/Volumes/%*[^/]%n", &len) != EOF) {
        char *drive = malloc(len + 1);
        strncpy(drive, path, len);
        drive[len] = '\0';

        printf("drive is %s\n", drive);
        free(drive);
    } else {
        printf("match failure\n");
    }
}

int main() {
    test("/Volumes/Media/Foo");
    test("/Volumes/Media");
    test("/Volumes");
}

Выход:

drive is /Volumes/Media
drive is /Volumes/Media
match failure
1 голос
/ 04 января 2009

Я думаю, что самый простой способ - использовать strtok () . Эта функция разбивает строку на токены, разделенные одним из символов в строке разделителей.

Если ваш исходный путь находится в str , и вы хотите вторую часть в part :

strtok(str, "/");        /* To get the first token */
part=strtok(NULL, "/");  /* To get the second token that you want */

Обратите внимание, что strtok () изменит str , поэтому он не должен быть const . Если у вас есть строка const , вы можете использовать stdrup () , который не является стандартным, но обычно доступен для создания копии.

Также обратите внимание, что strtok () не является потокобезопасным.

1 голос
/ 04 января 2009
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char * extractDriveName(const char *path, char separator, int maxLen)
{
    char *outBuffer;
    int outBufferSize, i, j;
    int sepOcur;

    outBufferSize = strlen(path) + 1;
    outBufferSize = outBufferSize > maxLen ? maxLen : outBufferSize;

    outBuffer = (char *) malloc(outBufferSize);

    // Error allocating memory.
    if(outBuffer == NULL)
        return NULL;

    memset(outBuffer, 0, outBufferSize);

    for(i = 0, sepOcur = 0, j = 0; i < outBufferSize; i++)
    {
        if(path[i] == separator)
            sepOcur ++;

        if(sepOcur >= 0 && sepOcur < 3)
            outBuffer[j++] = path[i];
        else if(sepOcur == 3)
            break;      
    }

    // Don't forget to free the buffer if 
    return outBuffer;           
}

int main(void)
{
    char path [] = "/Volumes/Media/Music/Arcade Fire/Black Mirror.aac";

    char * driveName = extractDriveName(path, '/', strlen(path) + 1);

    if(driveName != NULL)
    {
        printf("Path location: '%s'\n", path);
        printf("Drive name: '%s'\n", driveName);
        free(driveName);
    }
    else
    {
        printf("Error allocating memory\n");
    }
}

Выход:

Path location: '/Volumes/Media/Music/Arcade Fire/Black Mirror.aac'
Drive name: '/Volumes/Media'
1 голос
/ 04 января 2009

Я думаю, что вам нужно быть немного более точным в спецификации вашей проблемы.

Когда вы говорите, что хотите извлечь «Media», вы имеете в виду все, что находится между вторым и третьим символом «/», или в работе есть более сложная эвристика?

Кроме того, является ли строка в буфере подходящей для изменения?

Обычно для этого можно использовать strchr или strstr один или несколько раз, чтобы найти указатель на то место, откуда вы хотите извлечь подстроку (скажем, p), и указатель на символ после последнего символа, который вам нужно извлечь (скажем, q), если буфер является временным буфером, который вы не возражаете уничтожить, тогда вы можете просто сделать *q = 0 и p будет указателем на требуемую строку , В противном случае вам нужно иметь буфер не менее q - p + 1 символов (+1 должен включать пробел для нулевого терминатора, а также q - p интересных символов. Например, char *buffer = malloc(q - p + 1);), и вы можете извлечь строку с помощью memcpy. например memcpy(buffer, p, q - p + 1).

0 голосов
/ 04 января 2009

Ваш пример показывает, что вы работаете в среде Macintosh. Я подозреваю, что есть Apple API для получения тома, на котором находится конкретный файл.

Есть причина не использовать это?

Редактировать: Глядя на ваш профиль, я подозреваю, что я неправильно догадался о вашей среде. Я не могу помочь тебе за окнами. Удачи. Я оставлю это здесь на случай, если кто-то ищет такой же ответ на Mac.


На форумах Mac я нахожу « Получение имени текущего рабочего тома? », что похоже на тот же вопрос. Там есть хорошая дискуссия, но они, похоже, не приходят к единственному ответу.

Google - твой друг.


Другая возможность: Путь BSD к имени тома и наоборот на форумах CocoaDev.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...