How do I print specfic parts of a string in a file

63 Views Asked by At

I'm writing a program that will read from /etc/passwd and output the username and shell.

For example, here is the first line:

root:x:0:0:root:/root:/bin/bash

I need to only output the user and the shell. In this instance it would print:

root:/bin/bash

The values are seperated by : so I just need to print the string before the first : and the string after the 6th :. How can I do that?

Here is the code I have so far:

#include <unistd.h>
#include <fcntl.h>

//printf and scanf prototype

int printf(const char *text, ...);
int scanf(const char *format, ...);

int main(void)
{
        int fd;
        int buff_size = 1;
        char buff[512];
        int size;
        fd = open("/etc/passwd",O_RDONLY);
        if (fd < 0)
        {
                printf("Error opening file \n");
                return -1;
        }
        while ((size = read(fd,buff,1))>0)
        {
                buff[1] = '\0';
                printf("%s",buff);
        }
}

So far the code reads from /etc/passwd and prints out the whole file line by line. I need to configure the printf statement to just print the user and shell for each instance.

1

There are 1 best solutions below

2
Xin Cheng On

I just need to print the string before the first : and the string after the 6th :.

Filter the string, put the needed data into an output buffer, and print the output buffer.

Since you already used char buff[512]; as the original data buffer, then just create another buffer for output. i.e. char outbuff[512];

// char buff[512];     assume already defined as that in PO
// char outbuff[512];  assume already defined as that in PO
void customized_print(char* buff, char* outbuff) {
    int i = 0, j = 0, cnt = 0;
    while (i < 512) {   // copy until first ':'
        if((outbuff[j++]=buff[i++]) == ':') break;
    }
    // skip 5 more ':'
    while (i < 512 && cnt < 5) {
        if(buff[i++] == ':') cnt++;
    } 
    // copy the remains
    while (i < 512) {
        if( (outbuff[j++]=buff[i++]) == '\0' ) break; 
    }
    printf("%s\n", outbuff); 
    outbuff[0] = 0;  // clean the outbuff 
}

Another solution with a demo of full code.

If you do not need to use buff. You can use the following solution.

#include <stdio.h>
void customized_print(char* buff, char* outbuff) {
    int cnt = 0;
    char* p = outbuff;
    while (*buff) {   // copy until first ':'
        if((*p++=*buff++) == ':') break;
    }
    // skip 5 more ':'
    while (*buff && cnt < 5) {
        if(*buff++ == ':') cnt++;
    }
    // copy the remains
    while (*buff) {
        if( (*p++=*buff++) == '\0' ) break;
    }
    printf("%s\n", outbuff);
    outbuff[0]=0;  // clean the outbuff
}

int main(){
    char outbuff[512];
    customized_print("root:x:0:0:root:/root:/bin/bash", outbuff);
    customized_print("foo:x:0:0:root:/root:/bin/bash", outbuff);
    return 0;
}
  • Compile and run:

    gcc -Wall demo.c -o demo.out
    ./demo.out
    
  • Output:

    root:/bin/bash
    foo:/bin/bashh