0

As mentioned in the title, I don't know how to pass a char array to a struct array within a function.

The task is to write a little warehouse system, where you can add / remove / search for items. But in order to add / remove a Item, it should be checked whether the item already exists or not.

I have to use a struct and an array of this struct. My current approach is really buggy and I tried several hours to fix this but at this point I don't even know what to fix..

Important note: I am not allowed to use any other library than stdio.h and string.h and I am not allowed to use anything else than scanf for input and printf for output. I have to compare both strings with strcmp and I don't think that I am allowed to use strncpy.

Perhaps my whole approach is wrong..

Here is my code

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

#define LENGTHITEM 100
#define NUMBEROFITEMS 100

typedef struct WareHouse_ {
    char item[LENGTHITEM];
    int number;
} WareHouse;

void newItem(char*, WareHouse*, int);

int main() {

    int end = 0; int inputNumber = 0;
    char decision; char inputItem[NUMBEROFITEMS];
    WareHouse wHouse[NUMBEROFITEMS];

    printf("\nWelcome!");
    printf("\n\nYou can choose the following:");

    while (end != 1) {
        printf("\n\nNew Item (H) / Delete Item (E) | Search Item (S) | Table (A) | End (B): ");
        scanf("%c", &decision);

        switch(decision) {
            case 'h':
            case 'H': printf("\nName: ");
                      scanf("%s, inputItem);
                      printf("Number: "); 
                      scanf("%i", &inputNumber); <-- Here it says: scanf used to convert a string to an integer value (CLion)
                      newItem(inputItem, wHouse, inputNumber);
                      break;
            case 'e':
            case 'E': printf("\nTest E");
                      break;
            case 's':
            case 'S': printf("\nTest S");
                      break;
            case 'a':
            case 'A': printf("\nTest A");
                      break;
            case 'b':
            case 'B': printf("\nGood bye!");
                      end++;
                      break;
        }
    }
    return 0;
}

void newItem(char *inputItem, WareHouse *wHouse , int inputNumber) {

    for (int i = 0; i < NUMBEROFITEMS; i++) {
        if (strcmp(inputItem, wHouse[i].item) == 0) {
            printf("\nItem already exists, number increased %i", inputNumber);
            wHouse[i].number+= inputNumber;

        } else if (strcmp(inputItem, wHouse[i].item) < 0 || strcmp(inputItem, wHouse[i].item) > 0) {
            wHouse[i].number+= inputNumber;

            <-- Here I want to pass the "inputItem" into the "wHouse" array but I don't know how.. -->
        }
    }
}


Program:

    Welcome

    You can choose the following:

    New Item (H) / Delete Item (E) | Search Item (S) | Table (A) | End (B): H <-- My input

    Name and number (Name Number): fish 10 <-- My input


    New Item (H) / Delete Item (E) | Search Item (S) | Table (A) | End (B): <-- BUG IT APPEARS TWO TIMES

    New Item (H) / Delete Item (E) | Search Item (S) | Table (A) | End (B): H

    Name and number (Name Number): fish 10 <-- My input

    <-- Here it should output: "Item already exists, number increased 10" but it does nothing -->


    New Item (H) / Delete Item (E) | Search Item (S) | Table (A) | End (B): <-- BUG IT APPEARS TWO TIMES

    New Item (H) / Delete Item (E) | Search Item (S) | Table (A) | End (B): B

    Good bye

11
  • You’re else clause does not make sense, does it? How do you ensure you don’t overwrite an existing item if strcmp does not match? Also, why not reading strings and amount separately? It’s more often recommended to use fgets for reading strings. Also, what does fflush do? Commented Dec 7, 2019 at 11:55
  • 1
    Fyi, whatever book, website, tutorial, or acquaintance informed you fflush(stdin); is the standard method for clearing the stdin stream, they were wrong. See here. Commented Dec 7, 2019 at 11:57
  • @user0800 As mentioned before, I am not allowed to use fgets.. And my else should say "If item doesn't exists". Commented Dec 7, 2019 at 12:04
  • @WhozCraig My professor did. Commented Dec 7, 2019 at 12:05
  • Right, I missed that one. How do you prevent overwriting though? Commented Dec 7, 2019 at 12:05

1 Answer 1

1

To put a string into another array without strncpy(), you can use strcpy().

strcpy(wHouse[i].item, inputItem);

Another way is to calculate length to copy via strlen() and copying via memcpy().

size_t len = strlen(inputItem);
memcpy(wHouse[i].item, inputItem, len + 1); /* +1 for terminating null character */

If both of these ways are not allowed, you can copy each characters by yourself.

for (size_t p = 0; ; p++) {
    wHouse[i].item[p] = inputItem[p];
    /* break here (not via loop condition) instead of loop condition for copying terminating null character */
    if (inputItem[p] == '\0') break;
}

And I found three other problems in your code.

Firstly, the array wHouse is used without initializing, so you are using indeterminate values for calculation and invoking undefined behavior.

Initlalization can be done like this:

WareHouse wHouse[NUMBEROFITEMS] = {{"", 0}};

You can specify the value for only first element, and the left elements will be automatically initialized to "zero".

Secondly, the choice is displayed twice because newline characters are read via %c. To avoid this, you can add a space characte before %c to tell scanf ignore whitespace characters.

scanf(" %c", &decision);

Thiredly, if you add the "passing" in the newItem() function like you say, all elements will be modified because elements are modified for all values that strcmp() returns. Instead, I guess you want to modify the first empty element when specified item is not found.

To realize this, you can write like this:

void newItem(char *inputItem, WareHouse *wHouse , int inputNumber) {

    int itemFound = 0; /* set to 1 when specified item is found */
    int firstEmptyItem = -1; /* set to the index of the first empty item */

    for (int i = 0; i < NUMBEROFITEMS; i++) {
        if (strcmp(inputItem, wHouse[i].item) == 0) {
            printf("\nItem already exists, number increased %i", inputNumber);
            wHouse[i].number+= inputNumber;

            itemFound = 1; /* the item is found! */

        } else if (strcmp("", wHouse[i].item) == 0) { /* check if this item is empty */
            /* if empty and index is not written yet, write the index */
            if (firstEmptyItem < 0) firstEmptyItem = i;

        }
    }
    /* if the item is not found, and a room to add new item exists */
    if (!itemFound && firstEmptyItem >= 0) {
        int i = firstEmptyItem; /* set index (or you can use firstEmptyItem directly in the following code) */

        wHouse[i].number+= inputNumber;

        /* Here you should pass the "inputItem" into the "wHouse" array. */
    }
}
Sign up to request clarification or add additional context in comments.

9 Comments

What do you mean with "item i = firstEmptyItem;". I only get an error there.
@Andrew Sorry, it is my mistake and item should be int.
It works. I love you. At this moment, I don't exactly know what it does but I think thats a small problem that I will solve. Now I have to do the same thing with deleting an item :D
what does the "size_t" mean?
size_t is an unsigned integer type for storing object size.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.