0

I have a char* line on which I used while (fgets(line, line_size, fNames) != NULL). now the problem is I also get a new line character, which I want to strip.

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

int main() {
    int i;
    char fileName[30];
    FILE *fNames, *fCurrent;
    char *line = NULL, command[100];
    char letters3[3];
    size_t len = 0;
    //size_t read;
    const size_t line_size = 300;
    line = malloc(line_size);
    if (access("fileNames.lst", F_OK) == -1)
        system("crunch 3 3 abcd -o fileNames.lst");
    else
        printf("fileNames.lst already exists.\n");
    fNames = fopen("./fileNames.lst","r");

    while (fgets(line, line_size, fNames) != NULL) {
        printf("Making File: %s.lst\n", line);
        strcpy(command, "crunch 8 8 -t ");
        strcpy(command, line);
        strcpy(command, strcat(command," -o"));
        puts(command);
        strcpy(line, strcat(line, ".lst"));
        fCurrent = fopen(line, "w");
        //system(command);
        fclose(fCurrent);
        //system("read -r -p \"Press space to continue...\" key");
    }
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Yash Gulati
  • 82
  • 2
  • 3
  • 11

2 Answers2

3

There are problems in your code:

  • You do not check the return value of fopen(), nor that of malloc().

  • strcpy(command, strcat(command," -o")); and strcpy(line, strcat(line, ".lst")); invoke undefined behavior as you call strcpy on overlapping strings.

  • strcpy(command, line); overwrites the string you just copied to command with strcpy(command, "crunch 8 8 -t ");.

  • You do not check the lengths before copying or concatenating strings into line and command. You should use snprintf() for both a safer and simpler method.

To get rid of the trailing linefeed in line left by fgets(), you can either write:

line[strcspn(line, "\n")] = '\0';

or you can write this:

char *p = strchr(line, '\n');
if (p != NULL)
    *p = '\0';

or even this one that removes the linefeed at the end of the string:

size_t len = strlen(line);
if (len > 0 && line[len - 1] == '\n')
    line[--len] = '\0';

With both of the latter methods, you can track whether there was indeed a linefeed or not. The absence of a linefeed at the end of the line can mean one of several possibilities:

  • The line was truncated because it does not fit in the buffer provided. You should be careful to handle this condition because the string read does not correspond to the actual file contents. It could happen in your case if a filename is longer than 298 bytes, which is possible on many modern file systems.

  • The end of file was reached but no linefeed is present in the file at the end of the last line. This is probably not an error, but could indicate that the input file was truncated somehow.

  • The input file contains a '\0' byte, which causes early termination of the line read by fgets(). This would not be allowed as part of a filename and is quite unlikely to occur in text files, unless the file was encoded as ucs2 or UTF-16.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
1

I think you are searching for this one. It is very easy to use and it does the job.

line[strcspn(line, "\n")] = '\0';
Mirakurun
  • 4,859
  • 5
  • 16
  • 32
  • thanks bro. your idea is working and
    line[strcspn(line, "\n")] = '\0';
    is also working.
    – Yash Gulati Aug 17 '16 at 14:04
  • Would the downvoter care to explain? this method is simple and safe, it removes the linefeed if present and does nothing if there is no linefeed. – chqrlie Aug 17 '16 at 14:05
  • This only removes the first occurrence of `\n` which is not what OP is asking (even though he uses fgets, the question itself doesn't say so). The question is about "the end of char *". The assertion that the first newline is also the last one may be wrong. – Tim Aug 17 '16 at 14:09
  • strtok(line, "\n"); is also working – Yash Gulati Aug 17 '16 at 14:09
  • 2
    @TimF: I'm afraid you are wrong: there can only be one linefeed in the buffer filled by `fgets()`, and it is necessarily at the end of the string. – chqrlie Aug 17 '16 at 14:22
  • @chqrlie That's correct but the question is `strip new line character from end from char*` and not `strip new line character from end from char* given by fgets`. The fact that OP uses fgets is not in the title. In my opinion the answer must be related to the title more than to the details OP hides here and there in the description of its problem. – Tim Aug 17 '16 at 14:27
  • 1
    @TimF: come on, the context of the question is unambiguous: *I have a `char* line` on which I used `while (fgets(line, line_size, fNames) != NULL)`. now the problem is I also get a new line character, which I want to strip.* The question is more general and poorly expressed, but your downvote is excessive. Mirakurun should have given an explanation, but his answer is correct. – chqrlie Aug 17 '16 at 14:28
  • @chqrlie I won't say it's 100% crystal clear nor that it's unambiguous, but if someone is looking how to remove the newline from the end of a char and find this question (because it does match the title) the person could be disappointed to see the FIRST newline replaced instead of the last (i.e. `at the END of char *` ) – Tim Aug 17 '16 at 14:31
  • @chqrlie And to be fair, I just upvoted your solution because of the last one, since looking for the newline from the end of the char* and not from the beginning is indeed the/a correct answer. – Tim Aug 17 '16 at 14:33
  • 1
    @TimF: I understand your reasoning, but anybody copying code from an answer without some understanding of the context is up for worse disappointments. – chqrlie Aug 17 '16 at 14:34
  • @chqrlie Well guys, when I answered this question, it didn't even have the code in it. Look at the edits and find the first version of this question. I wrote it quickly just to give the OP an answer before the question gets closed, so he can continue with his work. There are a lot of people here who would rather vote to close the question than to answer, so I just wanted to help the OP. I voted up your answer chqrlie, it's very good. All the best! – Mirakurun Aug 17 '16 at 14:39