Help With Strings

C

Craig

Hello friends at comp.lang.c,

I'm trying to combine 2 strings with a newline character at the end to write
to a file. When I view the file, the messages run together and some of the
str string is cut-off. A portion of the code is below. Any help would be
appreciated.

#define MAX_SIZE 256
char str[MAX_SIZE];
char lev[] = "INFO: ";
va_list ap;

va_start(ap, fmt);
vsprintf(str, fmt, ap);
va_end(ap);

strcat(lev, str);

write(fd, lev, strlen(fmt));
 
K

Keith Thompson

Craig said:
I'm trying to combine 2 strings with a newline character at the end to write
to a file. When I view the file, the messages run together and some of the
str string is cut-off. A portion of the code is below. Any help would be
appreciated.

#define MAX_SIZE 256
char str[MAX_SIZE];
char lev[] = "INFO: ";
va_list ap;

va_start(ap, fmt);
vsprintf(str, fmt, ap);
va_end(ap);

strcat(lev, str);

write(fd, lev, strlen(fmt));

The variable lev has a size of 7 bytes (6 for the characters of the
string literal used to initialize it, plus 1 for the trailing '\0').
You use strcat() to append more characters, but here's no room for
them. The result is undefined behavior, most likely overwriting some
other chunk of memory.

(You also risk writing past the end of str with your vsprintf() call,
unless you're positive that MAX_SIZE is big enough.)

Also, standard C has no write() function; fwrite() is standard and
more portable. That's not relevant to your problem, but it's
something you should be aware of.

I'm now going to go off on a tangent.

Speaking of that, I'm curious about something. ISO C defines the
fread() and fwrite() functions, and all the other stuff in <stdio.h>
that operates on FILE*'s. POSIX defines read() and write(), and all
the other stuff that operates on file descriptors (small integers).
Historically, I think that read() and write() are probably as old as,
or older than, fread() and fwrite(); ANSI chose to standardize the
latter, but not the former. Are there any real-world hosted
implementations that support fread() and fwrite() but *don't* also
support read() and write(), or is the historical precedent strong
enough to make read() and write() effectively universal?

I'm not at all suggesting that read()/write() should be part of
standard C, or that they should be considered topical here. I'm just
curious about their status.
 
E

Eric Sosman

Keith said:
[...]
I'm now going to go off on a tangent.

Speaking of that, I'm curious about something. ISO C defines the
fread() and fwrite() functions, and all the other stuff in <stdio.h>
that operates on FILE*'s. POSIX defines read() and write(), and all
the other stuff that operates on file descriptors (small integers).
Historically, I think that read() and write() are probably as old as,
or older than, fread() and fwrite(); ANSI chose to standardize the
latter, but not the former. Are there any real-world hosted
implementations that support fread() and fwrite() but *don't* also
support read() and write(), or is the historical precedent strong
enough to make read() and write() effectively universal?

The Rationale discusses the C89 committee's thoughts on
the matter. The crux, it appears, is that read() et al. treat
a file as an array of characters, but this treatment is not
appropriate for all systems -- particularly for text files.
On a system where text lines are terminated with a CR/LF pair,
for example, what would be the semantics of lseek()ing to a
point just after the CR and then reading? Is the end-of-line
sequence recognizable in medias res?
 
A

Al Bowers

Craig said:
Hello friends at comp.lang.c,

I'm trying to combine 2 strings with a newline character at the end to write
to a file. When I view the file, the messages run together and some of the
str string is cut-off. A portion of the code is below. Any help would be
appreciated.

#define MAX_SIZE 256
char str[MAX_SIZE];
char lev[] = "INFO: ";
va_list ap;

va_start(ap, fmt);
vsprintf(str, fmt, ap);
va_end(ap);

strcat(lev, str);

Since lev is an array of 7 characters, appending to it
is flawed. Make lev a large enough array to hold all the characters.
char lev[LARGE_ENOUGH] = "INFO: ";

If you are only concerned with the final goal of getting the strings
to a file, there is no need to combine in a character array and then
copy to a file. Just copy one string to the file, then append to the
file the other string followed by appending the newline character.
This can all be done with one statement using function fprintf.

fprintf(fp,"%s%s\n",string1,string2);

Example:

#include <stdio.h>

#define FNAME "test1.txt"

int main(void)
{
char *s1 = "INFO: ";
char *s2 = "We are go for launch.";
int ch;
FILE *fp;

if((fp = fopen(FNAME,"w+")) != NULL)
{
fprintf(fp,"%s%s\n",s1,s2);
/* to test it */
rewind(fp);
puts("\tReading from the file, the line is:");
for( ; (ch = fgetc(fp)) != EOF; ) putchar(ch);
fclose(fp);
remove(FNAME);
}
return 0;
}
 
K

Keith Thompson

Eric Sosman said:
Keith said:
[...]
I'm now going to go off on a tangent.
Speaking of that, I'm curious about something. ISO C defines the
fread() and fwrite() functions, and all the other stuff in <stdio.h>
that operates on FILE*'s. POSIX defines read() and write(), and all
the other stuff that operates on file descriptors (small integers).
Historically, I think that read() and write() are probably as old as,
or older than, fread() and fwrite(); ANSI chose to standardize the
latter, but not the former. Are there any real-world hosted
implementations that support fread() and fwrite() but *don't* also
support read() and write(), or is the historical precedent strong
enough to make read() and write() effectively universal?

The Rationale discusses the C89 committee's thoughts on
the matter. The crux, it appears, is that read() et al. treat
a file as an array of characters, but this treatment is not
appropriate for all systems -- particularly for text files.
On a system where text lines are terminated with a CR/LF pair,
for example, what would be the semantics of lseek()ing to a
point just after the CR and then reading? Is the end-of-line
sequence recognizable in medias res?

The standard fread()/fwrite() system very nearly treats files as
arrays of characters except for the behavior on end-of-line (and
that's only for text mode). lseek() on a text file with CR/LF pairs
presumably behaves similarly to fseek() on the same file opened in
binary mode.

But my question wasn't about the rationale for the choices made in
standardizing one interface but not the other. (Personally I think it
was a good choice; imposing that kind of redundancy on all
implementations doesn't seem like a good idea.) The question was
whether any real-world implementations actually provide
fread()/fwrite() without providing read()/write(). I ask out of idle
curiosity, not out of any intent to use the knowledge for evil.
 
E

Eric Sosman

Keith said:
But my question wasn't about the rationale for the choices made in
standardizing one interface but not the other. (Personally I think it
was a good choice; imposing that kind of redundancy on all
implementations doesn't seem like a good idea.) The question was
whether any real-world implementations actually provide
fread()/fwrite() without providing read()/write(). I ask out of idle
curiosity, not out of any intent to use the knowledge for evil.

System vendors have an incentive to support as many
relevant Standards as possible with reasonable effort.
Most systems (for suitable values of "most") make an effort
to support both the C Standard and at least some of the
POSIX Standards, so read() et al. will be available on
about as many (for suitable values of "as many") systems
as fread() and friends.

That said, there certainly exist systems where neither
fread() nor read() is "native." (Open)VMS is one such, or
at least it was so when I last used it not quite a decade
ago. On VMS, fread() was not layered atop read(); both were
emulated semi-independently atop VMS' own file model. (As
it happens, neither C streams nor POSIX files are adequate
models for the semantics of all VMS file types.)
 
R

Richard Bos

Keith Thompson said:
The standard fread()/fwrite() system very nearly treats files as
arrays of characters except for the behavior on end-of-line (and
that's only for text mode).

Not quite:

# Data read in from a text stream will necessarily compare equal to the
# data that were earlier written out to that stream only if: the data
# consist only of printable characters and the control characters
# horizontal tab and new-line; no new-line character is immediately
# preceded by space characters; and the last character is a new-line
# character. Whether space characters that are written out immediately
# before a new-line character appear when read in is implementation-
# defined.

The newline issue is probably the only one most of us will ever
encounter, but an implementation that clobbers all over control
characters (except '\t' and '\n') is legal, as is one that truncates
whitespace from the ends of lines.

Richard
 
C

Craig

Al Bowers said:
Hello friends at comp.lang.c,

I'm trying to combine 2 strings with a newline character at the end to write
to a file. When I view the file, the messages run together and some of the
str string is cut-off. A portion of the code is below. Any help would be
appreciated.

#define MAX_SIZE 256
char str[MAX_SIZE];
char lev[] = "INFO: ";
va_list ap;

va_start(ap, fmt);
vsprintf(str, fmt, ap);
va_end(ap);

strcat(lev, str);

Since lev is an array of 7 characters, appending to it
is flawed. Make lev a large enough array to hold all the characters.
char lev[LARGE_ENOUGH] = "INFO: ";

If you are only concerned with the final goal of getting the strings
to a file, there is no need to combine in a character array and then
copy to a file. Just copy one string to the file, then append to the
file the other string followed by appending the newline character.
This can all be done with one statement using function fprintf.

fprintf(fp,"%s%s\n",string1,string2);

Example:

#include <stdio.h>

#define FNAME "test1.txt"

int main(void)
{
char *s1 = "INFO: ";
char *s2 = "We are go for launch.";
int ch;
FILE *fp;

if((fp = fopen(FNAME,"w+")) != NULL)
{
fprintf(fp,"%s%s\n",s1,s2);
/* to test it */
rewind(fp);
puts("\tReading from the file, the line is:");
for( ; (ch = fgetc(fp)) != EOF; ) putchar(ch);
fclose(fp);
remove(FNAME);
}
return 0;
}


--
Al Bowers
Tampa, Fl USA
mailto: (e-mail address removed) (remove the x to send email)
http://www.geocities.com/abowers822/

Thanks for the replies. I should posted my message sooner. I tried
increasing the buffer size but it didn't correct the problem so I decided to
re-write the function using fopen and fprintf. The message is written to
the file properly now except for when it is called by a test program that is
supposed to write 1000 messages. The function only writes messages 0
through 252. Any ideas why all the messages aren't being written and what
to do about it?
 
W

Walter Roberson

:I tried
:increasing the buffer size but it didn't correct the problem so I decided to
:re-write the function using fopen and fprintf. The message is written to
:the file properly now except for when it is called by a test program that is
:supposed to write 1000 messages. The function only writes messages 0
:through 252. Any ideas why all the messages aren't being written and what
:to do about it?

Are you using fopen() once per message? If so then my guess would be that
you are not fclose()'ing each after you are done. If you keep opening
files without closing them, you are going to run into an implimentation-
dependant maximum number of files that may be simultaneously open.

It is not uncommon for the limit on the number of open files to be
the one implied by the internal use of a char to store the underlying
descriptor number. On systems with 8 bit characters, that allows at
most 256 open files. 3 descriptors are certain to be in use when
the program starts: standard input, standard output, and standard error.
You observe 252; add 3 and you are at 255. The missing last descriptor
is experimental error ;-)
 
A

Al Bowers

Craig said:
Thanks for the replies. I should posted my message sooner. I tried
increasing the buffer size but it didn't correct the problem so I decided to
re-write the function using fopen and fprintf. The message is written to
the file properly now except for when it is called by a test program that is
supposed to write 1000 messages. The function only writes messages 0
through 252. Any ideas why all the messages aren't being written and what
to do about it?
You need to provide the code, at least for the function you mention.

In general, I think you will want to:
1. Open the file for writing.
2. write the 1000 lines to the file with fprintf, or the function
you mentioned.. Check the return value of fprintf in order to
catch a file write error.
3. close the file.

Example:

#include <stdio.h>

#define FNAME "test1.txt"

int WriteData(FILE *fp,const char *s1, const char *s2)
{
return fprintf(fp,"%s%s\n",s1,s2);
}

int main(void)
{
char *s1 = "Test Message Line", info[32];
int ch,i;
FILE *fp;

if((fp = fopen(FNAME,"w+")) != NULL)
{
for(i = 0; i < 1000; i++)
{
sprintf(info,"%s %d",s1,i+1);
if(0 > WriteData(fp,"INFO: ", info)) break;
}
/* to test it */
rewind(fp);
if(i != 1000) puts("Oops! A File Write Error");
else
{
for( ; (ch = fgetc(fp)) != EOF; ) putchar(ch);
puts("END OF FILE");
}
fclose(fp);
remove(FNAME);
}
else puts("Unable to open file for update");
return 0;
}
 
C

Craig

Al Bowers said:
Thanks for the replies. I should posted my message sooner. I tried
increasing the buffer size but it didn't correct the problem so I decided to
re-write the function using fopen and fprintf. The message is written to
the file properly now except for when it is called by a test program that is
supposed to write 1000 messages. The function only writes messages 0
through 252. Any ideas why all the messages aren't being written and what
to do about it?
You need to provide the code, at least for the function you mention.

In general, I think you will want to:
1. Open the file for writing.
2. write the 1000 lines to the file with fprintf, or the function
you mentioned.. Check the return value of fprintf in order to
catch a file write error.
3. close the file.

Example:

#include <stdio.h>

#define FNAME "test1.txt"

int WriteData(FILE *fp,const char *s1, const char *s2)
{
return fprintf(fp,"%s%s\n",s1,s2);
}

int main(void)
{
char *s1 = "Test Message Line", info[32];
int ch,i;
FILE *fp;

if((fp = fopen(FNAME,"w+")) != NULL)
{
for(i = 0; i < 1000; i++)
{
sprintf(info,"%s %d",s1,i+1);
if(0 > WriteData(fp,"INFO: ", info)) break;
}
/* to test it */
rewind(fp);
if(i != 1000) puts("Oops! A File Write Error");
else
{
for( ; (ch = fgetc(fp)) != EOF; ) putchar(ch);
puts("END OF FILE");
}
fclose(fp);
remove(FNAME);
}
else puts("Unable to open file for update");
return 0;
}



--
Al Bowers
Tampa, Fl USA
mailto: (e-mail address removed) (remove the x to send email)
http://www.geocities.com/abowers822/

Thanks, I just needed the fclose(fp); in the function.
 

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,780
Messages
2,569,611
Members
45,277
Latest member
VytoKetoReview

Latest Threads

Top