Okay so I'm trying to read in a PPM file (p3 format) and I want to read the comments (which are #s in ppm files).
The problem is that I don't know how to make C do what is in my head, heres what I want it to do.
read the file
where # appears, store all characters until the %\n character appears
repeat until all comments are read
I understand that I should be using some variations of getc, fgets and fscanf but I don't know how to apply them in this context.
I would put some code up showing what i've tried with getc, fgets and fscanf but to be brutally honest I have no idea how to use any of those functions and none of the info I can find seems to help and I really don't think any of my implementations are even doing anything.
Does anyone /is anyone willing to show me an example of how to parse a line with any of these functions?
Simple, two-state FSM, reading one character at a time:
#include <stdio.h>
int main(void)
{
int ch, state;
for(state=0;; ) {
ch = getc(stdin);
if (ch == EOF) break;
if (state) {
putc(ch, stdout);
if (ch == '\n') state=0;
continue;
}
if (ch == '#') state = 1;
}
return 0;
}
Using ./a.out <fsm.c
include <stdio.h>
') state = 1;
Related
#include<stdio.h>
#include<stdlib.h>
int main()
{
char str[1];
FILE *file;
file = fopen("dataloger.txt", "rb");
while(fread(&str[0], sizeof(str), 1, file) ==1){
if(str[0] =='\n'){
str[0] = '#';
}
printf("%s", str);
}
fclose(file);
/************************************************
int c;
if (file) {
while ((c = getc(file)) != EOF){
if(c =='\n') {
c = '#';
}
printf("%c", c);
}
fclose(file);
}
could someone explain why I didn't see normal output not just #?
As I faced the problem only after I try to replace the char'\n' by another char and print it.
Look at the screen shot added
I copied in your code minus the commented out bits and did some testing. Following is a version of your code with some tweaks.
#include<stdio.h>
#include<stdlib.h>
int main()
{
char str; /* In reality, "str" is a character - a string normally would be at least two characters long with a NULL terminator */
FILE *fp; /* Don't like to name variables with possibly reserved words */
fp = fopen("dataloger.txt", "rb");
if (fp == NULL) /* Just to make the program more robust */
{
printf("Could not find the file\n");
return -1;
}
while(fread(&str, sizeof(str), 1, fp) ==1)
{
if(str =='\n')
{
str = '#';
}
printf("%c", str);
}
fclose(fp);
printf("\n"); /* Just to be neat */
return 0;
}
Following are some points to note.
First, since the program is supposed to read a character at a time from the text file, it seemed more clear to utilize a character variable in lieu of a character array that had a length of "1". Technically both work, but that would come across a bit clearer to anyone analyzing the program.
It's usually a good idea to shy away from naming variables that might have reserved meaning in a program language. Although "file" and "FILE" are different names, it can add to confusion if anyone is analyzing this code.
Also, when working with files, it is often a good idea to check to make sure there were no issues with opening the file; therefore, a check to see if the file pointer is not NULL is beneficial - this might be at the core of your issue depending upon where the text file is in relation to the compiled program.
Testing out this tweaked code, a simple two-line text file was set up with the following test data.
The quick brown fox jumps over the lazy dog.
Now is the time for all good men to come to the aid of their country.
Executing the code resulted in the following output at the terminal (the program was compiled with a name of "ReadFile").
#Dev:~/C_Programs/Console/ReadFile/bin/Release$ ./ReadFile
The quick brown fox jumps over the lazy dog.#Now is the time for all good men to come to the aid of their country.#
Give those tweaks a try to see if it meets the spirit of your project.
Beginner here.
In the ANSI C textbook by K&R, page 20, they ask: How would you test the word count program?
I have copied exactly from the text book, using the CodeBlocks IDE, console application. I have seen many great input tests online, but my question is even dumber. How do I actually input something? Nothing happens when I press enter. Do I have this problem because I am using an IDE and therefore not learning how to run C programs properly?
Thanks in advance. I added a picture to show you what I mean
Here is the code:
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* counts lines, words and characters as input */
main()
{
int c, nl, nw, nc, state;
state = OUT;
/* set these three constants to 0: */
nl = nw = nc = 0;
while ((c = getchar()) != EOF){
++nc;
if (c == '\n')
++nl;
/* || == OR (&& == AND)
evaluation of the following line
will stop as soon as the truth or
falsehood is known, so the order matters */
if (c == ' ' || c == '\n' == c == '\t')
state = OUT;
else if (state == OUT){
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
On MacOS:
gcc kr_wc.c -o kr_wc
./kr_wc < example_text.txt
Example output:
40 260 1397
Where example_text.txt is this file:
1.5.4 Word Counting
The fourth in our series of useful programs counts lines, words, and
characters, with the loose definition that a word is any sequence of
characters that does not contain a blank, tab or newline. This is a
bare-bones version of the UNIX program wc.
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* count lines, words, and characters in input */
int main() {
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
Every time the program encounters the first character of a word, it
counts one more word. The variable state records whether the program
is currently in a word or not; initially it is "not in a word", which
is assigned the value OUT. We prefer the symbolic constants IN and
OUT to the literal values 1 and 0 because they make the program more
readable. In a program as tiny as this, it makes little difference,
but in larger programs, the increase in clarity is well worth the
modest extra effort to write it this way from the beginning. You'll
also find that it's easier to make extensive changes in programs
where magic numbers appear only as symbolic constants.
The program to count words in K&R 2nd edition is made to run on an environment in which you signal the end of input somehow. Normally, as they used UNIX all the time, they used Ctrl-D sequence (which is valid if you run the program in Linux or any Unix-like operating system) This has been so since the early beginning of the UNIX system.
Windows signals the end of input in a console application by the input of a Ctrl-Z (probably followed by a keyboard return key)
If you redirect the input from a file (as when you say a.out <my_input_file.txt) you'll get the number of words at the end, when there's no more input in the file.
You are running the program in an IDE, which is something that normally hides you where standard input and standard output go, or how to signal the window you show how to say that there's not more input to the program.
For the program to get to it's end, you have first to know how to get to an end on input.
The examples in K&R omit a return type of main, which is not valid in modern C, so add int before main():
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* counts lines, words and characters as input */
int main()
{
int c, nl, nw, nc, state;
state = OUT;
/* set these three constants to 0: */
nl = nw = nc = 0;
while ((c = getchar()) != EOF){
++nc;
if (c == '\n')
++nl;
/* || == OR (&& == AND)
evaluation of the following line
will stop as soon as the truth or
falsehood is known, so the order matters */
if (c == ' ' || c == '\n' == c == '\t')
state = OUT;
else if (state == OUT){
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
"How do I actually input something? Nothing happens when I press enter."
If you got problems with your IDE just run it online.
"How would you test the word count program"?
To cite the authors of a bundle of K&R solutions with an answer to that particular question here:
It sounds like they are really trying to get the programmers to learn how to do a unit test. I would submit the following:
input file contains zero words
input file contains 1 enormous word without any newlines
input file contains all white space without newlines
input file contains 66000 newlines
input file contains word/{huge sequence of whitespace of different >kinds}/word
input file contains 66000 single letter words, 66 to the line
input file contains 66000 words without any newlines
input file is /usr/dict contents (or equivalent)
input file is full collection of moby words
input file is binary (e.g. its own executable)
input file is /dev/null (or equivalent)
66000 is chosen to check for integral overflow on small integer machines.
I am working through the exercises in Stephen Prata's "C Primer Plus", and have a question re. listing 8.1:
/* echo.c -- echoes input */
#include <stdio.h>
int main(void)
{
char ch;
while ((ch = getchar()) != '#')
putchar(ch);
// while ((ch = getchar()) != '.')
// putchar(ch);
return 0;
}
The original code did not include the comments; I added them and they are the subject of my question. If I uncomment those lines there is no discernible effect on the output. It still ends at the # sign, without printing it. No additional text is displayed and I am returned to the command prompt.
Why is that? Also, does the # get consumed by getchar()? That was why I included the second loop - I was trying to display any remaining characters in the buffer, out of curiosity. Obviously, I don't know what I'm doing!
it's a very simple question, how to echo every char that I type in stdin to stdout? I'm trying to do it for a long time and I've tried many ways and no one works well. The best I could do was to get what I typed after application end.
The best I did was:
#include <stdio.h>
int main()
{
while (1)
{
int ch = getc(stdin);
if(ch == EOF) break;
putc(ch, stdout);
}
return 0;
}
Thanks.
You need to flush the stdout:
int main()
{
while (1)
{
int ch = getc(stdin);
fflush(stdout);
if(ch == EOF) break;
putc(ch, stdout);
}
return 0;
}
The code you have should work just fine, as long as you hit enter. In most systems, the program will get input in a line oriented fashion. If you want to echo the key immediately after it is hit, you will need to change the input method for the program. On many systems, this would be getch(), but there may be other requirements you have to satisfy before you can use the interface (ncurses requires some additional setup, for example).
When echoing the data immediately after the key is hit, you will be required to flush the output in some way. If you are sending the output to stdout, then a call to fflush() will work. If you are using some system specific output command, you may be required to call some kind or window refresh routine.
I wonder if a better way would be:
int ch;
while((ch = getchar()) >= 0)
{
putchar(ch);
}
Then if you call this:
echo this is my input | ./myprogram
it would output the entire stdin this is my input without hitting the enter key.
Here's my dilemma. I have a file, and wish to read in all characters up until the program hits a '#', and ignore everything on that line after the '#'. For example
0 4001232 0 #comment, discard
This is frustrating, as it feels like there is a very simple solution. Thanks!
FILE *f = fopen("file.txt", "r");
int c;
while ((c = getc(f)) != '#' && c != EOF)
putchar(c);
Read a line using fgets, read through this line till you get a '#' character.
Read an another line...
There are plenty of ways and examples of how to do it. Usually, the idea is to have a variable that holds the state (before #, after # , after \n etc.) and run in a while loop until EOF. an example you can see here it's a program to remove C comments, but the idea is the same.
filePointer = fopen("person.txt", "r");
do
{
read = fgetc(filePointer);
//stop when '#' read or when file ends
if (feof(filePointer) || read == '#')
{
break;
}
printf("%c", read);
} while (1);
fclose(filePointer);
also you better check if file opened succesfully
if (filePointer == NULL)
{
printf("person.txt file failed to open.");
}
else
{
file operations
}
The solution depends on how you are "reading" that.
I could, for example, just remove all of those comments with sed 's/#.*//' <infile >outfile in bash.
EDIT: However, if I was parsing it manually, I could simply (in my loop for parsing it) have
if(line[i]=='#') {
continue;
}
which would stop parsing that line by exiting the loop.