我正在编写一个程序,该程序将从/etc/passwd 读取并输出用户名和 shell。
例如,以下是/etc/passwd 文件的第一行:
root:x:0:0:root:/root:/bin/bash
我只需要输出用户和 shell。在这种情况下,它将打印:
root:/bin/bash
这些值由 ':'
分隔所以我只需要打印第一个 ':'
之前的字符串以及第六个 ':'
之后的字符串
这是我到目前为止的代码:
#include <string.h>
#define BUFFERSIZE 4096
int printf(const char *text, ...);
int main(void) {
int fd;
int buff_size = 1;
char buff[BUFFERSIZE];
int size;
fd = open("/etc/passwd", O_RDONLY);
if (fd < 0) {
printf("Error opening file \n");
return -1;
}
size = strlen(buff - 17);
size = size + 1;
while ((size = read(fd, buff, 1)) > 0) {
buff[1] = '\0';
write(STDOUT_FILENO, buff, size);
}
}
(我正在为 printf
创建原型(prototype),因为要求之一是编写不包含 <stdio.h>
或 <stdlib.h>
的程序)
最佳答案
另一种方法是使用单个循环和状态变量来根据读取的冒号数来跟踪每行中的位置状态。状态变量 ncolon 执行以下操作。本质上,您读取每个字符并检查循环是否处于应将字符写入输出的状态。您可以根据冒号的数量来调整写入,无论是在第一个冒号之前还是在最后一个冒号之后。
总而言之,你可以这样做:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main (int argc, char **argv) {
int fd, /* file descriptor */
ofd = STDOUT_FILENO, /* output file descriptor */
ncolon = 0; /* counter - number of colons seen */
/* open file given on command line or read from stdin otherwise */
if ((fd = argc > 1 ? open (argv[1], O_RDONLY) : STDIN_FILENO) == -1) {
return 1;
}
for (;;) { /* loop continually */
unsigned char c; /* storage for character */
int rtn; /* var to save return */
if ((rtn = read (fd, &c, 1)) < 1) { /* validate read of 1 char */
if (rtn == -1) { /* return on error */
return 1;
}
break; /* break read loop on EOF */
}
if (ncolon < 1 || ncolon == 6) { /* if before 1st or after last */
write (ofd, &c, 1); /* output char */
}
if (c == '\n') { /* reset ncolon on newline */
ncolon = 0;
}
else if (c == ':') { /* increment on colon */
ncolon += 1;
}
}
if (fd != STDIN_FILENO) { /* close file */
close (fd);
}
}
示例使用/输出
$ ./read_etc-passwd /etc/passwd
root:/bin/bash
messagebus:/usr/bin/false
systemd-network:/usr/sbin/nologin
systemd-timesync:/usr/sbin/nologin
nobody:/bin/bash
mail:/usr/sbin/nologin
chrony:/usr/sbin/nologin
...
确认格式
$ diff <(./read_etc-passwd /etc/passwd) <(awk -F: '{print $1":"$7}' /etc/passwd)
(无输出意味着程序输出和 awk
输出相同)
关于c - 如何在c中读取文件并输出特定字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74189447/