creating a testfile for catv

C

c gordon liddy

What follows purports to be a soln for K&R 8-1 that prints bitshifted
control chars and non-ascii chars:

#include <stdio.h>

int main(int argc, char **argv)
{

FILE *fp;
void filecopy(FILE *, FILE *);

if (argc < 2) printf("die");
else
while (--argc > 0)
if ((fp = fopen(*++argv, "r")) == NULL)
{
printf("catv can't open %s\n", *argv);
return 1;
}
else
{
filecopy(fp, stdout);
fclose(fp);
}

return 0;
}

/*filecopy */
void filecopy(FILE *ifp, FILE *ofp)
{
int c;
int ch;
int result;

while((ch=getc(ifp)) != EOF)
{
if (iscntrl(ch)) {
/* ch is a control character */
int result;

/*
* The two characters we want to print. The first is '^';
* we don't know yet what the second is.
*/
int ch1 = '^';
int ch2;

/* Try to print the first character. */
result = putchar(ch1);
if (result == EOF) {
/* Failed, terminate the loop */
break;
}

if (ch == '\177') {
/* ch is DEL, we want "^?" */
ch2 = '?';
}
else {
/*
* ch is another control character.
* Transform 1 to 'A', 2 to 'B', etc. using
* our intimate knowledge of ASCII encoding.
*/
ch2 = ch | 0100;
}

/* Print as above */
result = putchar(ch2);
if (result == EOF) {
break;
}
}

else putc(ch, ofp);



}

}
// gcc -o catv catv4.c
// catv text24.txt >text43.txt

Abridged output from text43 is:
^JTarget: i386-pc-mingw32^J

My guess is that J is what you get when you add octal 0100 to a carriage
return. Am I correct to think that the first 32 chars are control chars?
DEL appears to be 117 as well.

How would I populate a file containing non-ascii and ctrl chars for test
purposes? (Does anyone have one?)
 
S

santosh

c gordon liddy wrote:

How would I populate a file containing non-ascii and ctrl chars for
test purposes? (Does anyone have one?)

The easiest way is to open the file in a hex editor and fill in the
character codes directly.
 
M

Martin Golding

What follows purports to be a soln for K&R 8-1 that prints bitshifted
control chars and non-ascii chars: [snippage]
How would I populate a file containing non-ascii and ctrl chars for test
purposes? (Does anyone have one?)

mkchars.c:

#include "stdio.h"

unsigned char i;

int main(int argc, char * argv[])
{
unsigned char buffer[256];
do { buffer = i; } while(++i);
fwrite(buffer, 256, 1, stdout);

return 0;
}

make mkchars
../mkchars >samplechars

../catv samplechars


Many terminal emulators will react oddly if you fail to redirect. Don't
../mkchars

Many editors will behave badly if you try to edit samplechars.

Martin
 
S

santosh

Martin said:
What follows purports to be a soln for K&R 8-1 that prints bitshifted
control chars and non-ascii chars: [snippage]
How would I populate a file containing non-ascii and ctrl chars for
test purposes? (Does anyone have one?)

mkchars.c:

#include "stdio.h"

ITYM said:
unsigned char i;

int main(int argc, char * argv[])
{
unsigned char buffer[256];
do { buffer = i; } while(++i);
fwrite(buffer, 256, 1, stdout);


If the OP meant "ASCII control characters", then perhaps you should stop
at 31?

As far as "non-ascii" characters, I don't quite get what the OP means.
Does he mean characters from other encodings, like extended ASCII,
EBCDIC etc.?
 
K

Keith Thompson

Martin Golding said:
What follows purports to be a soln for K&R 8-1 that prints bitshifted
control chars and non-ascii chars: [snippage]
How would I populate a file containing non-ascii and ctrl chars for test
purposes? (Does anyone have one?)

mkchars.c:

#include "stdio.h"

unsigned char i;

int main(int argc, char * argv[])
{
unsigned char buffer[256];
do { buffer = i; } while(++i);
fwrite(buffer, 256, 1, stdout);

return 0;
}

[...]

Yes, that should do the job, but let me offer a few comments. None of
these are actual errors, but they're ways in which your code could be
made clearer.

Use #include <stdio.h>, not #include "stdio.h".

If you don't use argc or argv, you don't have to declare them; use
"int main(void)".

``i'' is declared at file scope. Why? It's only used inside main(),
so it should be declared inside main. Perhaps you declared it at file
scope so it would be implicitly initialized to 0.

Your "do ... while(++i);" depends on the value wrapping around from
255 to 0. That works only if UCHAR_MAX==255, which is not guaranteed.
Even if you're assuming 8-bit characters and don't care about
portability to more exotic systems, I find it needlessly obscure. I'd
probably use a for loop instead.

You store all 256 characters in a buffer, then print the entire buffer
at once. This is not necessary, since stdio does its own buffering.

Here's how I'd probably write it:

#include <stdio.h>
int main(void)
{
int c;
for (c = 0; c <= 255; c ++) {
putchar(c);
}
return 0;
}
 
G

Gerry Ford

Martin Golding said:
What follows purports to be a soln for K&R 8-1 that prints bitshifted
control chars and non-ascii chars: [snippage]
How would I populate a file containing non-ascii and ctrl chars for test
purposes? (Does anyone have one?)

mkchars.c:

#include "stdio.h"

unsigned char i;

int main(int argc, char * argv[])
{
unsigned char buffer[256];
do { buffer = i; } while(++i);
fwrite(buffer, 256, 1, stdout);

return 0;
}

make mkchars
./mkchars >samplechars

./catv samplechars


Many terminal emulators will react oddly if you fail to redirect. Don't
./mkchars

Many editors will behave badly if you try to edit samplechars.

Thanks Martin. You got me rolling with this, so I've got output to tune
things up with.

After I got a look at the output, I found a link that explained control and
non-ascii chars:
http://www.robelle.com/smugbook/ascii.html
It looks like ascii chars are 0 through 127 decimal. Control chars include
the first 32 and DEL at octal 177 (7 +8*7+64*1=7+56+64=127 decimal, the
ultimate ascii char). I'm confused as to the taxonomy of chars between
decimal 32 and decimal 37.

My output with Martin's output catv'ed is:
^@^A^B^C^D^E^F^G^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y
, which is good, in that I seem to have the behavior for control chars
correct. Clearly, other chars aren't making it through yet, so I need some
more time at the chalkboard for that.

I'll finish with Martin's output. All bets are off on how they are
displayed on a usenet message:




!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~?,f".??^?S<OZ''"".--~Ts>ozY
¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
 
R

Richard Heathfield

C. Gordon Liddy said:

Current output with catv is:
the quick brown fox^J^@^A^B^C^D^E^F^G^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y

So after it reads and writes the control characters, it doesn't want to
print anything more.

It is very suggestive that your output stops at Ctrl-Z, which is used as an
end-of-text-file marker by some systems. The fix is obvious - open the
file in binary mode:

#include <stdio.h>

int main(int argc, char **argv)
{

FILE *fp;
void filecopy(FILE *, FILE *);

if (argc < 2) printf("die");
else
while (--argc > 0)
if ((fp = fopen(*++argv, "r")) == NULL)

Change "r" to "rb" and re-test.

<snip>
 
C

C. Gordon Liddy

Keith Thompson said:
Here's how I'd probably write it:
#include <stdio.h>
int main(void)
{
int c;
for (c = 0; c <= 255; c ++) {
putchar(c);
}
return 0;
I modified this program and now have a good test file:

#include <stdio.h>
int main(void)
{
int c;
printf ("the quick brown fox\n");
for (c = 0; c <= 40; c ++) {
putchar(c);
}
printf ("jumps over\n");
for (c = 100; c <= 200; c ++) {
putchar(c);
}
printf ("the lazy dog\n");
return 0;
}
// gcc -o mkchars mkchars2.c
// mkchars >text42.txt

Current output with catv is:
the quick brown fox^J^@^A^B^C^D^E^F^G^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y

So after it reads and writes the control characters, it doesn't want to
print anything more. Here's the current version of catv. I cleaned up the
bracing, thinking that that would be where I was in trouble, but that's not
it. I also added some functionality for non-ascii chars. Again no luck.

#include <stdio.h>

int main(int argc, char **argv)
{

FILE *fp;
void filecopy(FILE *, FILE *);

if (argc < 2) printf("die");
else
while (--argc > 0)
if ((fp = fopen(*++argv, "r")) == NULL)
{
printf("catv can't open %s\n", *argv);
return 1;
}
else
{
filecopy(fp, stdout);
fclose(fp);
}

return 0;
}

/*filecopy */
void filecopy(FILE *ifp, FILE *ofp)
{
int c;
int ch;
int result;
int ch1 = '^';
int ch2;
int ch3 = 'M';

while((ch=getc(ifp)) != EOF)
{
if (iscntrl(ch))
{

result = putchar(ch1);
if (result == EOF)
{
/* Failed, terminate the loop */
break;
}

if (ch == '\177')
{
/* ch is DEL, we want "^?" */
ch2 = '?';
}
else
{
/*
* ch is another control character.
* Transform 1 to 'A', 2 to 'B', etc. using
* our intimate knowledge of ASCII encoding.
*/
ch2 = ch | 0100;
}

/* Print as above */
result = putchar(ch2);
if (result == EOF)
{
break;
}


// outer brace of if (iscntrl(ch))
}


else if (!isascii(ch))
{
result = putchar(ch3);
if (result == EOF)
{
break;
}

}


else putchar(ch);


// outer brace of while control
}
// outer brace of function
}
// gcc -o catv catv7.c >text22.txt 2>text23.txt
// catv text42.txt >text43.txt

I'm new to gcc. Does it have a debugger?

I get no warnings now, and I think I should at least with int c declared and
never referenced. How do I turn up the warnings?
 
C

C. Gordon Liddy

santosh said:
c gordon liddy wrote:



The easiest way is to open the file in a hex editor and fill in the
character codes directly.
Where does a person find such a thing?
--
 
C

C. Gordon Liddy

Richard Heathfield said:
C. Gordon Liddy said:



It is very suggestive that your output stops at Ctrl-Z, which is used as
an
end-of-text-file marker by some systems. The fix is obvious - open the
file in binary mode:



Change "r" to "rb" and re-test.
Thanks, Richard. My output is coming around.

the quick brown
fox^M^J^@^A^B^C^D^E^F^G^H^I^M^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^#^[^\^]^^^_
!"#$%&'(jumps
over^M^Jdefghijklmnopqrstuvwxyz{|}~^?MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMthe
lazy dog^M^J

Sometimes hitting the send button on a post is the exact stimulus one needs
to realize what's in his blind spot: ctrl-z is eof for windows. rb instead
of r works. I tried to do the same thing for that the original did for del:
if (ch == '\177')
{
/* ch is DEL, we want "^?" */
ch2 = '?';
}
else if(ch == 26)
{
/* we don't want ctrl-z coming out of here */
ch2 = '#';
}
I'm puzzled that this didn't work.

I've got some behavior for non-ascii characters. Again, I'll try to emulate
what came off the bsd site:
if (!isascii(ch)) {
if (putchar('M') == EOF || putchar('-') == EOF)
break;
ch = toascii(ch);
}

Heck, I can just paste it in wholesale. Woo-hoo.

--
 
B

Barry Schwarz

What follows purports to be a soln for K&R 8-1 that prints bitshifted
control chars and non-ascii chars:

snip code copied from earlier message thread

Why did you change the subject of the message and post the code again?
See the comments in the putchar thread.
// gcc -o catv catv4.c
// catv text24.txt >text43.txt

Abridged output from text43 is:
^JTarget: i386-pc-mingw32^J

My guess is that J is what you get when you add octal 0100 to a carriage
return. Am I correct to think that the first 32 chars are control chars?

On an ASCII system, \n (as your program sees it, not as it is stored
in the file) is 0xoa which has a decimal representation of 10.
DEL appears to be 117 as well.

You meant \177?
How would I populate a file containing non-ascii and ctrl chars for test
purposes? (Does anyone have one?)

Open a file for output and try
int i;
for (i = 0; i <= UCHAR_MAX; i++)
fputc(i,fp);
then close the file.


Remove del for email
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top