-4

So I use fgets to get strings from a file then add them to an array. But before I add them to the array, I want to strip the "\n". This is what I used for that

strtok(str,"\n");
array[i] = strdup(str);

array is initialized in char *array[32];

Now the functions work perfect, I can use the array and it's elements how I wan't to. However, whenever I try to print the elements, it doesn't work properly.

for example if array[i] = hello

printf("%s:TEST",array[i]);

will print

:TEST

but

printf("%s\n:TEST",array[i]);

will print

hello
:TEST

I need it to be on the same line, so I can't use \n, and it just weird how it will only print if there is a new line after it.

Edit: not strdup(strok) but strdup(str)

Edit: Complete example of code:

char *array[32]
char holder[32]


FILE *fp = fopen("file.txt","r");

int i = 0;

while(fgets(holder, 100, fp)){
    strtok(holder,"\n");
    array[i] = strdup(holder);
    i++;

}
fclose(fp);

printf("word: %s",words[1]);

array[i] will not print unless there is a '\n' after it, as mentioned above

Edit: added print function text file is in format

string1
string2
string3
Yee Kee
  • 137
  • 6
  • What is `array[i] = hello` supposed to do? – Weather Vane Mar 15 '19 at 17:03
  • 3
    `strdup(strok)` - huh? `strtok` is a function. Please show [mcve]. – Eugene Sh. Mar 15 '19 at 17:03
  • `printf()` will not flush the output until it sees a new line character (or the internal output buffer of `printf()` becomes full) unless you explicitly flush the output. Check out `fflush(stdout)`. – Richard Chambers Mar 15 '19 at 17:06
  • 1
    @RichardChambers True, but the described behavior is about having a *partial* output of `printf` – Eugene Sh. Mar 15 '19 at 17:07
  • Perhaps you meant to write `array[i] = strdup(str);` having used `strtok()` to truncate the input string. Anyway, here is a better way for [removing trailing newline character from fgets() input](https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input/28462221#28462221) – Weather Vane Mar 15 '19 at 17:07
  • @EugeneSh. I am commenting on "I need it to be on the same line, so I can't use \n, and it just weird how it will only print if there is a new line after it." from the post. – Richard Chambers Mar 15 '19 at 17:08
  • 1
    @RichardChambers the part that is missing is *before* `":TEST"` so it can't be a buffer flushing issue. – Weather Vane Mar 15 '19 at 17:10
  • @WeatherVane I didn't say it was. Read the end of the post. – Richard Chambers Mar 15 '19 at 17:11
  • 1
    Without the MCVE it is guesswork. Perhaps the string contains a CR (carriage return) and so the first part is overwritten without a LF (line feed, newline) also being output. Function `strtok` was looking for `'\n'` but suppose the string contains `'\r'` instead. Try printing the value (with `%d` format spec) of each character in the string. – Weather Vane Mar 15 '19 at 17:16
  • @EugeneSh. sorry I mean strdup(str) – Yee Kee Mar 15 '19 at 17:21
  • @WeatherVane I've tried using 'str[strcspn(str, "\n")] = 0;' like the post says, but I get the same result. – Yee Kee Mar 15 '19 at 17:24
  • 3
    One [mcve] worth hundreds of words. And your question is going to get closed without it anyway. So please, stop wasting our and your time and post one. – Eugene Sh. Mar 15 '19 at 17:28
  • Please printf each character value of the string in decimal to see what it actually contains. I predict a `13` will be in there. And, please read every comment carefully. – Weather Vane Mar 15 '19 at 17:28
  • @EugeneSh. sorry, i've edited in a better example – Yee Kee Mar 15 '19 at 17:38
  • Your edited code does not show the `printf` line. Note the "Complete" part of MCVE. – Eugene Sh. Mar 15 '19 at 17:39
  • `dump(array, 8/*guessing*/);` and `void dump(void const *p, int n) { char unsigned const *x = p; while(n--) fprintf(stderr, " 0x%02x", *x++); }` – pmg Mar 15 '19 at 17:40
  • @EugeneSh. it is the same print function as above before the edit, and it prints the same way – Yee Kee Mar 15 '19 at 17:48
  • 1
    *Complete example of code* -- it doesn't have the printing which is essential to the problem. Can you just "copy and paste" the exact code you are running? – Ajay Brahmakshatriya Mar 15 '19 at 17:55
  • 1
    Try `strtok(str, "\r\n");` – Weather Vane Mar 15 '19 at 18:03
  • @AjayBrahmakshatriya I've done that now – Yee Kee Mar 15 '19 at 18:12
  • @WeatherVane works! thank you! – Yee Kee Mar 15 '19 at 18:13
  • @WeatherVane seems like you nailed the problem. But this doesn't seem like the right solution, because `\r` could not be there and then the `strtok` wouldn't behave correctly. Could you perhaps write down a full answer which tokenizes on `\n` an removes the `\r` if it there at the end. Also explaining why there was a problem in the first place. – Ajay Brahmakshatriya Mar 15 '19 at 18:16
  • @AjayBrahmakshatriya I can't: it's been put on hold and it does not seem right for me to abuse my privilege and re-open the question so I can post an answer. – Weather Vane Mar 15 '19 at 18:29
  • @WeatherVane I voted to reopen at that time, because OP did add somewhat of an MCVE. I think it only needs one more right now. – Ajay Brahmakshatriya Mar 15 '19 at 18:49
  • @AjayBrahmakshatriya ah, I see now that I can only reopen a question I closed myself, as a duplicate. – Weather Vane Mar 15 '19 at 18:51
  • @WeatherVane that seems fair! – Ajay Brahmakshatriya Mar 15 '19 at 20:06
  • duplicate: [printf without \n does not display text when placed before while(1)](https://stackoverflow.com/q/7384110/995714), [Why does printf not flush after the call unless a newline is in the format string?](https://stackoverflow.com/q/1716296/995714), [why does "printf" not work?](https://stackoverflow.com/q/39180642/995714)... But your example is still not compilable: `char *array[32] char holder[32]` doesn't work. – phuclv Mar 16 '19 at 03:09
  • @YeeKee: you can accept one of the answers by clicking on the grey checkmark below its score. – chqrlie Apr 13 '19 at 11:54

2 Answers2

0

The C library function char *strtok(char *str, const char *delim) breaks string str into a series of tokens using the delimiter delim. So it's not a function the treats the string as reference but as value. So when you do something like:

strtok(str, "\n");

str will have the same value as before. If you want the first token, as in, the str value until it finds "\n" for the first time, you have to do something like.

array[i] = strtok(str, "\n");

or

char *token = strtok(str, "\n");
array[i] = strdup(token);

or anything like that.

CODE:

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

int main () {
  char buff[100];
  char *array[32];

  FILE *fp = fopen("file.txt","r");

  int i = 0;
  while(fgets(buff, 100, fp)){
    char* token = strtok(buff,"\n");
    array[i] = strdup(token);
    printf("%s:TEST\n", array[i]);
    i++;
  }

  fclose(fp);
  return(0);
}

file.txt

HELLO
BYE

Output:

HELLO:TEST
BYE:TEST
  • Unfortunately, this gives the same result. – Yee Kee Mar 15 '19 at 17:49
  • Your explanation is incorrect: `buff` is modified by `strtok` and the `'\n'` is overwritten with a `'\0'`, so using the return value of `strtok()` or `buff` should give the same behavior. The problem is elsewhere. – chqrlie Mar 26 '19 at 00:07
0

Your have multiple problems in the code fragment posted:

  • array is not initialized in char *array[32], it is just defined this way and uninitialized if this definition occurs inside the body of a function. Incidentally, the ; are missing from the definitions in the code fragment.

  • the size of holder is 32, yet you pass 100 to fgets() causing potential buffer overflows.

  • printf("%s:TEST",array[i]); is not present in your code, you did not post the offending code.
  • the final output, printf("word: %s",words[1]); uses an undefined object words, and the index 1 may be out of range if you only input a single word.

You must post the actual program with the offending behavior. The code fragment is inconsistent with the behavior you describe.

chqrlie
  • 98,886
  • 10
  • 89
  • 149