-1

My code is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct{

    char ID[1];
    char Content[4];
}

int main(){

    DATA z[1];
    DATA t;
    int c1, c2;

    scanf("%c",z[1].ID);
    scanf("%s",z[1].Content);

    printf("\n");

    c1=strlen(z[1].ID);
    c2=strlen(z[1].Content);

    t=z[1];

    printf("t:\n");
    printf("%s\n",t.ID);
    printf("%s\n",t.Content);

    printf("\n");

    printf("z:\n");
    printf("%s\n",z[1].ID);
    printf("%s\n",z[1].Content);

    printf("\n");

    printf("Length of z's ID: %d.\n",c1);
    printf("Length of z's Content: %d.\n",c2);
}

And this is what I get when executing it:

8
3092

t:
83092
3092

z:
83092
3092

Length of z's ID: 5.
Length of z's Content: 4.

I don't know why the ID has more than 1 element when it should only have 1. Please help, because I need to fix this for a project I'm working on. Thanks.

Eduard Malakhov
  • 1,095
  • 4
  • 13
  • 25
Britovski
  • 1
  • 6
  • Update the code to make it to compile. – Vlad from Moscow Jun 02 '17 at 14:55
  • `char Content[4]` will only hold four `chars`. But when you enter: `3092`, five `char`s are stored, since the `\0` terminator is automatically added by `scanf()` when using the `%s` conversion specifier. You should always specify a maximum width to avoid buffer overflow when using `%s` with `scanf()`: `%3s` in your case. – ad absurdum Jun 02 '17 at 15:11
  • the posted code does not compile! Amongst other things, the 'typedef' must be ended with a semicolon `;` and the typedef is missing the new type name. Another reason to separate the definition of the struct from the typedef statement. – user3629249 Jun 02 '17 at 21:45
  • this statement: `t=z[1];` is only assigning an address, not the contents of the `z[1]` array item. Note: this is also undefined behavior as it is accessing memory beyond the end of the array `z[]` Remember, in C, an array offset starts with 0 and extends to (number of elements in array -1) Suggest: `memcpy( &t, &z[0], sizeof( t ) );` – user3629249 Jun 02 '17 at 21:52
  • regarding this statement: (corrected for valid offset) `c1=strlen(z[0].ID);` Cannot obtain the length (via `strlen()`) of a single character. Note: the actual length will always be 1, but the function: `strlen()` will not stop until it encounters a NUL byte ('\0'). – user3629249 Jun 02 '17 at 22:04
  • when calling any of the `scanf()` family of functions, 1) always check the returned value (not the parameter values) to assure the operation was successful. 2) when using the '%s' input/format specifier, always include a MAX CHARACTERS modifier that is one less than the length of the input buffer to avoid overflowing the input buffer. Such overflow is undefined behavior and can lead to a seg fault event. – user3629249 Jun 02 '17 at 22:06

3 Answers3

0

I think there are several problems.

First, you use the index 1 on z which has a length of 1. You should use the index 0.

Second, you print the ID with %s which expects a null-terminated character array. Your character ID is not null-terminated and therefore it reads more than you expect (it keeps on going in the Content). Note that Content is in fact null-terminated because you used %s instead of %c.

Try to change printf("%s\n",t.ID); to printf("%c\n",t.ID);.

EDIT: I oversaw that you are storing 5 chars (4 chars and the null-termination) in an array of length 4. As @David Bowling suggests, you should use %3s or at least a bigger size of your array. Thanks to @David Bowling for pointing that out!

Be aware that I have still not tested this, as your example code is still not working.

Thomas D.
  • 1,031
  • 6
  • 17
  • After those changes, it gives me this: `teste.c: In function ‘main’: teste.c:31:11: warning: format ‘%c’ expects argument of type ‘int’, but argument 2 has type ‘char *’ [-Wformat=] printf("%c\n",t.ID); ^ teste.c:37:11: warning: format ‘%c’ expects argument of type ‘int’, but argument 2 has type ‘char *’ [-Wformat=] printf("%c\n",z[1].ID); ^ ` – Britovski Jun 02 '17 at 15:11
  • Please note that OP has UB because of user input and failure to specify maximum width with `%s` in `scanf()`. [See my comment above](https://stackoverflow.com/questions/44331703/array-with-only-1-element-storing-more-than-it-should#comment75668211_44331703) – ad absurdum Jun 02 '17 at 15:13
0

z[1].ID is equal to 8 in your code. Your problem is how you print your values.

here :

printf("%s\n",z[1].ID);
printf("%s\n",z[1].Content);

You request printf to print your char type variable z[1].ID as an array of characters (char*), with the %s format. This format will able you to print every characters until a null character \0 has been reached.

Thus, it displays the string but it also concatenates with what comes in memory. Indeed the variables contained in a struct are concatenated in the memory. In your case z[1].ID is concatenated with z[1].Content.

So to avoid the problem you have to change the format of your printf for z[1].ID whith %c.

And

Beware on how you use your array DATA z[1];.

Keep in mind that the reachable range of an array in C is [0; n-1].

In your code, you need to change every statements that "dereferencing" your array.

This is an example :

scanf("%c",z[1].ID);
scanf("%s",z[1].Content);

to

scanf("%c",z[0].ID);
scanf("%s",z[0].Content);

If your array is still declared like that : DATA z[1];

Jankov_n
  • 103
  • 1
  • 11
0

the following proposed code:

  1. cleanly compiles
  2. corrects the problems listed in the comments to the question
  3. performs the desired functionality

and now the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct{

    char ID[1];
    char Content[4];
} DATA;

int main( void )
{
    DATA z[1];
    DATA t;
    size_t c1;
    size_t c2;

    if( 1 != scanf("%c",  &(z[0].ID[0]) ) )
    {
        perror( "scanf for character failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, scanf successful

    if( 1 != scanf("%3s",  z[0].Content) )
    {
        perror( "scanf for content string failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, scanf successful

    printf("\n");

    c1=sizeof(z[0].ID);
    c2=strlen(z[0].Content);

    memcpy( &t, z, sizeof( t ) );

    printf("t: ID:%c Content:%s\n\n", t.ID[0], t.Content);
    printf("z: ID:%c Content:%s\n\n", z[0].ID[0], z[0].Content);

    printf("Length of z's ID: %lu.\n",c1);
    printf("Length of z's Content: %lu.\n",c2);
}

a run of the proposed code, with this input:

a
bcd

or this input:

a bcd

or this input:

abcd

yields this output:

t: ID:a Content:bcd

z: ID:a Content:bcd

Length of z's ID: 1.
Length of z's Content: 3.
user3629249
  • 16,402
  • 1
  • 16
  • 17