c - 如何在c中读取文件并输出特定字符串

标签 c

我正在编写一个程序,该程序将从/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/

相关文章:

c - pthread_join 自由() : invalid pointer error

c++ - 使用 C++ 检索网站数据

c - Glob 中的 "unsorted"订单来自哪里?

c - 我如何知道 USB 存储设备安装在哪里?

c - 为什么我看不到使用 Arduino 串行监视器通过 XBees 发送的数据?

在 C 中将十六进制值转换为字符数组

将整数转换为数字数组 [C]

c - 将现有的随机数生成器移植到 C

c++ - 从 cl_context 创建 OpenCL 上下文而不获取所有权

c - 使用共享内存(mmap)和信号量进行进程间通信