0

The code might be a little messy, but that's because I am just learning the basics.

In my program, one of the variables, namely listkl[i].imie is losing its value after it exits the void function in which it is given said value. The other variables that get their values in said function are working normally.

I'll also add that I am required to use gets function.

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

struct klient // definicja strultury "klient"
    {
        int nr_transakcji; //element struktury
        char *imie;
        char *nazwisko;
        int rok_urodzenia;
        char *produkt;
        float koszt;
    };


void nowy_klient(struct klient listkl[], int i)
{
    char im[100];
    char ko[100];
    gets(ko);
    listkl[i].nr_transakcji = i+1;
    gets(im);
    listkl[i].imie = im;
    gets(ko);
    listkl[i].koszt = atof(ko);

    printf("\n imie %s", listkl[i].imie);

}

void drukuj_liste(struct klient listkl[], int i)
{
    for(int i = 0; i < 17; i++)
        {
            if(listkl[i].imie == "brak")
            {
                printf("");
            }
            else
            {
                printf("\n imie %s", listkl[i].imie);
                printf("\n nr transakcji %d", listkl[i].nr_transakcji);
                printf("\n koszt %5.2f zl\n", listkl[i].koszt);
            }
        }
}

int main()
{
    struct klient listkl[17];
    int co_chcesz;
    int warunek_1 = 0;
    int i;

    for(i = 0; i < 17; i++)
    {
        listkl[i].imie = "brak";
    }

    while(warunek_1 == 0)
    {
        printf("Co chcesz zrobic?\n1 - Dodaj klienta\n2 - Drukuj klientow\n3 - Zakoncz\n");
        scanf("%d", &co_chcesz);
        switch(co_chcesz)
        {
            case 1:
                printf("Podaj numer klienta, pod ktorym chcesz dodac nowego klienta (1-17)\n");
                scanf("%d", &i);
                i = i - 1;
                if(listkl[i].imie == "brak")
                {
                    nowy_klient(listkl, i);
                }
                else
                {
                    int decyzja;
                    printf("Ten numer jest zajety. Nadpisac?\n1 - Tak\n2- Nie\n");
                    scanf("%d", &decyzja);
                    if(decyzja == 1)
                    {
                        nowy_klient(&listkl, i);
                    }
                    else
                    {
                        break;
                    }
                }
                break;
            case 2:
                printf("\n imie %s", listkl[0].imie);
                drukuj_liste(listkl, i);
                break;
            case 3:
                warunek_1 = 1;
                break;
        }
    }

    return 0;
}

Edit: I tried playing around with comments from you guys, for which I am really thankful btw, and I managed to get it to work almost right, as much as I can given the tools I have to use. The value stays in place now, the new problem is that instead of just the thing I type, it also has 3 random signs in front of it. Let's say I input "Dada", I get "Éi│Dada" instead.

New code:

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

struct klient // definicja strultury "klient"
    {
        int nr_transakcji; //element struktury
        char *imie;
        char *nazwisko;
        int rok_urodzenia;
        char *produkt;
        float koszt;
    };


void nowy_klient(struct klient listkl[], int i)
{
    char im[100];
    char ko[100];
    gets(ko);
    listkl[i].nr_transakcji = i+1;
    gets(im);
    listkl[i].imie = malloc(sizeof(char));
    strcat (listkl[i].imie, im);
    gets(ko);
    listkl[i].koszt = atof(ko);

    printf("\n imie %s", listkl[i].imie);

}

void drukuj_liste(struct klient listkl[], int i)
{
    for(int i = 0; i < 17; i++)
        {
            if(listkl[i].imie == "brak")
            {
                printf("");
            }
            else
            {
                printf("\n imie %s", listkl[i].imie);
                printf("\n nr transakcji %d", listkl[i].nr_transakcji);
                printf("\n koszt %5.2f zl\n", listkl[i].koszt);
            }
        }
}

int main()
{
    struct klient listkl[17];
    int co_chcesz;
    int warunek_1 = 0;
    int i;

    for(i = 0; i < 17; i++)
    {
        listkl[i].imie = "brak";
    }

    while(warunek_1 == 0)
    {
        printf("Co chcesz zrobic?\n1 - Dodaj klienta\n2 - Drukuj klientow\n3 - Zakoncz\n");
        scanf("%d", &co_chcesz);
        switch(co_chcesz)
        {
            case 1:
                printf("Podaj numer klienta, pod ktorym chcesz dodac nowego klienta (1-17)\n");
                scanf("%d", &i);
                i = i - 1;
                if(listkl[i].imie == "brak")
                {
                    nowy_klient(listkl, i);
                }
                else
                {
                    int decyzja;
                    printf("Ten numer jest zajety. Nadpisac?\n1 - Tak\n2- Nie\n");
                    scanf("%d", &decyzja);
                    if(decyzja == 1)
                    {
                        nowy_klient(listkl, i);
                    }
                    else
                    {
                        break;
                    }
                }
                break;
            case 2:
                drukuj_liste(listkl, i);
                break;
            case 3:
                warunek_1 = 1;
                break;
        }
    }

    return 0;
}

Finally, thanks to you, mostly Oka, I managed to get this trainwreck working properly... or at least give me the output I need, while the code itself is zombie made of many different ideas.

Final code:

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

struct klient // definicja strultury "klient"
    {
        int nr_transakcji; //element struktury
        char *imie;
        char *nazwisko;
        int rok_urodzenia;
        char *produkt;
        float koszt;
    };


void nowy_klient(struct klient listkl[], int i)
{
    char im[100];
    char ko[100];
    gets(ko);
    listkl[i].nr_transakcji = i+1;
    gets(im);
    listkl[i].imie = malloc(sizeof(128));
    strcpy (listkl[i].imie, im);
    gets(ko);
    listkl[i].koszt = atof(ko);

}

void drukuj_liste(struct klient listkl[], int i)
{
    for(int i = 0; i < 17; i++)
        {
            if(listkl[i].imie == "brak")
            {
                printf("");
            }
            else
            {
                printf("\n imie %s", listkl[i].imie);
                printf("\n nr transakcji %d", listkl[i].nr_transakcji);
                printf("\n koszt %5.2f zl\n", listkl[i].koszt);
            }
        }
}

int main()
{
    struct klient listkl[17];
    int co_chcesz;
    int warunek_1 = 0;
    int i;

    for(i = 0; i < 17; i++)
    {
        listkl[i].imie = "brak";
    }

    while(warunek_1 == 0)
    {
        printf("Co chcesz zrobic?\n1 - Dodaj klienta\n2 - Drukuj klientow\n3 - Zakoncz\n");
        scanf("%d", &co_chcesz);
        switch(co_chcesz)
        {
            case 1:
                printf("Podaj numer klienta, pod ktorym chcesz dodac nowego klienta (1-17)\n");
                scanf("%d", &i);
                i = i - 1;
                if(listkl[i].imie == "brak")
                {
                    nowy_klient(listkl, i);
                }
                else
                {
                    int decyzja;
                    printf("Ten numer jest zajety. Nadpisac?\n1 - Tak\n2- Nie\n");
                    scanf("%d", &decyzja);
                    if(decyzja == 1)
                    {
                        nowy_klient(listkl, i);
                    }
                    else
                    {
                        break;
                    }
                }
                break;
            case 2:
                drukuj_liste(listkl, i);
                break;
            case 3:
                warunek_1 = 1;
                break;
        }
    }

    return 0;
}
  • `listkl[i].imie == "brak"` ! See: [How do I properly compare strings in C?](https://stackoverflow.com/q/8004237/2505965) – Oka Apr 04 '22 at 15:01
  • 2
    `gets` ! See: [Why is the gets function so dangerous that it should not be used?](https://stackoverflow.com/q/1694036/2505965) – Oka Apr 04 '22 at 15:02
  • What makes you think it looses it's value? Did you inspect it with your debugger? Did you printf it? – Jabberwocky Apr 04 '22 at 15:04
  • 2
    Those arrays in `nowy_klient()` are local stack variables, use`malloc()` to keep them on heap. – जलजनक Apr 04 '22 at 15:05
  • 4
    `listkl[i].imie = im;` ! See: (C++) [Can a local variable's memory be accessed outside its scope?](https://stackoverflow.com/q/6441218/2505965) – Oka Apr 04 '22 at 15:05
  • I tried printing it a few times in a few places in the code, it keeps its value only inside the void, outside of it it does not have any, and in the next void, it shows a smiley face when I print it. – user18703498 Apr 04 '22 at 15:05
  • 2
    If you're required to sue `gets`, you should ask your teacher/professor/tutor or whoever why you're required to use a function that has been deprecated more than 10 years ago. – Jabberwocky Apr 04 '22 at 15:06
  • 1
    You are not required to use `gets`. You are required to quit the class that is even suggesting that using `gets` is a good idea. – William Pursell Apr 04 '22 at 15:34
  • 1
    `im` is a local variable in the function `nowy_klient`. After that function returns, the address if `im` is invalid. – William Pursell Apr 04 '22 at 15:35
  • `malloc(sizeof(char))` allocates one (1) byte of memory. This is enough to hold only the null terminating byte of a string. Effectively enough memory for the empty string (`""`). Allocate more memory (~ `malloc(128)`), and ensure you do not read a string that would occupy more than this. Note that 128 bytes of memory can store a string of length 127, as one final byte of memory is needed for the null terminating byte (`\0`). `gets` cannot ensure memory safety (it will read and read and read until a newline is found) -- this is why we stopped using it decades ago. – Oka Apr 04 '22 at 15:50
  • 1
    `strcat (listkl[i].imie, im);` -- `strcat` requires the destination buffer to be a valid, null terminated string. Do not use it to initialize memory allocated by `malloc`. Use `malloc` + `strcpy`, or `strdup` (or at the very least `calloc` + `strcat`). – Oka Apr 04 '22 at 15:53

1 Answers1

0

At least these problems:

Wrong size

sizeof(128) is the size of an int, typically 4. Certainly code should allocate more - the size for a string.

// listkl[i].imie = malloc(sizeof(128));  // bad
size_t  length = strlen(im);
listkl[i].imie = malloc(length + 1);
if (listkl[i].imie == NULL) {
  Handle_Allocation_failure(); /// TBD code
}

strcpy (listkl[i].imie, im);

gets() and scanf()

gets() is not available since C11. Typical scanf() calls leave a '\n' in stdin that gets() reads as a short line. Mixed use of these leads to troubles.

Better code would perform all user input with fgets().

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256