-1

strtok()各フィールドを取得する代わりに、以下の文字列を解析する方が良いですか。

"subject=what&cc=bose@yahoo.com&server=smtp.yahoo.com:8000"

基本的に、各フィールドの値を別の char buf に取得したいと考えています。

これが私のコードです。それを行うための他のより良い方法があるかどうかを知りたかっただけです(より良い文字列解析アルゴリズム)

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

#define SUBJECT "subject="
#define CC_LIST "cc="
#define SERVER "server="

static void
get_value (const char *tok, char **rval_buf, size_t field_len)
{
    size_t val_size = 0;

    if (!tok || !rval_buf)
        return;

    val_size = strlen(tok + field_len) + 1;
    *rval_buf = calloc(1, val_size);

    if (*rval_buf) {
        strlcpy(*rval_buf, tok + field_len, val_size);
    }
}


int
main (int argc, char **argv)
{
    /* hard coded buf for testing */
    char buf[] = "subject=what&cc=bose@yahoo.com&server=smtp.yahoo.com:8000";
    char *subject_text = NULL;
    char *cc_list = NULL;
    char *server_addr = NULL;
    char *tok = NULL;
    int field_len = 0;
    int val_len = 0;

    tok = strtok(buf, "&");
    while(tok) {
        /*
         * Handle the token
         */
        /* check if it is subject */
        if (strstr(tok, SUBJECT)) {
            get_value(tok, &subject_text, strlen(SUBJECT));
        } else if (strstr(tok, CC_LIST)) { /* check if it is CC */
            get_value(tok, &cc_list, strlen(CC_LIST));
        } else if (strstr(tok, SERVER)) { /* check if it is server */
            get_value(tok, &server_addr, strlen(SERVER));
        }
        tok = strtok(NULL, "&");
    }
    /* dump data */
    fprintf(stdout, "\nSUBJECT: \"%s\"\nCC_LIST: \"%s\"\nSERVER: \"%s\" \n\n",
            subject_text, cc_list, server_addr);

    return EXIT_SUCCESS;
}
4

3 に答える 3

1

strstrある文字列 (「針」) を別の文字列 (「干し草の山」) 内で検索しますが、本当に知りたいのは針が干し草の山であるかどうかだけです。

ここに小さな提案があります:(#include <stdbool>ブール値をintに変更するか、ブール値を必要とします。私はブール値が好きです。)

static bool
getval(const char* haystack, const char** res, const char* needle, size_t len) {
  if (haystack && 0 == strncmp(haystack, needle, len)) {
    *res = strdup(haystack + len);
    return true;
  }
  return false;
}

以降:

for (tok = strtok(buf, "&"); tok; tok = strtok(NULL, "&")) {
  getval(tok, &subject_text, SUBJECT, strlen(SUBJECT)) ||
  getval(tok, &cc_list, CC_LIST, strlen(CC_LIST)) ||
  getval(tok, &server_addr, SERVER, strlen(SERVER));
}

最近のほとんどのコンパイラは、 getval をインライン化し、定数文字列の長さを定数倍するのに十分なほど賢いため、のstrlen内部を実行することで実際に回避できます。これにより、ノイズが大幅に削減されます。getval

于 2013-10-01T20:46:56.223 に答える
0

strtok() を使用する

char *strtok(char *str, const char *delim)

「&」を区切り文字として使用できます

于 2013-10-01T19:29:52.050 に答える