-2

this is my first post here so I will apologize in advance if I mess anything up.

I am writing a program for my class in C and the assignment wants us to read in a string 20 characters long from a file, then use a union to take the string and make 5 ints out of it.

All of my int values are coming out the same, and I can not figure out what else to do. All the examples I can find only really care about taking in a string then making it into one int or an int and a float.

my union is set up as follows

union hashes
{
    char str[20];
    int one;
    int two;
    int three;
    int four;
    int five;
};

int main (void)
{
    union hashes hashes1;
}

A new attempt at showing more of the program

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

union hashes
{
    char str[20];
    int one;
    int two;
    int three;
    int four;
    int five;
};

int main (int argc, char *argv[])
{
    //declare union
    union hashes hashes1;
    //declare struct from link.h
    struct node* current;
    struct node* new_node;
    //file pointer to open file
    FILE *fpointer;
    fpointer = fopen(argv[1], "r");
    //activate first node
    current = (struct node*) malloc(sizeof(struct node));

//read from file
    while (fread(current, 20, 1, fpointer))
    {
        //copy the string to the union
        strncpy(hashes1.str, current->name, 20);
        //add the variables
        printf("string: %s\nInts: %d %d %d %d %d\n", hashes1.str, hashes1.one, hashes1.two, hashes1.three, hashes1.four, hashes1.five);

        new_node = (struct node*) malloc(sizeof(struct node));
        current = new_node;
    }
}
RandyC
  • 11
  • 4
  • 1
    Your posted code makes no effort to read in a string of 20 characters or use a union to make 5 ints out of it. This is not a homework completion site. From the [help/on-topic]: *Questions asking for homework help **must include a summary of the work you've done so far to solve the problem, and a description of the difficulty you are having solving it**.* If you can't get started on your assignment, ask your instructor for help. – Ken White Dec 11 '16 at 07:17
  • Sorry Ken, I read a lot of helpful posts on this site and I have seen many new posters get yelled at for posting too much. I knew the issue was with my union, and what n.m. said I understand and should fix it. I did not want to post the whole code and get yelled at, I was attempting to focus on the area where I knew the issue was. – RandyC Dec 11 '16 at 07:19
  • I also assumed it was implied that i can read the strings from the file and attempt to use union being that I stated my union ints were all coming out with the same values. – RandyC Dec 11 '16 at 07:25
  • You need to post a [mcve]. Don't expect us to *assume* anything, particularly when it comes to posting your homework assignments. Include the *minimal relevant code to demonstrate the problem*. What you included is not useful in any way. – Ken White Dec 11 '16 at 07:28
  • If the contents of the file are `int` * 5 binary, you do not need to use `union`. You can read directly into arrays(`int[5]`) using `fread` directly. – BLUEPIXY Dec 11 '16 at 07:29
  • Ken, if you stop back by let me know if this would be more acceptable in the future? I would prefer to not make this mistake moving forward. Thank you for informing me. – RandyC Dec 11 '16 at 07:39
  • `printf("string: %s\n...", hashes1.str,` This is not suitable. I think that you are misunderstanding. – BLUEPIXY Dec 11 '16 at 07:46
  • @BLUEPIXY Thank you very much! I understand what you mean, but I don't think the file is in binary. It appears to be strings and null characters. Plus the assignment directions specifically want it done this way. The end result (which I did not add in my post because I was attempting to be succinct) is to use this union as an algorithm for a hash table. So I have to add these 5 ints together, then use the modulus division on them to get a number that I will use to add it to a linked list for that number. – RandyC Dec 11 '16 at 07:47
  • oh i see....... – BLUEPIXY Dec 11 '16 at 07:51
  • @BLUEPIXY I dont understand what you mean about the printf not being suitable. I am only using it to check the values in the union variables because the hash values were acting wierd and that is when i learned they were all storing the exact same value. – RandyC Dec 11 '16 at 07:51
  • Your code should not compile (since `struct node` is not defined). – Basile Starynkevitch Dec 11 '16 at 09:20
  • @Basile sorry, I was trying to leave out anything not required to express my issue here, the program at the time i posted this was approx 100 lines, and as I said ive seen people get yelled at for posting too much. There is a header file that i didnt put in the include that has the node struct. Should have #include "link.h" at the top, but i felt that would only be more confusing so i commented that struct declaration hoping it would shed some light on it. – RandyC Dec 11 '16 at 17:08

3 Answers3

3

If sizeof(int) is 4 on your platform, use:

union hashes
{
    char str[20];
    int numbers[5];
};

You can also use a fixed width integer.

union hashes
{
    char str[20];
    int32_t numbers[5];
};
R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

All of your ints are the same. Another approach will be having another vector, but this time, of ints. Since the sizeof(int) between platforms can change, you can get the vector size relative to the int size:

union hashes
{
   char str[20];
   int numbers[20 / sizeof(int)];
};

A little test case can be used to prove that both fields have a same size:

int main(void)
{
   union hashes hashes1;

   printf("%lu %lu %lu", sizeof(hashes1), sizeof(hashes1.str),
                         sizeof(hashes1.numbers));
   return 0;
}

That prints 20 20 20. A little Coliru demo.

To know or work with the resulting amount of ints you could do something like:

int main(void)
{
    union hashes hashes1;
    int i;

    if (sizeof(hashes1.numbers) / sizeof(int) != 5)
       printf("In this architecture we cannot extract 5 numbers "
              " from 20 characters\n");
    else {
       printf("The numbers are: ");

       for (i = 0; i < 5; ++i)
         printf("%d ", hashes1.numbers[i]);

       printf("\n");
    }

    return 0;
}

Although usually sizeof(int) == 4, so, you will nearly always get 5 integers, and the first if will be never executed in your tests.

ABu
  • 10,423
  • 6
  • 52
  • 103
0

With recent C (e.g. C99 or C11 at least), a union can contain an anonymous struct. So you might code:

union hashes {
  char str[20];
  struct {
    int one;
    int two;
    int three;
    int four;
    int five;
  };
};

and later use hashes1.str and hashes1.three etc.

Be aware that you have no guarantee that an int takes four bytes (or that it is aligned to 4 bytes). You might use <stdint.h> and types like int32_t (a 32 bits signed integer) or uint8_t (an 8 bit unsigned integer, e.g. a byte). See also this and read the standard reference, e.g. n1570 (a draft which is practically the same as the ISO C11 standard).

You should use the sizeof operator (and perhaps also alignof, if alignment is relevant). In particular your call to fread should have sizeof(struct node) or sizeof(union hashes) instead of 20.

(BTW, your code is wrong, so won't compile, because struct node is not declared)

Don't forget to favor readability and portability when writing C code. Be sure to enable all warnings & debug info when compiling (e.g. use gcc -Wall -Wextra -g if using GCC...), then use the debugger (e.g. gdb).

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Thank you very much. From my understanding we are using C89 (atleast according to the professor). I am still very much wet behind the ears on this stuff, but we use a shell program to log into a campus linux os machine to do all the code, so I dont know how to tell which type it is for sure. There was a comment earlier (which got removed for some reason) where someone suggested making 2 structs and doing a union of them, which is what I did and it worked. Pretty much what you suggested here, but yours is even better, less typing! – RandyC Dec 11 '16 at 07:55
  • Recent (and even not so recent) Linux distributions hava a [GCC](http://gcc.gnu.org/) compiler so are usually accepting C99 (at least if compiling with `gcc -std=c99`) – Basile Starynkevitch Dec 11 '16 at 09:08
  • BTW, I believe you should learn C99 at least. So ask your professor if you are allowed to code against that standard (or even better, C11), and if he forbids it, ask him why. C89 is really a thing of the past and I see no reason to code against it in 2016. Please look into the [n1570](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) draft. You won't understand all of it, but you really should take a hour to glance into it. – Basile Starynkevitch Dec 11 '16 at 09:13
  • Will do, thank you sir! – RandyC Dec 11 '16 at 17:06