-1

What I want to do is the following:

  • read 1st line from file.txt
  • remove the \n from it.
  • print it

For that purpose, my code is:

main(){
    char line_one[100];
    FILE *fp;
    fp = fopen("file.txt", "r");
    fgets(line_one, sizeof line_one, fp);

    printf("%s", line_one);

    char line_one_NEW[100];
    strncpy(line_one_NEW, line_one, strlen(line_one)-1);

    printf("%s", line_one_NEW);

    return 0;
}

The result that I am getting is:

test
test�{r

Why is there strange stuff after the line_one_NEW ?

horro
  • 1,262
  • 3
  • 20
  • 37
  • 1
    `strncpy()`, despite its name, was not designed to work with *strings*. It does not deal with `'\0'` in the usual way: it may leave the terminator out of the final array or it may fill the array with several of them. – pmg Jun 22 '17 at 11:01
  • `fp = fopen("file.txt", "r");` -> Could do with checking if `fp` is not null – Ed Heal Jun 22 '17 at 12:42
  • Possible duplicate of [Removing trailing newline character from fgets() input](https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input) – Baldrickk Jun 22 '17 at 12:56

6 Answers6

4

Use strrchr for a reverse search.

char* pos = strrchr(line_one, '\n');
if (pos) *pos = 0;

Your method that copies the string over is incorrect, because you miss to add a null character to terminate the string.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • I like to see old-hands answers. Beat me sir! +1 – Soner from The Ottoman Empire Jun 22 '17 at 11:04
  • `strchr()` should also work. `fgets()` will never write two (or more) `'\n'` to the array. – pmg Jun 22 '17 at 11:05
  • What if input has `\n` per se? @pmg – Soner from The Ottoman Empire Jun 22 '17 at 11:07
  • @snr: the following characters are buffered, ready to be read on the (probable) next time through the loop. – pmg Jun 22 '17 at 11:09
  • @snr `fgets()` stops at the first `\n`, that's the whole point of the function. –  Jun 22 '17 at 11:09
  • The workings of `strchr()` and `strrchr()` on a string coming from `fgets()` should be very similar. Nevertheless, `strchr()` is, for me, easier to visualize. – pmg Jun 22 '17 at 11:12
  • This is interesting, but the *actual* question is: *"Why is there strange stuff after the line_one_NEW ?"* – Nisse Engström Jun 22 '17 at 11:58
  • 1
    @NisseEngström-- the title of the question is, "removing `\n` from a line that comes from `fgets()`." – ad absurdum Jun 22 '17 at 11:59
  • Note that strrchr doesn't do a reverse search, it still searches forwards, but returns the location of the last match found. As we are searching for the end of the string though, there isn't a (significant) difference in performance (`strrchr` will go on to read the `null`) – Baldrickk Jun 22 '17 at 12:55
  • @DavidBowling: That's not a question, it's a statement. It seems to describe the purpose of the code. The question is asked in the *body* of the post, as you'd expect. – Nisse Engström Jun 22 '17 at 12:56
  • @NisseEngström-- it is the _title_ of the question. I would say that it is the main thrust of the question. I see the question about behavior as a secondary question. IAC, I think you are being overly pedantic about this. – ad absurdum Jun 22 '17 at 12:58
  • @DavidBowling: So the OP wrote a bad title. That doesn't excuse anyone from not reading the rest of the post. The *important* issue here is the missing string terminator. It's a subtle and hard-to-find bug and *that* needs addressing. The other stuff is largely irrelevant. - This is C programming we're talking about; you're not being pedantic enough. – Nisse Engström Jun 22 '17 at 15:57
3

the easiest solution i think is strcspn() to remove \n:

buffer[strcspn(buffer, "\n")] = 0;
Waqas Amjad
  • 195
  • 1
  • 13
  • `strcspn` is already too complicated, since the second argument is a string, too. And then your method has undesired results if there isn't any newline present. – Jens Gustedt Jun 22 '17 at 11:03
  • 1
    @JensGustedt no, this method is safe. `strcspn()` will return the index of the `0` terminator if no "unaccepted" character is found. –  Jun 22 '17 at 11:04
  • @FelixPalmen Yes,this worked for me as a charm always – Waqas Amjad Jun 22 '17 at 11:06
  • How is this supposed to be applied to the code in the question? It doesn't have a `buffer` identifier. And you haven't answered *the actual* question: *"Why is there strange stuff after the line_one_NEW ?"* – Nisse Engström Jun 22 '17 at 11:54
2

For starters to remove the new line character from a string you can use the following trick

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

As for this code snippet

strncpy(line_one_NEW, line_one, strlen(line_one)-1);
printf("%s", line_one_NEW);

then at first it is logically wrong because in general the new line character can be absent in the string line_one. In this case the expression for the number of copied characters

strlen(line_one)-1

will be wrong.

But in any case if you use the standard function strncpy you should explicitly to append a terminating zero. For example

strncpy(line_one_NEW, line_one, strlen(line_one)-1);
line_one_NEW[strlen(line_one)-1] = '\0';

Or if you want to copy the first line into the second line without the new line character but keeping the new line character in the first line then you can write

size_t n = strcspn( line_one, "\n" );
strncpy( line_one_NEW, line_one, n );
line_one_NEW[n] = '\0'; 
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

char * strncpy ( char * destination, const char * source, size_t num );

No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow).

Therefore, it should be:

char line_one_NEW[100] = {0};
strncpy(line_one_NEW, line_one, strlen(line_one)-1);
sameerkn
  • 2,209
  • 1
  • 12
  • 13
0

In order to remove the "\n" from the line you need to write this code line after the fgets(I will write the line of the fgets too):

fgets(str,MAX_CHARACTERS,fp); 
//MAX_CHARACTERS is the maximum of characters that you want to get from the fgets
str[strcspn(str,"\n")]=0;

Hope that my comment was helpful for you ;)

happymancer
  • 45
  • 1
  • 10
-5
strncpy(arg1 , arg2 ,  integer);

a function in the string.h library means Copy first n chars of arg2 into arg1

strlen(str) :

a function in the string.h library , is used to count the number of the characters in the string str and return integer int , Because we don't want to write '/n' , so it avoids last character which is '/n'by writing

strlen(line_one)-1
The Hungry Dictator
  • 3,444
  • 5
  • 37
  • 53
  • 1
    You're just repeating what OP was already doing and you're also failing at writing a `'\0'` at the end of the new string. – SiggiSv Jun 22 '17 at 11:44