0

I compile my code then run: $ ./a.exe < input.txt For some reason it doesn't read the first character (t is missing from test in first line) and there is also a weird character at the end. How do I combat these two errors? Thanks

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

int main(void) {    
    char c = getchar();    
    while (c != EOF){
        printf("%c ",c); 
        c = getchar();
    }
    return (0);
}        

Sample execution:

$ ./a.exe < input.txt
  e s t   l i n e   o n e
 t e s t   l i n e   t w o
 f i n a l   l i n e ▒ 
smac89
  • 39,374
  • 15
  • 132
  • 179
  • 2all the answering people: please stop using "char c" in your snippets. All char-related functions take and return ints, not chars, and so is EOF. int c -- correct, char c -- wrong. – user3125367 Oct 01 '14 at 02:52

3 Answers3

3

First, note that when you while first executes, c is unassigned.

Then, notice that when the next-to-last character is read, your while test will pass, resulting in reading and printing another character - so you are seeing the visual representation of the EOF as the last character.

If you are piping a file into this program, I suspect something before the lines you wrote is resulting in the T being omitted.

You could avoid the other problems by doing something like:

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

    int main(void) {    
        int c = getchar();    
        while (c != EOF){
            printf("%c ",c); 
            c = getchar();
        }
        return (0);
    }

Edit: I would also suggest we follow user3125367's suggestion in the comment above, which eliminates some sneaky casting from int to char. I've edited above to use int. This may also let you use the %n to see what the actual value of the first character is in your file, and/or it may solve the problem (i.e., the first character in your file may have looked like a T, but been a non-ASCII character with a value greater than 255.)

Dronz
  • 1,970
  • 4
  • 27
  • 50
  • This is a good example of a case where a do-while construct can be more useful and easier to read than just a while. – millinon Oct 01 '14 at 02:49
  • Your solution fixed the EOF showing up at the end, but the first character is still omitted. http://gyazo.com/a66ebc666b56cbc381b6ff4bea8408bf – ImBadAtProgramming Oct 01 '14 at 02:52
  • Edit the question to show us the code before the code you showed. I think it must happen before then. – Dronz Oct 01 '14 at 02:53
  • my whole program is just those lines, nothing more – ImBadAtProgramming Oct 01 '14 at 02:57
  • Either that, or your input file could be interesting. It looks like there IS a character being read, but it's not displaying as anything visible. You could switch the program to display the integer character code value of each character, to see what it thinks the first character is. – Dronz Oct 01 '14 at 02:57
  • i.e. try printf("%n ",c); – Dronz Oct 01 '14 at 02:57
  • that gives: Segmentation fault (core dumped) – ImBadAtProgramming Oct 01 '14 at 03:02
  • okay so using ints worked when I made the output integers for the ASCII values, there it was able to show the t as 116, but printing as %c still skips the t. Any idea? Just curious, thanks – ImBadAtProgramming Oct 01 '14 at 03:31
  • Hmm, odd. 116 is t, so I think it should work. You could put printf("Output:\n"); before the code, to see if it is just something weird with your shell. – Dronz Oct 01 '14 at 03:37
0

I don't see anything remarkable about redirecting stdin. It looks like your text file effectively has ASCII characters (is that right--no strange symbols?). The file may be encoded as UTF-8 (up to 4 bytes per character) or another multibyte system. For UTF-8 the values of the ASCII characters are preserved, i.e. all less than 128, so they can be converted to signed char without loss of precision. In general though, a character in UTF-8 could be up to 4 bytes in size, thus requiring storage at least the size of int. Your code is a bit awkward, but I don't see right away why it shouldn't work unless the char type is the problem. However, I tried with both int and char and got the same result (it worked fine). Here's my code (with the char type commented out):

#include <stdio.h>
int main()
{//char c; // Wrong.  getchar returns int.
   int  c;
   while ( (c = getchar()) != EOF) printf("%c", c);
   return 0;
}

The output was the same for either char c; or int c; as follows:

Test line 1
Test line 2
Last Line, no CR

Edit: The alternating spaces indicate that your input.txt file must be encoded as UCS-2 (two byte Unicode), or something similar; every other byte is a zero since your text character values are all less than 127. The zeros print as spaces since they are "unprintable." I'm guessing here (don't have time to check it out) that the leading space on your first output line is due to a two byte BOM (Byte Order Mark), either FF FE or FE FF, which are likely to be unprintable. Save your input file as UTF-8 or ANSI and try again.

Community
  • 1
  • 1
riderBill
  • 818
  • 9
  • 16
  • Did you edit your coded since posting the original question? Also, did you type the alternating spaces in input.txt, or are they an artifact of the code? – riderBill Oct 01 '14 at 14:09
-2

Not sure how the first error is happening, but this should fix the second one:

int c;   
for (c = getchar(); c != EOF; c = getchar()) {
    printf("%c ",c);          
}

Double check to make sure that your file does infact contain the first character you are missing.

The reason you use int when reading characters with getchar is because the EOF constant is an integer and it is not guaranteed to represent a valid character value. So when you compare your character to EOF, even if you have encountered EOF, it will not evaluate to true when compared to the actual EOF constant.

You will also notice that those functions you use such as getchar, putchar, etc, all take and return ints not char (I know, confusing right?). I believe this decision was made primarily so that support of EOF can be added without sacrificing precious bytes.

Community
  • 1
  • 1
smac89
  • 39,374
  • 15
  • 132
  • 179