c - 如何使用 sscanf 从相似的行中读取特定数字?

标签 c scanf

我正在尝试使用 C 标准库中的 sscanf() 函数从文件中读取特定数字。我的示例数据来自运行 Linux 内核 的系统上的 /proc/stat。这是它的样子:

cpu  90158 11772 50095 6885572 36975 0 207 0 0 0
cpu0 22942 2975 12847 1720241 9655 0 58 0 0 0
cpu1 23879 2979 12080 1717405 12483 0 45 0 0 0
cpu2 21510 3105 12864 1722238 7790 0 57 0 0 0
cpu3 21824 2712 12301 1725687 7044 0 45 0 0 0
.
.
.
intr 2108705 19 28724 0 0 0 0 0 0 1 90871 0 0 204911 0 0 0 143 0 0 0 0 35 0     0 0 0 2362 0 101810 25 388 0 404786 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 11136028
btime 1423918994
processes 155184
procs_running 2
procs_blocked 1
softirq 2109698 8 644880 168 19330 95660 0 24557 551780 3897 769418

我尝试打印 if 语句之后的所有行,但包含 cpu 的行除外(没有空格)直接跟一个数字。那是第一行 cpu 应该与所有其他人一起打印,但例如不是第二行 cpu0。此外,这些行中紧跟在 cpu 之后的数字应该作为 int 存储到 int cpu 中。

我真的很想解决这个问题,我至少可以通过使用字符类来打印正确的行。我的 if 语句包含:

sscanf(line, "cpu%*1[^ ]%d", &cpu) != 1)

其中 %1[^ ] 表示在行中读取直到遇到单个空格(可能不需要 1),然后存储以下数字 %dint cpu 中。但是为 cpuN 行存储了错误的值。不是存储 0、1、2、3,而是存储值 22942、23879、21510、21824。现在这可以追溯到我对 %1[^ ] 的使用。但是我尝试了很多不同的东西,以至于我可能会错过显而易见的东西。如何打印除 cpu 后跟数字 N 并将 N 存储在 中的所有行(无空格) int cpu? (如果可能,我想避免使用 regex.h。)这是我目前的代码:

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

main(void)
{
    FILE * fp;
    char * line = NULL;
    size_t len = 0;
    ssize_t read;

    fp = fopen("/proc/stat", "r");
    if (fp == NULL)
        exit(EXIT_FAILURE);

    while ((read = getline(&line, &len, fp)) != -1) {
        int cpu;
         if (sscanf(line, "cpu%*1[^ ]%d", &cpu) != 1) {
            printf("%s", line);
        }
    }

    fclose(fp);
    if (line)
        free(line);
    exit(EXIT_SUCCESS);
}

最佳答案

您不想禁止分配 cpu 之后的数字。但是,您也不想跳过空白,因此您需要使用 %c%[] 因为所有其他格式(除了 %n ,在此上下文中绝对不算数)跳过前导空格。反过来,这意味着您需要读取一个字符串,而不是一个整数。所以,代码应该是:

char cpu_str[8];  // Allow for big machines!
if (sscanf(line, "cpu%7[^ ]", cpu_str) != 1)
    printf("%s", line);
else if (sscanf(cpu_str, "%d", &cpu) != 1)
    …oops: may the scanset should be %7[0-9]…
else
    …cpu contains the cpu number…

关于c - 如何使用 sscanf 从相似的行中读取特定数字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28518704/

相关文章:

c - malloc 之后的点初始化结构

c - 如何从 C 文件中查找某个字符的编号?

c - 为什么 Xcode 似乎跳过了第二个 scanf() 调用?

c - 为什么我的字符串的第一个字母不打印?

使用后继续fscanf

c - 无法完全执行 do-while 循环

c++ - Canon SDK (EDSDK) 抓取指定大小的视频流区域

铿锵: compiling with non-flat x86 stack model

c - 二维数组结构段错误

C幂函数和scanf