Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #76012 > unrolled thread

how to do this?

Started bybilsch01 <king621@comcast.net>
First post2015-11-14 12:09 -0800
Last post2015-11-14 15:18 -0800
Articles 20 — 5 participants

Back to article view | Back to comp.lang.c


Contents

  how to do this? bilsch01 <king621@comcast.net> - 2015-11-14 12:09 -0800
    Re: how to do this? Rosario19 <Ros@invalid.invalid> - 2015-11-14 21:49 +0100
    Re: how to do this? Ian Collins <ian-news@hotmail.com> - 2015-11-15 10:02 +1300
      Re: how to do this? Ian Collins <ian-news@hotmail.com> - 2015-11-15 10:17 +1300
      Re: how to do this? bilsch01 <king621@comcast.net> - 2015-11-14 15:16 -0800
        Re: how to do this? James Kuyper <jameskuyper@verizon.net> - 2015-11-14 18:24 -0500
          Re: how to do this? bilsch01 <king621@comcast.net> - 2015-11-14 15:30 -0800
            Re: how to do this? Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2015-11-14 19:01 -0500
            Re: how to do this? James Kuyper <jameskuyper@verizon.net> - 2015-11-14 19:07 -0500
    Re: how to do this? Ian Collins <ian-news@hotmail.com> - 2015-11-15 11:26 +1300
      Re: how to do this? bilsch01 <king621@comcast.net> - 2015-11-14 15:07 -0800
        Re: how to do this? James Kuyper <jameskuyper@verizon.net> - 2015-11-14 18:17 -0500
        Re: how to do this? bilsch01 <king621@comcast.net> - 2015-11-14 15:25 -0800
          Re: how to do this? Ian Collins <ian-news@hotmail.com> - 2015-11-15 13:10 +1300
            Re: how to do this? James Kuyper <jameskuyper@verizon.net> - 2015-11-14 19:21 -0500
              Re: how to do this? Ian Collins <ian-news@hotmail.com> - 2015-11-15 13:24 +1300
          Re: how to do this? James Kuyper <jameskuyper@verizon.net> - 2015-11-14 19:12 -0500
            Re: how to do this? Ian Collins <ian-news@hotmail.com> - 2015-11-15 13:18 +1300
              Re: how to do this? James Kuyper <jameskuyper@verizon.net> - 2015-11-14 19:23 -0500
    Re: how to do this? bilsch01 <king621@comcast.net> - 2015-11-14 15:18 -0800

#76012 — how to do this?

Frombilsch01 <king621@comcast.net>
Date2015-11-14 12:09 -0800
Subjecthow to do this?
Message-ID<n2849g$a6p$1@dont-email.me>
I don't know how to write code to eliminate repetitiveness.  The program 
below operates on four files, does several tasks for each.  I want to 
learn a way to do the same thing with 1/4 of the code by having (a 
macro?) substitute 1, 2, 3, 4 in the code where needed when the program 
runs.



int main(void){

char *vec1, *vec2, *vec3, *vec4;
char ivt1[2305], ivt2[2305], ivt3[2305], ivt4[2305];
char mk1[9] = "**  1  **", mk2[9] = "**  2  **", mk3[9] = "**  3  **";
int i=0;
FILE *fp1, *fp2, *fp3, *fp4;

		printf("\n\n\n\tvec#\t  ivt1\t\t  ivt2\t\t  ivt3\t\t  ivt4\n\n");

		if ((fp1=fopen("ivt1.txt", "r"))==NULL)
				printf("\nerror opening file ivt1.txt\n");
		
		if ((fp2=fopen("ivt2.txt", "r"))==NULL)
				printf("\nerror opening file ivt2.txt\n");
		
		if ((fp3=fopen("ivt3.txt", "r"))==NULL)
				printf("\nerror opening file ivt3.txt\n");
		
		if ((fp4=fopen("ivt4.txt", "r"))==NULL)
				printf("\nerror opening file ivt4.txt\n");
		
		fread(ivt1, 1, 2304, fp1); 	
		fread(ivt2, 1, 2304, fp2);
		fread(ivt3, 1, 2304, fp3);
		fread(ivt4, 1, 2304, fp4);

		for (i=0;i<256;i++)
		{
			vec1 = malloc(9);
				memcpy(vec1, ivt1+i*9, 9);
			
			vec2 = malloc(9);
				memcpy(vec2, ivt2+i*9, 9);
			
			vec3 = malloc(9);
				memcpy(vec3, ivt3+i*9, 9);
	
			vec4 = malloc(9);
				memcpy(vec4, ivt4+i*9, 9);
			

			if (strcmp(vec2, vec1) == 0)
					strcpy(vec2, mk1);

			if (strcmp(vec3, vec1) == 0)
					strcpy(vec3, mk1);
			
			if (strcmp(vec3, vec2) == 0)
					strcpy(vec3, mk2);

			if (strcmp(vec4, vec1) == 0)
					strcpy(vec4, mk1);

			if (strcmp(vec4, vec2) == 0)
					strcpy(vec4, mk2);
			
			if (strcmp(vec4, vec3) == 0)
					strcpy(vec4, mk3);

			printf("\t%i\t%s\t%s\t%s\t%s\n", i, vec1, vec2, vec3, vec4);
		}

		fclose(fp1);
		fclose(fp2);
		fclose(fp3);
		fclose(fp4);

		printf("\n\t\t\t\t Shift+PgUp/PgDn to scroll\n\n");

		return 0;
}

[toc] | [next] | [standalone]


#76021

FromRosario19 <Ros@invalid.invalid>
Date2015-11-14 21:49 +0100
Message-ID<fg7f4bp492iffqb9a2q1nd702i92fd877v@4ax.com>
In reply to#76012
On 14 Nov 2015 20:32:08 GMT, (Stefan Ram) wrote:

>bilsch01  writes:
>>I don't know how to write code to eliminate repetitiveness.  The program 
>
>  I am busy right now, so I might not have the time to finish
>  this today. I just show a first step, and might follow-up
>  today or on other days with more refactorings later. The
>  first step is a minor normalization (reformatting) of the
>  source code. I do not test this, so minor typos might creep in.
>
>#include <stdio.h>
>
>int main( void )
>{ char * vec0;
>  char * vec1;
>  char * vec2; 
>  char * vec3;
>  char ivt0[ 2305 ];
>  char ivt1[ 2305 ]; 
>  char ivt2[ 2305 ];
>  char ivt3[ 2305 ];
>  char mk0[ 9 ]= "**  1  **";
>  char mk1[ 9 ]= "**  2  **";
>  char mk2[ 9 ]= "**  3  **";
>  int i = 0;
>  FILE * fp0;
>  FILE * fp1;
>  FILE * fp2;
>  FILE * fp3;
>  printf( "\n\n\n\tvec#\t  ivt0\t\t  ivt1\t\t  ivt2\t\t  ivt3\n\n" );
>  if(( fp0 = fopen( "ivt0.txt", "r" ))== NULL )printf( "error opening file ivt0.txt\n" );
>  if(( fp1 = fopen( "ivt1.txt", "r" ))== NULL )printf( "error opening file ivt1.txt\n" );
>  if(( fp2 = fopen( "ivt2.txt", "r" ))== NULL )printf( "error opening file ivt2.txt\n" );
>  if(( fp3 = fopen( "ivt3.txt", "r" ))== NULL )printf( "error opening file ivt3.txt\n" );
>  fread( ivt0, 1, 2304, fp0 );
>  fread( ivt1, 1, 2304, fp1 );
>  fread( ivt2, 1, 2304, fp2 );
>  fread( ivt3, 1, 2304, fp3 );
>  for( i=0; i < 256; ++i )
>  { vec0 = malloc( 9 ); memcpy( vec0, ivt0 + i * 9, 9 );
>    vec1 = malloc( 9 ); memcpy( vec1, ivt1 + i * 9, 9 );
>    vec2 = malloc( 9 ); memcpy( vec2, ivt2 + i * 9, 9 );
>    vec3 = malloc( 9 ); memcpy( vec3, ivt3 + i * 9, 9 );
>    if( strcmp( vec1, vec0 )== 0 )strcpy( vec1, mk0 );
>    if( strcmp( vec2, vec0 )== 0 )strcpy( vec2, mk0 );
>    if( strcmp( vec2, vec1 )== 0 )strcpy( vec2, mk1 );
>    if( strcmp( vec3, vec0 )== 0 )strcpy( vec3, mk0 );
>    if( strcmp( vec3, vec1 )== 0 )strcpy( vec3, mk1 );
>    if( strcmp( vec3, vec2 )== 0 )strcpy( vec3, mk2 );
>    printf( "\t%i\t%s\t%s\t%s\t%s\n", i, vec0, vec1, vec2, vec3 ); }
>  fclose( fp3 );
>  fclose( fp2 );
>  fclose( fp1 );
>  fclose( fp0 );
>  printf( "\n\t\t\t\t Shift+PgUp/PgDn to scroll\n\n" ); }

i like more this way indenting than the other one
because definition are first

[toc] | [prev] | [next] | [standalone]


#76026

FromIan Collins <ian-news@hotmail.com>
Date2015-11-15 10:02 +1300
Message-ID<daplreFi0ttU6@mid.individual.net>
In reply to#76012
bilsch01 wrote:
> I don't know how to write code to eliminate repetitiveness.  The program
> below operates on four files, does several tasks for each.  I want to
> learn a way to do the same thing with 1/4 of the code by having (a
> macro?) substitute 1, 2, 3, 4 in the code where needed when the program
> runs.

The obvious starting point is to create a function to open and read the 
files with the necessary error checking.  Say:

char*
load( const char* filename )
{
   FILE* fp = fopen(filename, "r");

   if( fp == NULL)
   {
     printf("\nerror opening file %s\n", filename );
     return NULL;
   }

   const size_t buffSize = 2305;
   char* buffer = malloc(buffSize);

   if( (fread( buffer, buffSize-1, 1, fp )) != buffSize-1 )
   {
     printf("\nerror reading from file %s\n", filename );
     free( buffer );
     return NULL;
   }

   // What goes in the last character?

   return buffer;
}

Then do your processing.

<snip>

>
> 		for (i=0;i<256;i++)
> 		{
> 			vec1 = malloc(9);

Why are you using dynamic allocation here?  You never free what you 
allocate.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#76030

FromIan Collins <ian-news@hotmail.com>
Date2015-11-15 10:17 +1300
Message-ID<dapmnqFi0ttU8@mid.individual.net>
In reply to#76026
Ian Collins wrote:
> bilsch01 wrote:
>> I don't know how to write code to eliminate repetitiveness.  The program
>> below operates on four files, does several tasks for each.  I want to
>> learn a way to do the same thing with 1/4 of the code by having (a
>> macro?) substitute 1, 2, 3, 4 in the code where needed when the program
>> runs.
>
> The obvious starting point is to create a function to open and read the
> files with the necessary error checking.  Say:
>
> char*
> load( const char* filename )
> {
>     FILE* fp = fopen(filename, "r");
>
>     if( fp == NULL)
>     {
>       printf("\nerror opening file %s\n", filename );
>       return NULL;
>     }
>
>     const size_t buffSize = 2305;
>     char* buffer = malloc(buffSize);
>
>     if( (fread( buffer, buffSize-1, 1, fp )) != buffSize-1 )
>     {
>       printf("\nerror reading from file %s\n", filename );
>       free( buffer );
>       return NULL;
>     }
>
>     // What goes in the last character?
>
>     return buffer;
> }

Not forgetting to close the file....

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#76041

Frombilsch01 <king621@comcast.net>
Date2015-11-14 15:16 -0800
Message-ID<n28f7r$pmq$1@dont-email.me>
In reply to#76026
>
>    // What goes in the last character?
>

There's EOF.  9*256=2304

> Why are you using dynamic allocation here?  You never free what you
> allocate.

Yes I see I need to free().  You mention dynamic allocation here - is 
there another kind I could use?
>

[toc] | [prev] | [next] | [standalone]


#76044

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-14 18:24 -0500
Message-ID<5647C2C4.9070704@verizon.net>
In reply to#76041
On 11/14/2015 06:16 PM, bilsch01 wrote:
>>
>>    // What goes in the last character?
>>
> 
> There's EOF.  9*256=2304
> 
>> Why are you using dynamic allocation here?  You never free what you
>> allocate.
> 
> Yes I see I need to free().  You mention dynamic allocation here - is 
> there another kind I could use?

This is automatic allocation:
	char vec1[9];
	// work with vec1.

This is dynamic allocation:
	char *vec1 = malloc(9);
	if(vec1)
        {
             // work with vec1
             free(vec1);
        }

In general, automatic allocation is a lot simpler. Dynamic allocation
may be necessary if the amount of memory needed is large, because many
systems have far more memory available for dynamic allocation than for
automatic allocation. It's also more appropriate when there's a lot of
variation in the amount of memory that needs to be allocated. Neither of
those reasons apply in this case: 9 bytes is quite tiny, and it's also
fixed.

[toc] | [prev] | [next] | [standalone]


#76046

Frombilsch01 <king621@comcast.net>
Date2015-11-14 15:30 -0800
Message-ID<n28g35$smg$1@dont-email.me>
In reply to#76044
On 11/14/2015 03:24 PM, James Kuyper wrote:
> On 11/14/2015 06:16 PM, bilsch01 wrote:
>>>
>>>     // What goes in the last character?
>>>
>>
>> There's EOF.  9*256=2304
>>
>>> Why are you using dynamic allocation here?  You never free what you
>>> allocate.
>>
>> Yes I see I need to free().  You mention dynamic allocation here - is
>> there another kind I could use?
>
> This is automatic allocation:
> 	char vec1[9];
> 	// work with vec1.
>
> This is dynamic allocation:
> 	char *vec1 = malloc(9);
> 	if(vec1)
>          {
>               // work with vec1
>               free(vec1);
>          }
>
> In general, automatic allocation is a lot simpler. Dynamic allocation
> may be necessary if the amount of memory needed is large, because many
> systems have far more memory available for dynamic allocation than for
> automatic allocation. It's also more appropriate when there's a lot of
> variation in the amount of memory that needs to be allocated. Neither of
> those reasons apply in this case: 9 bytes is quite tiny, and it's also
> fixed.
>
There was spurious trailing bullshit at the end of the output lines. 
When I put in the malloc() that solved the problem.

[toc] | [prev] | [next] | [standalone]


#76051

FromLew Pitcher <lew.pitcher@digitalfreehold.ca>
Date2015-11-14 19:01 -0500
Message-ID<pXP1y.94399$1J.87579@fx31.iad>
In reply to#76046
On Saturday November 14 2015 18:30, in comp.lang.c, "bilsch01"
<king621@comcast.net> wrote:

> On 11/14/2015 03:24 PM, James Kuyper wrote:
>> On 11/14/2015 06:16 PM, bilsch01 wrote:
>>>>
>>>>     // What goes in the last character?
>>>>
>>>
>>> There's EOF.  9*256=2304
>>>
>>>> Why are you using dynamic allocation here?
[snip] 
> There was spurious trailing bullshit at the end of the output lines.
> When I put in the malloc() that solved the problem.

Having stayed silent for most of this discussion, I /have/ to speak up here.

Likely, your "spurious trailing bullshit" occurred as an artifact of your not
having \0 string terminators on the character arrays that you treat as
strings. If your use of malloc() "corrects" that output behaviour, it does so
only as a side-effect of how it operates under the covers, and you should
consider it as "undefined behaviour" that you cannot depend on.

It appears that, throughout your program, you struggle with C's string
termination requirements. Clean up those spots and you should be able to fix
your "spurious trailing bullshit" problem properly, without resorting to the
accidental side-effects of malloc().

-- 
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request

[toc] | [prev] | [next] | [standalone]


#76052

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-14 19:07 -0500
Message-ID<5647CCC9.4060001@verizon.net>
In reply to#76046
On 11/14/2015 06:30 PM, bilsch01 wrote:
> On 11/14/2015 03:24 PM, James Kuyper wrote:
>> On 11/14/2015 06:16 PM, bilsch01 wrote:
>>>>
>>>>     // What goes in the last character?
>>>>
>>>
>>> There's EOF.  9*256=2304

Your existing code does nothing with the last character. Do you mean
that a future version of your program will put EOF in that location? If
so, why?
EOF is an error code returned by several functions when they reach the
end of a file or experience an I/O error. It is not something that you
normally have any reason to store in an array that's being read from a
file or written to a file. Reading a file into an array will not place
EOF into the array when the end of the file is read; writing from an
array containing EOF will not cause the output file to end at that location.

...
>> This is automatic allocation:
>> 	char vec1[9];
>> 	// work with vec1.
>>
>> This is dynamic allocation:
>> 	char *vec1 = malloc(9);
>> 	if(vec1)
>>          {
>>               // work with vec1
>>               free(vec1);
>>          }
>>
>> In general, automatic allocation is a lot simpler. Dynamic allocation
>> may be necessary if the amount of memory needed is large, because many
>> systems have far more memory available for dynamic allocation than for
>> automatic allocation. It's also more appropriate when there's a lot of
>> variation in the amount of memory that needs to be allocated. Neither of
>> those reasons apply in this case: 9 bytes is quite tiny, and it's also
>> fixed.
>>
> There was spurious trailing bullshit at the end of the output lines. 
> When I put in the malloc() that solved the problem.

That's to be expected, because your code fails to null-terminate the
buffer before passing it to strcmp(), strcpy(), and printf(), all of
which require that the strings they work on be null-terminated. Even
worse, you didn't allocate enough memory to store the terminating null
character.

I'm not sure why using malloc() would make a difference, but I've got an
idea: on many implementations, malloc() fills the allocated memory with
zeros, just like calloc() is required to do. That's because the system
utilities that make memory available always zero it out, usually as a
security measure. Also, if you request an allocation of 9 bytes, it's
quite likely that malloc() may have rounded that allocation up to 10,
12, or 16 bytes, and zeroed out the entire thing. In that case, your
strings get null terminated even though you code didn't do anything to
null terminate them. You should not rely upon this, because malloc() is
not required to zero out the memory, and you should also not count on
malloc() setting aside enough room for the terminating null, since you
failed to tell it to do so.

There's a simple solution to this problem: allocate enough space for the
entire string, including the terminating null character, using either

    char vec1[10];

or

    char *vec1 = malloc(10);

Then, after filling in the string

    memcpy(vec1, ivt1+i*9, 9);

null terminate it using the following statement:

    vec1[9] = '\0';

[toc] | [prev] | [next] | [standalone]


#76037

FromIan Collins <ian-news@hotmail.com>
Date2015-11-15 11:26 +1300
Message-ID<dapqp9Fi0ttU9@mid.individual.net>
In reply to#76012
bilsch01 wrote:

One I missed earlier:

> char mk1[9] = "**  1  **", mk2[9] = "**  2  **", mk3[9] = "**  3  **";

These aren't null terminated strings.
			
>
> 			if (strcmp(vec2, vec1) == 0)
> 					strcpy(vec2, mk1);

So this copy could go horribly wrong.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#76040

Frombilsch01 <king621@comcast.net>
Date2015-11-14 15:07 -0800
Message-ID<n28emj$nl3$1@dont-email.me>
In reply to#76037
On 11/14/2015 02:26 PM, Ian Collins wrote:
> bilsch01 wrote:
>
> One I missed earlier:
>
>> char mk1[9] = "**  1  **", mk2[9] = "**  2  **", mk3[9] = "**  3  **";
>
> These aren't null terminated strings.
>
>>
>>             if (strcmp(vec2, vec1) == 0)
>>                     strcpy(vec2, mk1);
>
> So this copy could go horribly wrong.
>
why isn't "**  1  **" a null terminated string?  How should I declare it 
to make it null terminated?

char "**  1  **",0

I thought when you declare an array of type char it gets null terminated 
if "" are used.

[toc] | [prev] | [next] | [standalone]


#76042

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-14 18:17 -0500
Message-ID<5647C100.40005@verizon.net>
In reply to#76040
On 11/14/2015 06:07 PM, bilsch01 wrote:
> On 11/14/2015 02:26 PM, Ian Collins wrote:
>> bilsch01 wrote:
>>
>> One I missed earlier:
>>
>>> char mk1[9] = "**  1  **", mk2[9] = "**  2  **", mk3[9] = "**  3  **";
>>
>> These aren't null terminated strings.
>>
>>>
>>>             if (strcmp(vec2, vec1) == 0)
>>>                     strcpy(vec2, mk1);
>>
>> So this copy could go horribly wrong.
>>
> why isn't "**  1  **" a null terminated string?  How should I declare it 
> to make it null terminated?
> 
> char "**  1  **",0
> 
> I thought when you declare an array of type char it gets null terminated 
> if "" are used.

Only if it's big enough to store the terminating null character. For
example, It requires 6 char objects to store 'h', 'e', 'l', 'l', 'o' and
the terminating '\0' character.

    char unterminated[5] = "hello";
    char terminated1[6] = "hello";

If you don't specify the length, it's automatically set big enough to
include the terminating null character:

    char terminated2[] = "hello";

[toc] | [prev] | [next] | [standalone]


#76045

Frombilsch01 <king621@comcast.net>
Date2015-11-14 15:25 -0800
Message-ID<n28fpg$rmm$1@dont-email.me>
In reply to#76040
On 11/14/2015 03:07 PM, bilsch01 wrote:
> On 11/14/2015 02:26 PM, Ian Collins wrote:
>> bilsch01 wrote:
>>
>> One I missed earlier:
>>
>>> char mk1[9] = "**  1  **", mk2[9] = "**  2  **", mk3[9] = "**  3  **";
>>
>> These aren't null terminated strings.
>>
>>>
>>>             if (strcmp(vec2, vec1) == 0)
>>>                     strcpy(vec2, mk1);
>>
>> So this copy could go horribly wrong.
>>
> why isn't "**  1  **" a null terminated string?  How should I declare it
> to make it null terminated?
>
> char "**  1  **",0
>
> I thought when you declare an array of type char it gets null terminated
> if "" are used.

  Oh.  The vec1 , vec2 . . . aren't null terminated.  I don't see any 
way to fix that.

[toc] | [prev] | [next] | [standalone]


#76053

FromIan Collins <ian-news@hotmail.com>
Date2015-11-15 13:10 +1300
Message-ID<daq0r5Fi0ttU10@mid.individual.net>
In reply to#76045
bilsch01 wrote:
> On 11/14/2015 03:07 PM, bilsch01 wrote:
>> On 11/14/2015 02:26 PM, Ian Collins wrote:
>>> bilsch01 wrote:
>>>
>>> One I missed earlier:
>>>
>>>> char mk1[9] = "**  1  **", mk2[9] = "**  2  **", mk3[9] = "**  3  **";
>>>
>>> These aren't null terminated strings.
>>>
>>>>
>>>>              if (strcmp(vec2, vec1) == 0)
>>>>                      strcpy(vec2, mk1);
>>>
>>> So this copy could go horribly wrong.
>>>
>> why isn't "**  1  **" a null terminated string?  How should I declare it
>> to make it null terminated?
>>
>> char "**  1  **",0
>>
>> I thought when you declare an array of type char it gets null terminated
>> if "" are used.

It does, but you were losing the terminator by copying into a 9 
character array.

>    Oh.  The vec1 , vec2 . . . aren't null terminated.  I don't see any
> way to fix that.

Your code as written implied that they were null terminated by using 
strxxx functions to compare and copy them.  I wasn't sure (because you 
didn't specify the file format) so in my re-write I used this function 
for the compare and copy:

const size_t itemSize = 9;

void
subsituteIfEqual( char* token, const char* key, const char* value )
{
   if( memcmp( token, key, itemSize ) == 0 )
   {
     memcpy( token, value, itemSize );
   }
}

To get meaningful rather than speculative replies, you must specify the 
format of the data files.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#76057

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-14 19:21 -0500
Message-ID<5647D007.2010207@verizon.net>
In reply to#76053
On 11/14/2015 07:10 PM, Ian Collins wrote:
> bilsch01 wrote:
...
>>    Oh.  The vec1 , vec2 . . . aren't null terminated.  I don't see any
>> way to fix that.
> 
> Your code as written implied that they were null terminated by using 
> strxxx functions to compare and copy them.

True. However, he opened the file in text mode, which means that even if
null characters were written to that file, there's no guarantee that
they'll still be there when read back from the file. That's because of
7.21.2p2:

"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 printing 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."

Therefore, if a file contains null characters, it should be read in
binary mode, not text mode.

[toc] | [prev] | [next] | [standalone]


#76059

FromIan Collins <ian-news@hotmail.com>
Date2015-11-15 13:24 +1300
Message-ID<daq1m2Fi0ttU12@mid.individual.net>
In reply to#76057
James Kuyper wrote:
> On 11/14/2015 07:10 PM, Ian Collins wrote:
>> bilsch01 wrote:
> ....
>>>     Oh.  The vec1 , vec2 . . . aren't null terminated.  I don't see any
>>> way to fix that.
>>
>> Your code as written implied that they were null terminated by using
>> strxxx functions to compare and copy them.
>
> True. However, he opened the file in text mode, which means that even if
> null characters were written to that file, there's no guarantee that
> they'll still be there when read back from the file. That's because of
> 7.21.2p2:
>
> "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 printing 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."
>
> Therefore, if a file contains null characters, it should be read in
> binary mode, not text mode.

Good spot!

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#76054

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-14 19:12 -0500
Message-ID<5647CDEA.8050307@verizon.net>
In reply to#76045
On 11/14/2015 06:25 PM, bilsch01 wrote:
> On 11/14/2015 03:07 PM, bilsch01 wrote:
>> On 11/14/2015 02:26 PM, Ian Collins wrote:
>>> bilsch01 wrote:
>>>
>>> One I missed earlier:
>>>
>>>> char mk1[9] = "**  1  **", mk2[9] = "**  2  **", mk3[9] = "**  3  **";
>>>
>>> These aren't null terminated strings.
>>>
>>>>
>>>>             if (strcmp(vec2, vec1) == 0)
>>>>                     strcpy(vec2, mk1);
>>>
>>> So this copy could go horribly wrong.
>>>
>> why isn't "**  1  **" a null terminated string?  How should I declare it
>> to make it null terminated?
>>
>> char "**  1  **",0
>>
>> I thought when you declare an array of type char it gets null terminated
>> if "" are used.
> 
>   Oh.  The vec1 , vec2 . . . aren't null terminated.  I don't see any 
> way to fix that.
> 

This will automatically make mk1 10 bytes long, large enough to include
the terminating null character:

	char mk1[] = "**  1  **";

This makes sure vec1 is big enough to store the terminating null character:

	char vec1[10];
	strcpy(vec2, mk1)

If mk1 is null-terminated, strcpy() will copy the null terminator along
with the rest of the string. If mk1 is NOT null-terminated, strcpy() has
undefined behavior - DON'T DO THAT.

[toc] | [prev] | [next] | [standalone]


#76056

FromIan Collins <ian-news@hotmail.com>
Date2015-11-15 13:18 +1300
Message-ID<daq19sFi0ttU11@mid.individual.net>
In reply to#76054
James Kuyper wrote:
> On 11/14/2015 06:25 PM, bilsch01 wrote:
>> On 11/14/2015 03:07 PM, bilsch01 wrote:
>>> On 11/14/2015 02:26 PM, Ian Collins wrote:
>>>> bilsch01 wrote:
>>>>
>>>> One I missed earlier:
>>>>
>>>>> char mk1[9] = "**  1  **", mk2[9] = "**  2  **", mk3[9] = "**  3  **";
>>>>
>>>> These aren't null terminated strings.
>>>>
>>>>>
>>>>>              if (strcmp(vec2, vec1) == 0)
>>>>>                      strcpy(vec2, mk1);
>>>>
>>>> So this copy could go horribly wrong.
>>>>
>>> why isn't "**  1  **" a null terminated string?  How should I declare it
>>> to make it null terminated?
>>>
>>> char "**  1  **",0
>>>
>>> I thought when you declare an array of type char it gets null terminated
>>> if "" are used.
>>
>>    Oh.  The vec1 , vec2 . . . aren't null terminated.  I don't see any
>> way to fix that.
>>
>
> This will automatically make mk1 10 bytes long, large enough to include
> the terminating null character:
>
> 	char mk1[] = "**  1  **";

Given what they are and how they are used, a better definition would be:

   const char* mk1 = "**  1  **";

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#76058

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-14 19:23 -0500
Message-ID<5647D075.9050805@verizon.net>
In reply to#76056
On 11/14/2015 07:18 PM, Ian Collins wrote:
> James Kuyper wrote:
...
>> This will automatically make mk1 10 bytes long, large enough to include
>> the terminating null character:
>>
>> 	char mk1[] = "**  1  **";
> 
> Given what they are and how they are used, a better definition would be:
> 
>    const char* mk1 = "**  1  **";

Agreed.

[toc] | [prev] | [next] | [standalone]


#76043

Frombilsch01 <king621@comcast.net>
Date2015-11-14 15:18 -0800
Message-ID<n28fc0$pmq$2@dont-email.me>
In reply to#76012
On 11/14/2015 02:05 PM, Stefan Ram wrote:
> ram@zedat.fu-berlin.de (Stefan Ram) writes:
>> ram@zedat.fu-berlin.de (Stefan Ram) writes:
>>> ram@zedat.fu-berlin.de (Stefan Ram) writes:
>>>> ram@zedat.fu-berlin.de (Stefan Ram) writes:
>>>>> #include <stdio.h>
>>>> #include <stdio.h>
>>> #include <stdio.h>
>> #include <stdio.h>
>
>    Another refactor, SCNR:
>
> #include <stdio.h>
>
> static FILE * fp[ 4 ];
> static char * fn[ 4 ]={ "ivt0.txt", "ivt1.txt", "ivt2.txt", "ivt3.txt" };
> static char ivt[ 4 ][ 2305 ];
> static char * vec[ 4 ];
> static char mk[ 3 ][ 9 ]= "**  i  **";
>
> void c( int const i, int const j )
> { if( !strcmp( vec[ i ], vec[ j ]))strcpy( vec[ i ], mk[ j ]); }
>
> void main4()
> { c( 1, 0 ); c( 2, 0 ); c( 2, 1 ); c( 3, 0 ); c( 3, 1 ); c( 3, 2 );
>    printf( "\t%i\t%s\t%s\t%s\t%s\n", i, vec[ 0 ], vec[ 1 ], vec[ 2 ], vec[ 3 ]); }
>
> void main3( int const i, int const n )
> { vec[ n ]= malloc( 9 ); if( vec[ n ])
>    { memcpy( vec[ n ], ivt[ n ]+ i * 9, 9 );
>      if( n < 3 )main3( i, n + 1 ); else main4();
>      free( vec[ n ]); }}
>
> void main2( void )
> { for( int i = 0; i < 256; ++i )main3( i, 0 );  }
>
> void main1( int const i )
> { fp[ i ]= fopen( fn[ i ], "r" );
>    if( !fp[ i ])printf( "error opening file %s\n", fn[ i ] ); else
>    { fread( ivt[ i ], 1, 2304, fp[ i ]);
>      if( i < 3 )main1( i + 1 ); else main2()
>      fclose( fp[ i ]); }}
>
> int main( void )
> { printf( "\n\n\n\tvec#\t  ivt0\t\t  ivt1\t\t  ivt2\t\t  ivt3\n\n" );
>    main1( 0 );
>    printf( "\n\t\t\t\t Shift+PgUp/PgDn to scroll\n\n" ); }
>
>    still untested and therefore intended to be read more as
>    pseudocode (sketch of an idea) than as C.
>
  Thanks for the step by step instruction.  That makes it understandable.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web