I am working on inputting a 2d pixel array from a PPM file with the one I am testing being of width and length 5. Also I am aware that in a ppm file that is rgb it has 3 color values not just one. I had forgotten that before I wrote this code, but the problem still persists even with the update to it and the problem still exists in the same way. I have simplified the problem to just the array as to isolate the problem. From what I can tell this seems to be both dropping characters and replacing some with new line characters as well. Any insight into why this is happening would be greatly appreciated and if I forgot to add something I will update this as soon as I am aware.
#include <stdio.h>
int main(int args, char *argv[]) {
int w = 5, h = 5;
FILE *f = fopen(argv[1], "rb");
int c = 'a';//I am setting this so as to avoid the off chance of c being defined as EOF
for(int i = 0; i < h && c != EOF; i++) {
for(int j = 0; j < w && (c = fgetc(f)) != EOF; j++) printf("%c", c);
fgetc(f);//To remove the '\n' character I am not using fgets because it stops at '\n' character and it is possible for a rgb value to be == to '\n'
printf("\n");
}
fclose(f);
return 0;
}
Test File I am using:
12345
abcde
12345
abcde
12345
Output I am getting:
12345
abcd
123
5
ab
de
1
Thanks in advance!
Edit: This is running on the windows 10 command prompt
The problem is that '\n' on a Windows machine actually ends up producing two characters, a carriage return (ASCII code 13) and a line feed (ASCII code 10). When you open a file in binary mode, those line endings are not translated back to a single character. You're only accounting for one of these characters, so you're getting off by a character on each line you read.
To illustrate this, replace your printf("%c", c);" with printf("%d ", c);. I get the following output:
49 50 51 52 53
10 97 98 99 100
13 10 49 50 51
53 13 10 97 98
100 101 13 10 49
You can see those 10s and 13s shifting through.
Now try adding a second fgetc(f); to eat the line feed and it will work much better. Keep in mind, however, that this only works on files with CRLF line endings. Port it to Linux or Mac and you will have more troubles.
Related
I created a file like this
a v
bb
e
And I didn't press enter after typing e in the last line.
So there are four characters in the first line 'a',' ','v','\n'.
There are three characters in the second line 'b','b','\n'.
And there is one character in the last line 'e'.
So there are totally 8 characters in this file. But when I count the characters using the following C program:
#include<stdio.h>
/* count characters in input; 1st version */
int main()
{
long nc;
nc = 0;
while (getchar() != EOF) {
++nc;
}
printf("%ld\n", nc);
return 0;
}
It gave me 9. Even when I use wc command to count, it is still 9. Why?
There's reasoning in favor of having all lines terminated with a newline character:
Why should text files end with a newline?
And there are text editors that are set up to add a trailing newline character automatically (if not already there):
How to stop Gedit, Gvim, Vim, Nano from adding End-of-File newline char?
Probably that is why you observe the unexpected file size.
To inspect the actual content of such files, I like to use hexdump:
$ hexdump -C test
00000000 61 20 76 0a 62 62 0a 65 0a |a v.bb.e.|
00000009
I am trying to loop over stdin, but since we cannot know the length of stdin, I am not sure how to create the loop or what condition to use in it.
Basically my program will be piped in some data. Each line in the data contains 10 characters of data, followed by a line break (So 11 characters per line)
In pseudocode, what I am trying to accomplish is:
while stdin has data:
read 11 characters from stdin
save 10 of those characters in an array
run some code processing the data
endwhile
Each loop of the while loop rewrites the data into the same 10 bytes of data.
So far, I have figured out that
char temp[11];
read(0,temp,10);
temp[10]='\0';
printf("%s",temp);
will take the first 11 characters from stdin,and save it. The printf will later be replaced by more code that analyzes the data. But I don't know how to encapsulate this functionality in a loop that will process all my data from stdin.
I have tried
while(!feof(stdin)){
char temp[11];
read(0,temp,11);
temp[10]='\0';
printf("%s\n",temp);
}
but when this gets to the last line, it keeps repeatedly printing it out without terminating. Any guidance would be appreciated.
Since you mention line breaks, I assume your data is text. Here is one way, when you know the line lengths. fgets reads the newline too, but that is easily ignored. Instead of trying to use feof I simply check the return value from fgets.
#include <stdio.h>
int main(void) {
char str[16];
int i;
while(fgets(str, sizeof str, stdin) != NULL) { // reads newline too
i = 0;
while (str[i] >= ' ') { // shortcut to testing newline and nul
printf("%d ", str[i]); // print char value
i++;
}
printf ("\n");
str[i] = '\0'; // truncate the array
}
return 0;
}
Program session (ended by Ctrl-Z in Windows console, Ctrl-D in Linux)
qwertyuiop
113 119 101 114 116 121 117 105 111 112
asdfghjkl;
97 115 100 102 103 104 106 107 108 59
zxcvbnm,./
122 120 99 118 98 110 109 44 46 47
^Z
I'm a beginner in C, and I've got problem I can't figure out, and wasn't able to find a solution on other threads here.
I'm trying to read integers from a keyboard input/ txt file with the following code:
int grades[MAX_GRADES_LENGTH]={0}, histogram[HISTOGRAM_SIZE]={0};
int maxGradesHistogramBucket=0, median=0, gradesLength=0;
double avg=0.0;
int grade=0;
printf("Enter grades:\n");
while (scanf("%d",&grade) != EOF)
{
grades[gradesLength]=grade;
gradesLength=gradesLength+1;
}
I'm supposed to set these "grades" in the grades[] array and count the length of the array along the loop.
Somehow the loop is misbehaving, it seems that some inputs are ok with the loop, but for some inputs(most of them actually) the scanf() doesn't get the EOF, whether it's an actual end of file, or the ^D command in the terminal.
I've heard the scanf() is not the most reliable method to read data, but unfortunately I can't use anything else since we haven't learned any other method in class so we can only use scanf() on our homework.
I've tried to change the!= EOF with == 1 and its all the same.
for the input
100 0 90 10 80 20 70 30 60 40 50
for example it works fine.
but for the input:
0 50 100
the loop is infinite.
I'm using a macbook pro btw (if it matters).
Any ideas?
If you type a letter instead of a number, scanf() will return 0 (as in, "zero successfully converted numbers") and not EOF (as in, "there was no data left to read"). The correct test is to ensure that you got the expected number of values — in this case, 1:
while (scanf("%d", &grade) == 1)
If you need to know whether you got to EOF or got no result (but reading the rest of the line might clear the problem), then capture the return value from scanf():
int rc;
while ((rc = scanf("%d", &grade)) == 1)
{
}
if (rc != EOF)
…read the rest of the line, or at least the next character, before resuming the loop…
And, if you really want to, you could then write:
int rc;
while ((rc = scanf("%d", &grade)) != EOF)
{
if (rc == 1)
grades[gradesLength++] = grade;
else
{
printf("Discarding junk: ");
int c;
while ((c = getchar()) != EOF && c != '\n')
putchar(c);
putchar('\n');
if (c == EOF)
break;
}
}
The code in the else clause could plausibly be put into a function. It might also report the messages to standard error rather than standard output. It is courteous to let the user know what it was that you objected to. You could stop before newline with a different test (&& !isdigit(c) && c != '+' && c != '-', using isdigit() from <ctypes.h>). However, the user doesn't have a chance to re-edit the stuff they put after the letters, so you may be going to misinterpret their input. It is probably better just to throw away the rest of the line of input and let them start over again.
As chux noted, after reading a character that could be part of an integer, that character needs to be put back into the input stream. Therefore, if I were going to analyze the rest of the line and restart scanning at the first data that could actually be part of an integer, I'd consider using something like:
#include <ctype.h>
static inline int could_be_integer(int c)
{
return isdigit(c) || c == '+' || c == '-');
}
and then the else clause might be:
else
{
printf("Discarding junk: ");
int c;
while ((c = getchar()) != EOF && c != '\n' && !could_be_integer(c))
putchar(c);
putchar('\n');
if (could_be_integer(c))
ungetc(c, stdin);
else if (c == EOF)
break;
}
This gets messy, as you can see. Sometimes (as Weather Vane noted in a comment), it is easier to read a line with fgets() and then use sscanf() in a loop (see How to use sscanf() in a loop?). Be wary of suggestions about Using fflush(stdin); it isn't automatically wrong everywhere, but it won't work on a MacBook Pro under normal circumstances.
On the whole, simply ignoring the rest of the line of input is usually a better interface decision.
It works for me.
I enclosed your snippet thus:
#include <stdio.h>
#include <errno.h>
#define MAX_GRADES_LENGTH 20
#define HISTOGRAM_SIZE 20
main()
{
int grades[MAX_GRADES_LENGTH]={0}, histogram[HISTOGRAM_SIZE]={0};
int maxGradesHistogramBucket=0, median=0, gradesLength=0;
double avg=0.0;
int grade=0;
int i;
printf("Enter grades:\n");
while (scanf("%d",&grade) != EOF)
{
grades[gradesLength]=grade;
gradesLength=gradesLength+1;
}
if (errno)
perror("grade");
for (i = 0; i < gradesLength; ++i) {
printf("%d\n", grades[i]);
}
}
and ran it:
$ a.out
Enter grades:
100 0 90 10 80 20 70 30 60 40 50
100
0
90
10
80
20
70
30
60
40
50
$ a.out
Enter grades:
0 50 100
0
50
100
$
Perhaps you are looking in the wrong place. Maybe the bug is in your output routine?
Personally, if had to do this, given some ambiquity over what scanf returns when, and without rewriting it, then this small change is probably more reliable:
int i, r;
printf("Enter grades:\n");
while ((r = scanf("%d",&grade)) > 0)
So here is the code that I am attempting to get to work:
char* inFile = "input.txt";
FILE *out = fopen("output.txt", "a+");
int i = 0
while(i < 5){
int countFound = findWord(inFile, keyWord[i]);//returns count of keywords in given file
fprintf(out, "%s: %d\n", keyWord[i], countFound);
i++;
}
fclose(out);
The output of this code is:
youshouldsee1
: 3
youshouldsee2
: 3
youshouldsee3
: 3
youshouldsee4
: 3
youshouldsee5: 1
Expected output:
youshouldsee1: 3
youshouldsee2: 3
youshouldsee3: 3
youshouldsee4: 3
youshouldsee5: 1
I don't really understand why the output is like that, shouldn't it print the string and the int then a new line? Also note that there is not a newline after the last line and there should be. I did some testing and I noticed that if I changed the fprintf statement to fprintf(out, "%s\n", keyWord[i]); the output is:
youshouldsee1
youshouldsee2
youshouldsee3
youshouldsee4
youshouldsee5
Which is formatted much better. Again note that there is not a newline after the last line and there should be.
I noticed that while doing this with just printf statements I get the exact same problem, but the output is slightly more messed up.
Does anybody know what causes this specific issue? Much appreciated.
The array keyWord[] is a double pointer, I'm not sure if that makes a difference or not, but I thought that I would mention it. It is declared like so char** keyWord;. And it was created as follows:
char *tempWord = "something";
keyWords[x] = strdup(tempWord);
That could be totally irrelevent but I thought it was best to mention it.
You likely have some carriage return characters ('\r' or 0x0D) and/or backspace characters ('\b' or 0x08) in your keyWord[i] strings.
CRs and backspaces don't print ordinarily to terminals and instead move the terminal cursor—CRs move the cursor to the beginning of the current line, and backspaces move the cursor backwards one character. When subsequent characters are printed, they overwrite what was there before. So this code
printf("foobar\rbaz\n");
results in this output
bazbar
and this code
printf("foo\bbar\n");
results in this output
fobar
If you look at the raw bytes of the output without printing it to the terminal, you should see the CRs and backspaces plain as day. I like to use the program hexdump(1) to do that. For example:
$ echo -e 'foobar\rbaz'
bazbar
$ echo -e 'foobar\rbaz' | hexdump -C
00000000 66 6f 6f 62 61 72 0d 62 61 7a 0a |foobar.baz.|
0000000b
So I'd suggest looking at the raw data in your program's output and find out where the pesky characters are, and then figure out how to get rid of them.
Sorry for asking very simple question.I'm new to coding.
Input txt file
5,3
001
110
111
110
001
I need to print the output as
U1: 001
U2: 110
U3: 111
U4: 110
U5: 001
Upto now I was able to print the contents with this:
#include <stdio.h>
void main() {
FILE *fopen(), *fp;
int c;
fp = fopen("read.txt","r");
c = getc(fp) ;
while (c!= EOF) {
putchar(c);
c = getc(fp);
}
fclose(fp);
}
Can Anybody tell how should I proceed?
Most of your work is done inside the while loop.
But you're not doing enough work ...
a) you need to count lines
b) you need to print the "U#"
Suggestion: create a variable for the line counting business and rewrite your loop to consider it. Here's a few snippets
int linecount = 0;
printf("U%d: ", linecount)
if (c == '\n') linecount += 1;
Oh! You really shouldn't add the prototype for fopen yourself. It is already specified with #include <stdio.h>.
And well done for declaring c as int. Many people do the error of declaring it char which is incompatible with EOF and all the range of characters
I would read the data a line at a time with fgets. When you have a complete line in a buffer, it'll be pretty easy to get fprintf to put in your line header with a format like "U%d: %s\n".