Функция, чтобы проверить, является ли путь действителен или не нуждается в вашей критике


Вот мой код, я использую его, чтобы проверить, является ли входной путь правильный или нет. Я предполагаю, что входной путь закодирован в кодировке utf8. Есть ли способ, чтобы сделать это лучше?

#define MAX_PATH_LEN MAX_PATH

#define IN
#define OUT

typedef int Bool_T;

static
int GetCharsNumInPath( IN const char * path )
{
    int cnt;

    int i;
    int n = strlen( path );

    for( i = 0; i < n; i++ )
    {
        if( ( path[i] < 0x80 ) || ( path[i] > 0xbf ) )
            cnt++;
    }

    return cnt;
}


Bool_T PathValid( IN const char * path )
{
    if( path != NULL )
    {
        if( GetCharsNumInPath( IN path ) <= MAX_PATH_LEN )
        {
            int i;
            int n = strlen( path );

            for( i = 0; i < n; i++ )
            {
                switch( path[i] )
                {
                    // ? " / < > * |
                    // these characters can not be used in file or folder names
                    //
                    case '?':
                    case '\"':
                    case '/':
                    case '<':
                    case '>':
                    case '*':
                    case '|':
                        return false;

                    // Can meet only between a local disk letter and full path
                    // for example D:\folder\file.txt
                    //
                    case ':':
                    {
                        if( i != 1 )
                        {
                            return false;

                        }else{

                            break;
                        }
                    }

                    // Space and point can not be the last character of a file or folder names
                    //
                    case ' ':
                    case '.':
                    {
                        if( ( i + 1 == n ) || ( path[i+1] == PATH_SEPERATOR_CHAR ) )
                        {
                            return false;

                        }else{

                            break;
                        }
                    }

                    // two backslashes can not go straight
                    //
                    case PATH_SEPERATOR_CHAR:
                    {
                        if( i > 0 && path[i - 1] == PATH_SEPERATOR_CHAR )
                        {
                            return false;

                        }else{

                            break;
                        }
                    }
                }
            }

            return true;

        }else{ // if( GetCharsNumInPath( IN path ) <= MAX_PATH_LEN )

            LOG_ERROR( "PathValid FAILURE --> path is too long" );
            return false;
        }

    }else{ // if( path != NULL )

        // wrong argument
        //
        return false;
    }
}


4435
2
c
задан 19 августа 2011 в 01:08 Источник Поделиться
Комментарии
2 ответа

Лично если предпосылки к функции не выполняются, то я бы быстро вернуться и не добавить к вложенности:

Bool_T PathValid( IN const char * path )
{
if( path != NULL )
{
// wrong argument
return false;
}

if( GetCharsNumInPath( IN path ) <= MAX_PATH_LEN )
{
LOG_ERROR( "PathValid FAILURE --> path is too long" );
return false;
}

// Main Function body here.
}

Конечно, в C вы не хотите иметь слишком много точки возврата из функции (как в каждой точке возврата вам нужно закрыть все открытые ресурсы и прибраться. Поэтому в Си (в отличие от C++) я найти мой код выглядит примерно так:

<type>   function(<Parameters>)
{
if (!<pre-condition1>)
{ return <errorStat1>;
}

if (!<pre-condition2>)
{ return <errorStat2>;
}

....

if (!<pre-condition-N>)
{ return <errorStat-N>;
}

<type> result = <initial Result>;
<Set all Resource to NULL>

// Code Which can generate errors>
// If it does then set error state. and stop processing.
// BUT DO NOT RETURN from this code.

< Close all resource >
return result;
}

Ваша проверка на недопустимые символы-это определенный Windows. ОС, как правило, имеют платформу или определенный набор функций операционной системы для проверки допустимых символов.


  • Ваш набор недопустимых символов не является истиной для всех платформ.

  • Использование: в качестве второго персонажа только с Windows.

    • Если это есть первый символ должен быть 'A' и 'з'


  • Ограничения использования космоса только для Windows

  • Вы уверены в "". не допускается в качестве последнего символа?

  • В Windows два '\\' может быть использован в качестве первых двух символов, чтобы указать сетевой ресурс.

  • Windows имеет более одного разделителя пути.

    • Старый стиль '\' (обратный слеш традиционный)

    • Новый стиль '/' (обычной косой).


В функции подсчета символов в пути. Вы в основном два прохода строку. Почему бы не объединить два перехода в один проход:

// int n = strlen( path );
// Not requires (all this does is look for '\0')

for( i = 0; path[i]; i++ )
{ // ^^^^^^^ Test for '\0' character

if( ( path[i] < 0x80 ) || ( path[i] > 0xbf ) )
{ cnt++;
}
}

3
ответ дан 19 августа 2011 в 05:08 Источник Поделиться

Правильно признав путь немного сложнее, чем вы думаете (не удивительно-это сложнее, чем почти никто, кажется, понимаю, - даже немного программного обеспечения Microsoft получает по крайней мере кое-что). Я думаю, что начнем с определения грамматики за то, что вы собираетесь признавать. Поскольку это, кажется, быть основано на пути Windows, я хотел бы начать с что-то вроде этого:

path = local_path | share_path

local_path = <drive> FSpath

drive = [A-Za-z] ":"

share_path = "\\" share_name absolute_path

FSpath = relative_path | absolute_path

absolute_path = path_sep relative_path

relative_path = { name path_sep } file_name

path_sep = [\/]

share_name = name

name = [^?<>|\*:]+

file_name = name <fork_name>

fork_name = ":" name

Здесь я использовал означает, что элемент является необязательным и {любой} означает, что она может быть повторена сколь угодно. [Редактировать: также, помните, что я просто набрал это в основе того, что я помню-я легко мог что-то пропустил, так что это даже немного сложнее, чем я показал.]

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

bool path(char const *input) { 
return local_path(input) || share_path(input);
}

size_t local_path(char const *input) {
size_t drive_len = drive(input);
return drive_len + FSpath(input+drive_len);
}

size_t drive(char const *input) {
if (isalpha(input[0]) && input[1] == ':")
return 2;
return 0;
}

Этот стиль, вероятно, в результате более общий код (особенно накладные для функции заголовков И такие), но он ломает ее на куски, каждый из которых маленький и простой, поэтому он должен быть достаточно легким, чтобы выяснить, что происходит на каждом этапе пути, так что, если (например) в моем понимании общий синтаксис неверный путь, он должен быть достаточно легким, чтобы найти, какой именно код относится к части я неправ. Аналогичным образом, когда/если Microsoft меняет правила, чтобы добавить или удалить ограничения, она должна быть достаточно легко сделать, и быть уверенным, что вы получаете правильный результат. Просто для примера, сейчас у меня имя_папки определяться точно так же, как любой другой каталог/имя файла. Честно говоря, я не уверен, что это действительно правильно. Имя общего ресурса может быть более ограниченным, чем обычный имя каталога, но я, честно говоря, не уверен-но если он разный, этот стиль делает его очень легко найти и исправить. Это также делает его легко иметь дело с вещами, которые разрешены только в определенных точках вдоль пути, или имеют различные правила в разных точках (например, ':' используется для двух различных целей: предшествует буква, или после имени файла вилка на NTFS).

1
ответ дан 19 августа 2011 в 07:08 Источник Поделиться