从缓冲区读取数据的最佳实践

时间:2013-04-02 01:39:36

标签: c buffer uart

我想收到有关如何从UART缓冲区读取数据的想法。更准确地说,我需要一种方法在缓冲区中找到一些字符串模式。问题是,如果我等待搜索此字符串,则会再次写入缓冲区,计数器会更改,并且数据可以具有该模式。好吧,我认为这个解释有点难以理解,所以请随意提出其他任何问题。

void f(char * buffer) {

char * p;
p = strstr(buffer, "abc");

printf(p);
}

我认为在我的情况下,UART是由块写的,而不是char写的char,并且没有办法说数据已经完成,因为它是一个连续的流。为了更好地说明,它是一个代码,它以NMEA协议读取GPS数据并尝试从这些数据中获取信息。

祝你好运

3 个答案:

答案 0 :(得分:0)

你能收到所有数据然后处理字符串吗?我认为代码喜欢这个:

char *p_uart = read_from_uart();

void search_string(char *p_uart)
{
    static char last_remain_char[20];
    char new_data[1000] = {0};
    char *p = NULL;
    int n = 0;

    n = snprintf(new_data, sizeof(new_data), "%s%s", last_remain_char, p_uart);
    p = strstr(new_data, "abc");

    strcpy(last_remain_char, new_data + (n - (strlen("abc") - 1)));
}

答案 1 :(得分:0)

您可以接收每个字符并将它们(复制)累积在常规缓冲区中以便稍后进行比较。或者,更好的方法是接收每个角色并保留一个状态变量来告诉你你在比赛中的距离:

size_t state = 0;
while( c=get_char_uart() ) {
    if (str_to_match[state] == c)  {
        state++;
        if (state == strlen(str_to_match)) {
            /* success */
        }
    }
    else 
        state = 0;
}

如果您期望重复的字符序列(“abcabd”),它会变得更加棘手。在这种情况下,如果您在d失败,则可能需要查找c。警告。

答案 2 :(得分:0)

你的问题不明确,但我看到很多人误解了缓冲区是如何工作的,所以我想我可以提供帮助。

根据您所说的,您希望将数据读入缓冲区,并担心它会与您的搜索字符串部分匹配。然后,当您阅读其余部分时,您将覆盖第一批数据。

因此,这取决于您处理数据的方式。您不需要每次都读入相同的内存部分。缓冲区的全部内容是它为您提供了可以填充的空间,必要时可以随意丢弃然后丢弃。

有效地使用缓冲区的方法有很多种。我会给你最简单的理解,虽然它可能不是最有效的:

当你读入缓冲区时,你维护一个索引(让我们称之为tail),这样你就知道最后一个字节在哪里。您最多可以读取N个字节,其中N是缓冲区的大小。在处理数据时,您可以检查最多tail的字节。

要跟踪已处理的内容,请维护head索引。一旦确定需要阅读更多数据,就可以在headtail之间取得所有内容并将其移至缓冲区的开头(使用memmove NOT memcpy)。您设置了head = 0tail = tail-head。现在,您最多可以读取N - tail个字节。当然,您会在tail索引之后的缓冲区中读入一个位置。

如果您希望能够将整个匹配字符串测试为连续字节,这是最简单的缓冲方法。

如果你想更进一步,想到你根本不需要移动数据并不需要太多想象力。你可以绕着head追逐tail。这称为 ring (或循环)缓冲区。这样做的难点在于你不能使用普通的字符串匹配,但它不需要花很多时间来完成。

希望这有用。