문제

무언가를 쓸 위치를 알기 위해 구성 파일을 읽는 데몬이 있습니다. 구성 파일에는 이와 같은 줄이 있습니다.

output = /tmp/foo/%d/%s/output

또는 다음과 같이 보일 수 있습니다.

output = /tmp/foo/%s/output/%d

... 또는 단순히 이것을 좋아합니다 :

output = /tmp/foo/%s/output

... 또는 마지막으로 :

output = /tmp/output

나는 그 라인을 내 프로그램 내에서 cfg-> pathfmt로 가지고 있습니다. 내가 지금하려는 것은 그것을 사용하는 영리한 방법을 생각해내는 것입니다.

조금 더 설명하면, 경로에는 최대 두 개의 구성 요소가 포함될 수 있습니다. %d는 작업 ID (int)로, %s는 작업 이름 (문자열)으로 확장됩니다. 사용자는 구성 파일에서 둘 다 또는 아무도 사용하지 않을 수 있습니다. 나는 그들이 원하는 것이 무엇인지, 그리고 마침내 그것을 snprintf ()로 전달하기 전에 어떤 순서로 알아야합니다. 나는 그것을 좁힐 수는 있지만, 나는 Strtok ()와 계속 대화하고 싶고 그것은 추악한 것 같습니다.

사용자에게 이런 종류의 유연성을 제공하고 싶지만,이를 구현할 수있는 현명하고 휴대용 방법을 찾고 있습니다. 나는 또한 이것을 검색하는 방법에 대한 완전하고 총 손실에 있습니다.

나는 매우 행복 할 것이다.

  • 누군가가 검색어를 좁히도록 도와 줄 수 있습니다.
  • 누군가 이것을 구현하는 일부 OSS 프로젝트에 링크를 게시 할 수 있습니다.
  • 누군가 psuedo 코드를 게시 할 수 있습니다

나는 코드가 저를 위해 쓰여진 것을 원하지 않습니다. 나는 단지 매우 간단한 무언가가되어야한다고 생각하고 첫 번째 물기를 가져가는 데 도움이 필요합니다. 나는 정말로 생각하고 명백한 생각을 간과하는 것처럼 느낍니다.

최종 결과는 다음과 같은 부울 기능이어야합니다.

bool output_sugar(const char *fmt, int jobid, const char *jobname, struct job *j);

그런 다음 j-> outpath에서 snprintf () (snessibly)를 호출하고, 어떤 종류의 쓰레기 (즉, s, d 또는 %가 아닌 것을 뒤 따르는)가 구성 줄 (또는 그 널)에 있으면 거짓을 반환합니다. 정신 점검은 쉽습니다. 저는 인수의 숫자 (및 순서)를 정확하게하는 데 약간의 시간을 보내고 있습니다.

미리 감사드립니다. 또한 명성이 있다면이 제목을 편집하십시오. 내가 말했듯이, 한 줄로 질문을하는 방법은 잘 모르겠습니다. 나는 내가 필요한 것이 a라고 생각합니다 파서, 그러나 하나의 간단한 문자열을 처리하기 위해 완전히 날아간 Lexer / Parser를 사용하여 어색한 느낌이 듭니다.

도움이 되었습니까?

해결책

예, 당신은 일종의 구식이 필요합니다. 그러나 복잡 할 필요는 없습니다.

void format_filename(const char *fmt, int jobid, const char *jobname,
                     char *buffer, size_t buflen)
{
    char *end = buffer + buflen - 1;
    const char *src = fmt;
    char *dst = buffer;
    char c;
    assert(buffer != 0 && fmt != 0 && buflen != 0 && jobname != 0);
    while ((c = *src++) != '\0')
    {
        if (dst >= end)
            err_exit("buffer overflow in %s(): format = %s\n",
                     __func__, fmt);
        else if (c != '%')
            *dst++ = c;
        else if ((c = *src++) == '\0' || c == '%')
        {
            *dst++ = '%';
            if (c == '\0')
                break;
        }
        else if (c == 's')
        {
            size_t len = strlen(jobname);
            if (len > end - dst)
                err_exit("buffer overflow on jobname in %s(): format = %s\n",
                         __func__, fmt);
            else
            {
                strcpy(dst, jobname);
                dst += len;
            }
        }
        else if (c == 'd')
        {
             int nchars = snprintf(dst, end - dst, "%d", jobid);
             if (nchars < 0 || nchars >= end - dst)
                 err_exit("format error on jobid in %s(); format = %s\n",
                          __func__, fmt);
             dst += nchars;
        }
        else
            err_exit("invalid format character %d in %s(): format = %s\n",
                     c, __func__, fmt);
    }
    *dst = '\0';
}

이제 테스트 된 코드. 사용자가 출력에 단일 '%'를 포함 할 수 있도록 '%%'표기법을 지원합니다. 또한 문자열 끝에서 단일 '%'를 유효하고 '%%'와 동일합니다. 오류에서 err_exit ()을 호출합니다. 시스템에 적합한 대체 오류 전략을 선택할 수 있습니다. 나는 단순히 당신이 포함했다고 가정합니다 <assert.h>, <stdio.h> 그리고 <string.h> 그리고 err_exit() (variadic) 기능.


테스트 코드 ...

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>

static void err_exit(const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    exit(1);
}

... 그 다음에 format_filename() 위와 같이 ... 그런 다음 ...

#define DIM(x) (sizeof(x)/sizeof(*(x)))

static const char *format[] =
{
    "/tmp/%d/name/%s",
    "/tmp/%s/number/%d",
    "/tmp/%s.%d%%",
    "/tmp/%",
};

int main(void)
{
    char buffer[64];
    size_t i;

    for (i = 0; i < DIM(format); i++)
    {
        format_filename(format[i], 1234, "job-name", buffer, sizeof(buffer));
        printf("fmt = %-20s; name = %s\n", format[i], buffer);
    }

    return(0);
}

다른 팁

Strtok을 사용하는 것은 오류가 발생하기 쉬운 오류입니다. (FL) Lex 및 YACC를 사용하여 변수를 미니 언어로 취급 할 수 있습니다. 여기에 간단한 튜토리얼이 있습니다

%{
#include <stdio.h>
%}

%%
%d                      printf("%04d",jobid);
%s                      printf("%s",stripspaces(dirname));
%%

나는 당신이 dbprintf와 같은 일을 할 수있는 ODBC 래퍼를 만들었습니다 ( "blah 값에 삽입 %s %d %t %y", 여기에 재료 ...); 그러나 몇 년 전이었고 나는 그것을 물고 strtok을 사용하여 형식 문자열을 구문 분석했습니다.

옵션 수가 적고 구문 분석기의 추가 유연성과 복잡성을 원하거나 필요로하지 않으면 strstr ()를 사용하여 각 잠재적 대체 기판을 검색 할 수 있습니다.

두 가지 옵션 만있는 경우, 올바르게 주문한 상태에서 Sprintf ()를 호출 할 수있는 4 개의 브랜치 IF/Else 구조 (A, A 전 B가있는 B, B가있는 B, B와 함께 B 만 포함 할 수 있습니다. 논쟁. 그렇지 않으면 여러 sprintf () 호출을 만들고 각각은 형식 문자열의 첫 번째 교체 마커 만 대체합니다. (이것은 교체가 필요한 목록을 작성하고 외관으로 정렬하는 것을 의미합니다 ...)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top