0

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;
}
  • `fopen` can fail, and often does for example if a file does not exist. You absolutely __must__ check if `fopen` fails and acct accordingly. – Jabberwocky May 18 '20 at 11:16
  • the old file definitely exists – Prometheus_26 May 18 '20 at 11:18
  • 2
    That's not an excuse, change your code and do the checks, to eliminate this red herring. Maybe there is a typo in your code. I've seen it so many times before in other questions. – Jabberwocky May 18 '20 at 11:19
  • Also show a minimal `group.txt` file that allows to reproduce the problem along with the actual and the expected output. – Jabberwocky May 18 '20 at 11:21

2 Answers2

1
  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.

kiran Biradar
  • 12,700
  • 3
  • 19
  • 44
  • Although true, I don't see the relevance - OP isn't outputting a newline. It looks as though OP does not realise that `"light"` will be found as a substring of `"lightdm"`. – Weather Vane May 18 '20 at 11:30
  • @WeatherVane I agree with you, I have updated the answer with relevant link. – kiran Biradar May 18 '20 at 11:31
  • Yes, OTOH the presence of the newline will prevent `strcmp` from finding the exact match for `"light"`. – Weather Vane May 18 '20 at 11:32
  • @WeatherVane Do you think we should mark this question as duplicate of above answers? – kiran Biradar May 18 '20 at 11:32
  • I think your answer should point out that the newline needs to be removed *and* `strcmp` needs to be used. Of course the newline then needs adding back in the `fprintf`. – Weather Vane May 18 '20 at 11:34
  • @WeatherVane I don't think `strcmp` will help here. Can you please recheck the question, OP has added the examples. – kiran Biradar May 18 '20 at 11:35
  • Hmm, OP wants to remove a line that says `"light"` but not one that says `"lightdm"`. – Weather Vane May 18 '20 at 11:36
  • No I want to remove the line if the name is in the file. In this case `"lightdm"` – Prometheus_26 May 18 '20 at 11:38
  • @4shwin_26 yes, 1st. Trim the newline if you are reading search string from stdin. 2. `strstr` will match the substring, thus you need some additional check as suggested by the link provided in the answer. – kiran Biradar May 18 '20 at 11:42
  • No, he doesn't need to trim the final `\n` if he is not going to do more on the lines than to copy them to the output. Trimming the intput is a question of taste, and he OP doesn't need to implement something that is not required. – Luis Colorado May 19 '20 at 23:08
0

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)

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31