Prometheus_26
Prometheus_26

Reputation: 9

pointers and weird fgets behaviour

This program copies content from a file and transfers all the content except the inputted name. This code handles files. The problem i'm having is whenever I take input for char *name through fgets() the output doesn't work and when the name is for ex: light, the line which has lightdm also gets deleted.

group.txt (original file)

systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
messagebus:x:106:110::/var/run/dbus:/bin/false
uuidd:x:107:111::/run/uuidd:/bin/false
lightdm:x:108:114:Light Display Manager:/var/lib/lightdm:/bin/false
whoopsie:x:109:117::/nonexistent:/bin/false
avahi-autoipd:x:110:119:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
avahi:x:111:120:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/bin/false

if ex lightdm is inputted

systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
    systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
    systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
    systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
    syslog:x:104:108::/home/syslog:/bin/false
    _apt:x:105:65534::/nonexistent:/bin/false
    messagebus:x:106:110::/var/run/dbus:/bin/false
    uuidd:x:107:111::/run/uuidd:/bin/false
    whoopsie:x:109:117::/nonexistent:/bin/false
    avahi-autoipd:x:110:119:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
    avahi:x:111:120:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
    dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/bin/false

Code

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

int main()
{

    FILE *fold = fopen("D:\\C Codes\\deluser\\PFILE\\group.txt", "r"); // old file
    FILE *fnew = fopen("D:\\C Codes\\deluser\\PFILE\\group1.txt", "w"); // new temp file
    char *name = "lightdm"; // whatever user selected
    char buf[64]; 

    while (fgets(buf, 64, fold)) {

        if (!strstr(buf, name)) {

            fprintf(fnew, "%s", buf);
        }
}
return 0;
}

Upvotes: 0

Views: 63

Answers (2)

Luis Colorado
Luis Colorado

Reputation: 12668

The code doesn't seem to be incorrect, except that you have reserved very low space for the buffer, and in that case fgets() returns what fills the buffer, and then the next call brings you the rest until the new line. Give more space for the buffer, as you have lines in the files you showed above that are longer than 64 bytes.

As you don't trim the last \n character, and produce one yourself (as recommended in some of the comments) you don't see the break, and it seems that fgets is dealing with the whole lines.... that's simply not true.... lines longer than 63 chars are divided into two chunks (first of 63 ---plus one more for the \0 string terminator) and the second with the rest of the line.

You don't post the bad output, but I guess if the line containing the name you want to be filtered out is longer than 63 chars, then the last part is written (in the second run through fgets() where it doesn't have anymore the searched string)

Upvotes: 0

kiran Biradar
kiran Biradar

Reputation: 12732

  1. for the first issue::

    The problem i'm having is whenever I take input for char *name through fgets() the output doesn't work

    It is because fgets appends \n to the output buffer, you will have to trim it.

    how-to-trim-n-from-the-end-of-fgets-output

  2. for the second issue.

    strstr will match substring and in order to mtch the exact word using strstr refer Matching an exact word using in c.

Upvotes: 1

Related Questions