нужна идея о функции strtok? - PullRequest
0 голосов
/ 20 апреля 2011

Привет друзья, я читаю данные из файла и определяю значение с помощью ','. входной файл:

shankar,kumar,ooty
ravi,,cbe

код:

while ( fgets ( mem_buf, sizeof mem_buf, infile ) != NULL ) 
{
item = strtok(mem_buf,delims); 
printf("1 val:%s",item);    
item = strtok(NULL,delims);    
printf("2 val:%s",item);    
item = strtok(NULL,delims);    
printf("3 val:%s",item);
}

для указанного выше файла ввода, например:

1:shankar 2:kumar 3:ooty
1:ravi 2:cbe 3:

но мне нужен вывод, как,

1:shankar 2:kumar 3:ooty
1:ravi 2: 3:cbe 

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

Ответы [ 5 ]

3 голосов
/ 20 апреля 2011

Ничто не мешает вам кодировать вашу собственную strtok -подобную функцию:

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

static char *myStrTok (char *s, int c) {
    static char *nextS = NULL;  // Holds modified delimiter.
    static int done = 1;        // Flag to indicate all done.

    // Initial case.
    if (s != NULL) {
        // Return NULL for empty string.
        if (*s == '\0') { done = 1; return NULL; }

        // Find next delimiter.
        nextS = s;
        while ((*nextS != c) && (*nextS != '\0')) nextS++;
        done = (*nextS == '\0');
        *nextS = '\0';
        return s;
    }

    // Subsequent cases.
    if (done) return NULL;

    // Put delimiter back and find next one.
    *nextS++ = c;
    s = nextS;
    while ((*nextS != c) && (*nextS != '\0')) nextS++;
    done = (*nextS == '\0');
    *nextS = '\0';
    return s;
}

static int prt (char *s) {
    char *s2 = myStrTok (s, ','); printf ("1: [%s]\n", s2);
    s2 = myStrTok (NULL, ',');    printf ("2: [%s]\n", s2);
    s2 = myStrTok (NULL, ',');    printf ("3: [%s]\n", s2);
    s2 = myStrTok (NULL, ',');    if (s2 != NULL) printf ("4: [%s]\n", s2);
    printf ("==========\n");
}

int main (void) {
    char x[] = "shankar,kumar,ooty"; char y[] = "ravi,,cbe";
    prt (x); prt (y);
    printf ("[%s] [%s]\n", x, y);
    return 0;
}

Это выводит:

1: [shankar]
2: [kumar]
3: [ooty]
==========
1: [ravi]
2: []
3: [cbe]
==========
[shankar,kumar,ooty] [ravi,,cbe]

по вашему желанию.Он обрабатывает только один символ для разделителя, но в данном случае этого вполне достаточно.

2 голосов
/ 20 апреля 2011

Из справочной страницы: «Последовательность двух или более смежных символов-разделителей в разобранная строка считается одним разделителем. Символы разделителя в начале или конце строки игнорируются. Поставить другой путь: токены, возвращаемые функцией strtok (), всегда являются непустыми строками. "

Так что, если вам нужно использовать strtok, вам сначала нужно как-то изменить ввод.

0 голосов
/ 20 апреля 2011

Вот техника, которую я беззастенчиво скопировал с Роба Пайка:

void print_tokens(char *s)
{
    char *p, *last;

    last = s;

    for (p = strchr(s, ','); p; p=strchr(p+1, ',')){
            *p = 0;
            puts(last);
            *p = ',';
            last = p+1;
    }
    puts(last);
}

Я не тестировал приведенный выше код, поэтому возможны некоторые незначительные недостатки. Однако основная идея должна быть ясной.

0 голосов
/ 20 апреля 2011

Если strtok не может выполнить работу, которую вы хотите, вы можете кодировать свой собственный синтаксический анализатор, что-то вроде:

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

static int prt (char *s) {
    char *s2;
    s2 = strchr (s, ','); printf ("1: [%*.*s]\n", s2-s, s2-s, s); s = s2 + 1;
    s2 = strchr (s, ','); printf ("2: [%*.*s]\n", s2-s, s2-s, s); s = s2 + 1;
    printf ("3: [%s]\n", s);
    printf ("==========\n");
}

int main (void) {
    char x[] = "shankar,kumar,ooty"; char y[] = "ravi,,cbe";
    prt (x2); prt (y2);
    return 0;
}

Этот небольшой пример показывает разницумежду strtok решением и ручным strchr решением, при этом получается:

1: [shankar]
2: [kumar]
3: [ooty]
==========
1: [ravi]
2: []
3: [cbe]
==========

Вам нужно следить за случаями, когда у вас недостаточно разделителей (или их слишком много), ноэто должно быть незначительное изменение.

0 голосов
/ 20 апреля 2011

Вы можете проверить длину каждого item, чтобы убедиться, что он не равен 0.

Еще лучше, объедините это с циклом каждой строки ( пример ), чтобы вы не былиограничено тремя значениями.

...