如何使用 sscanf 从相似的行中读取特定数字?
How to read in a specific number with sscanf from lines which are similar?
我正在尝试使用 C
标准库中的 sscanf()
函数从文件中读取特定数字。我的示例数据来自 /proc/stat
系统 运行 a Linux Kernel
。外观如下:
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
),然后将以下数字 %d
存储在 int cpu
.但是 cpuN
行存储了错误的值。不是存储 0, 1, 2, 3
而是存储值 22942, 23879, 21510, 21824
。现在这可以追溯到我对 %1[^ ]
的使用。但是我尝试了很多不同的东西,以至于我可能会错过显而易见的东西。我如何打印除 cpu
后跟数字 N
并在 int cpu
中存储 N
的行以外的所有行? (如果可能,我想避免使用 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);
}
建议:
1) 将行读入缓冲区
2) strncmp (buffer, "cpu ") if 0, ignore line // notice trailing space
3) strncmp (buffer, "cpu" ) if 0, saved = atoi( buffer[3] ) // 没有尾随 space
4) 忽略所有其他行
您不想禁止分配 cpu
之后的数字。但是,您也不想跳过空白,因此您需要使用 %c
或 %[]
,因为所有其他格式(除了 %n
,这绝对不算在内contex) 跳过前导空格。反过来,这意味着您需要读取一个字符串,而不是一个整数。所以,代码应该是:
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()
函数从文件中读取特定数字。我的示例数据来自 /proc/stat
系统 运行 a Linux Kernel
。外观如下:
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
),然后将以下数字 %d
存储在 int cpu
.但是 cpuN
行存储了错误的值。不是存储 0, 1, 2, 3
而是存储值 22942, 23879, 21510, 21824
。现在这可以追溯到我对 %1[^ ]
的使用。但是我尝试了很多不同的东西,以至于我可能会错过显而易见的东西。我如何打印除 cpu
后跟数字 N
并在 int cpu
中存储 N
的行以外的所有行? (如果可能,我想避免使用 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);
}
建议:
1) 将行读入缓冲区
2) strncmp (buffer, "cpu ") if 0, ignore line // notice trailing space
3) strncmp (buffer, "cpu" ) if 0, saved = atoi( buffer[3] ) // 没有尾随 space
4) 忽略所有其他行
您不想禁止分配 cpu
之后的数字。但是,您也不想跳过空白,因此您需要使用 %c
或 %[]
,因为所有其他格式(除了 %n
,这绝对不算在内contex) 跳过前导空格。反过来,这意味着您需要读取一个字符串,而不是一个整数。所以,代码应该是:
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…