Złe typowanie zakresu liczb

0

Witam serdecznie.

Piszę program pod Linuxa w C, i nie radzę sobie z tymi błędami w GCC i rzutowaniem typów i wskaźników.
Program jest następujący:

 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <math.h>
#include <string.h>

#define PROJECTID 825 // unikalne ID dla pamięci współdzielonej
#define SIZE 20 // ilosc liczb do wylosowania
#define TYPE unsigned int

void LosujLiczby(TYPE* block, int x1, int x2);
void Generuj(TYPE* block, char* x1, char* x2);
unsigned int CzyUnikalne(TYPE* block, int count, int which);
void Wypisz(TYPE* block);

int main(int argc, char** argv)
{
    printf("PID naszego procesu: %d\n", getpid()); // wyswietlanie PID naszego procesu

    key_t key = ftok("/tmp", PROJECTID); // ftok() zwraca klawisz oparty na sciezce
    int flag = IPC_CREAT | 0x1B6;
    TYPE* block; // specjalna zmienna dla pamieci wspoldzielonej
    int size = SIZE * sizeof(TYPE);

    printf("Tworzymy blok pamieci o rozmiarze: %d\n", size);

    //Proces składa żądanie alokacji lub uzyskania dostępu do istniejącego segmentu pamięci
    //współdzielonej wywołaniem funkcji shmget()
    int id = shmget(key, size, flag); // id pamieci zaalokowanej
    
    printf("Zaalokowane ID dla pamieci wspoldzielonej: %d\n", id); // drukowanie id pamieci zaalokowanej

    if (id > 0) // jesli id wieksze od 0
    {
        block = (TYPE*)shmat(id, NULL, 0); // dolaczenie pamieci zaalokowanej pod okreslonym id
        struct shmid_ds buffer;
        
        char opcja;
        printf("Wybierz jedna z dostepnych opcji\n");
        printf("\n");
        printf("[ W - aby generowac, a - aby wypisac, c - aby wyczyscic ]\n");
        scanf("%c",&opcja);
        
        unsigned int poczatek_przedzialu = 0;
        unsigned int koniec_przedzialu = 0;
        
        switch(opcja)
        {
            case 'w':
                printf("Podaj poczatek przedzialu: ");
                scanf("%u",(unsigned int*)poczatek_przedzialu);
                printf("Podaj koniec przedzialu: ");
                scanf("%u",(unsigned int*)koniec_przedzialu);
                
                
                printf("Nastepuje generowanie liczb losowych z przedzialu [ %u , %u ] \n", poczatek_przedzialu, koniec_przedzialu);
                Generuj(block, poczatek_przedzialu, koniec_przedzialu); // zapis do pamieci wspolnej
                shmdt((void*)block); // zwalnianie pamieci
            break;
            
            case 's':
                printf("Wyswietlanie wylosowanych liczb! \n");
                Wypisz(block); //wyswietlamy zawartosc pamieci wspolnej
                shmdt((void*)block); // zwalnianie pamieci
            break;
            
            case 'c':    
                shmctl(id, IPC_RMID, &buffer); // czyscimy zawartosc pamieci wspolnej
            break;
        }       
    }
    return 0;
}

void Wypisz(TYPE* block) // funkcja wypisujaca rezultaty na ekran
{
    int i = 0;
    for (i=0; i < SIZE; ++i)
    {
        printf("%d\t,", block[i]);
    }

    printf("\n");
}

void Generuj(TYPE* block, unsigned int* a, unsigned int* b)
{
    int _a = atoi(a); // funkcja atoi() odpowiada za parsowanie stringa do inta
    int _b = atoi(b);
    printf("x: %d, y: %d \n", _a, _b);
    LosujLiczby(block, _a, _b);
}

void LosujLiczby(TYPE* block, int a, int b) // funkcja losujaca 20 liczb podzielnych przez 3
{
    srand(time(NULL)); // incjowanie losowania
    
    int i = 0;
    for (i=0; i < SIZE; i++) 
    {
        unsigned int r = (rand() % b)+ a + 1;
        unsigned int dig = (r / 5) * 5;

        if (CzyUnikalne(block, i, dig)) // sprawdzanie czy liczby sa unikalne
        {
            if((dig >= a)) // jesli losowane liczby sa wieksze niż poczatek zakresu a
            {
                if((dig <= b)) // jesli losowane liczby sa mniejsze niż koniec zakresu b
                {
                    block[i] = dig; // dodawanie liczby do bloku naszej pamieci
                    //printf("%d\n", dig);
                }
            }
        }
    }
}

unsigned int CzyUnikalne(TYPE* block, int count,  int which) // funkcja sprawdzajaca czy liczby sa unikalne
{
    int i = 0;
    for (i=0; i < count; ++i)
    {
        if (block[i] == which)
        {
            return 0; // jesli sie powtarza zwraca 0
        }
    }
    return 1; // jesli nie zwraca 1
}


Chodzi, mi głownie o tego Switcha. Bo chciałbym zczytać z klawiatury początek i koniec zakresu i przekazać te dane do funkcji generuj, a ona powinna wygenerować mi 20 liczb z podanego przedzialu, podzielnych przez 5, bez powtórzen.

Wywala mi takie błędy:

z2.c: In function ‘main’:
z2.c5: warning: passing argument 2 of ‘Generuj’ makes pointer from integer without a cast [enabled by default]
Generuj(block, poczatek_przedzialu, koniec_przedzialu); // zapis do pamieci wspolnej
^
z2.c6: note: expected ‘char ’ but argument is of type ‘unsigned int’
void Generuj(TYPE
block, char* x1, char* x2);
^
z2.c5: warning: passing argument 3 of ‘Generuj’ makes pointer from integer without a cast [enabled by default]
Generuj(block, poczatek_przedzialu, koniec_przedzialu); // zapis do pamieci wspolnej
^
z2.c6: note: expected ‘char ’ but argument is of type ‘unsigned int’
void Generuj(TYPE
block, char* x1, char* x2);
^
z2.c: At top level:
z2.c6: error: conflicting types for ‘Generuj’
void Generuj(TYPE* block, unsigned int* a, unsigned int* b)
^
z2.c6: note: previous declaration of ‘Generuj’ was here
void Generuj(TYPE* block, char* x1, char* x2);
^
z2.c: In function ‘Generuj’:
z2.c2: warning: passing argument 1 of ‘atoi’ from incompatible pointer type [enabled by default]
int _a = atoi(a); // funkcja atoi() odpowiada za parsowanie stringa do inta
^
In file included from z2.c0:
/usr/include/stdlib.h12: note: expected ‘const char *’ but argument is of type ‘unsigned int *’
extern int atoi (const char *__nptr)
^
z2.c2: warning: passing argument 1 of ‘atoi’ from incompatible pointer type [enabled by default]
int _b = atoi(b);
^
In file included from z2.c0:
/usr/include/stdlib.h12: note: expected ‘const char *’ but argument is of type ‘unsigned int *’
extern int atoi (const char *__nptr)

Bardzo proszę o pomoc :(

0

Ok poprawiłem co nieco, nie ma teraz błędów, program się kompiluje, ale jak chcę teraz wczytać z klawiatury początek i koniec przedziału to wywala mi: "segmentation core dumped "

 

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <math.h>
#include <string.h>

#define PROJECTID 825 // unikalne ID dla pamięci współdzielonej
#define SIZE 20 // ilosc liczb do wylosowania
#define TYPE unsigned int


void LosujLiczby(TYPE* block, int x1, int x2);
void Generuj(TYPE* block, char* x1, char* x2);
unsigned int CzyUnikalne(TYPE* block, int count, int which);
void Wypisz(TYPE* block);

int main(int argc, char** argv)
{
    printf("PID naszego procesu: %d\n", getpid()); // wyswietlanie PID naszego procesu

    key_t key = ftok("/tmp", PROJECTID); // ftok() zwraca klawisz oparty na sciezce
    int flag = IPC_CREAT | 0x1B6;
    TYPE* block; // specjalna zmienna dla pamieci wspoldzielonej
    int size = SIZE * sizeof(TYPE);

    printf("Tworzymy blok pamieci o rozmiarze: %d\n", size);

    //Proces składa żądanie alokacji lub uzyskania dostępu do istniejącego segmentu pamięci
    //współdzielonej wywołaniem funkcji shmget()
    int id = shmget(key, size, flag); // id pamieci zaalokowanej
    
    printf("Zaalokowane ID dla pamieci wspoldzielonej: %d\n", id); // drukowanie id pamieci zaalokowanej

    if (id > 0) // jesli id wieksze od 0
    {
        block = (TYPE*)shmat(id, NULL, 0); // dolaczenie pamieci zaalokowanej pod okreslonym id
        struct shmid_ds buffer;
        
        char opcja;
        printf("Wybierz jedna z dostepnych opcji: \n");
        printf("\n");
        printf("[ W - aby generowac, a - aby wypisac, c - aby wyczyscic ]\n");
        scanf("%c",&opcja);
        
        unsigned int poczatek_przedzialu = 0;
        unsigned int koniec_przedzialu = 0;
        
        switch(opcja)
        {
            case 'w':
                printf("Podaj poczatek przedzialu: ");
                scanf("%u",(unsigned int*)poczatek_przedzialu);
                printf("Podaj koniec przedzialu: ");
                scanf("%u",(unsigned int*)koniec_przedzialu);
                
                
                printf("Nastepuje generowanie liczb losowych z przedzialu [ %u , %u ] \n", poczatek_przedzialu, koniec_przedzialu);
                Generuj(block, (char*)poczatek_przedzialu, (char*)koniec_przedzialu); // zapis do pamieci wspolnej
                shmdt((void*)block); // zwalnianie pamieci
            break;
            
            case 's':
                printf("Wyswietlanie wylosowanych liczb! \n");
                Wypisz(block); //wyswietlamy zawartosc pamieci wspolnej
                shmdt((void*)block); // zwalnianie pamieci
            break;
            
            case 'c':    
                shmctl(id, IPC_RMID, &buffer); // czyscimy zawartosc pamieci wspolnej
            break;
        }
        
    }
    return 0;
}

void Wypisz(TYPE* block) // funkcja wypisujaca rezultaty na ekran
{
    int i = 0;
    for (i=0; i < SIZE; ++i)
    {
        printf("%d\t,", block[i]);
    }

    printf("\n");
}

void Generuj(TYPE* block, char* a, char* b)
{
    int _a = atoi(a); // funkcja atoi() odpowiada za parsowanie stringa do inta
    int _b = atoi(b);
    printf("x: %d, y: %d \n", _a, _b);
    LosujLiczby(block, _a, _b);
}

void LosujLiczby(TYPE* block, int a, int b) // funkcja losujaca 20 liczb podzielnych przez 3
{
    srand(time(NULL)); // incjowanie losowania
    
    int i = 0;
    for (i=0; i < SIZE; i++) 
    {
        unsigned int r = (rand() % b)+ a + 1;
        unsigned int dig = (r / 5) * 5;

        if (CzyUnikalne(block, i, dig)) // sprawdzanie czy liczby sa unikalne
        {
            if((dig >= a)) // jesli losowane liczby sa wieksze niż poczatek zakresu a
            {
                if((dig <= b)) // jesli losowane liczby sa mniejsze niż koniec zakresu b
                {
                    block[i] = dig; // dodawanie liczby do bloku naszej pamieci
                    //printf("%d\n", dig);
                }
            }
        }
    }
}

unsigned int CzyUnikalne(TYPE* block, int count,  int which) // funkcja sprawdzajaca czy liczby sa unikalne
{
    int i = 0;
    for (i=0; i < count; ++i)
    {
        if (block[i] == which)
        {
            return 0; // jesli sie powtarza zwraca 0
        }
    }
    return 1; // jesli nie zwraca 1
}

7330bf3268.png

0

Jakbyś tak wczytał?

scanf("%u", &koniec_przedzialu);
0

Wtedy przejdzie, ale w momencie gdzie ma wygenerować te 20 liczb podzielnych przez 5 wywala "segmentation foult" core dumped

d58b8c012e.png

0

Zamień generuj tak, żeby przyjmowała int zamiast char*. Nie będziesz musiał używać później atoi w funkcji losującej

0

Zmodyfikowałem funkcje generuje na taką:

void Generuj(TYPE* block, int a, int b)
{
//int _a = atoi(a);
//int _b = atoi(b);
printf("x: %d, y: %d \n", a, b);
LosujLiczby(block, a, b);
}

Ale teraz jest jakiś dziwny konflikt typów. :(

e3b31906c9.png

0

Coś z tymi wskaźnikami znowu.

ac66f4d717.png

0

Poczekaj proszę, już sie w tym pogubiłem. Na obecną chwilę mam tak:

 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <math.h>
#include <string.h>

#define PROJECTID 825 // unikalne ID dla pamięci współdzielonej
#define SIZE 20 // ilosc liczb do wylosowania
#define TYPE unsigned int


/*Zad 2. Z2.c podajemy 2 liczby zakres z którego będą liczby losowane do pam.
Wspólnej mamy zapisać 20 liczb które są podzielne przez 5 z tego zakresu który podaliśmy ma być zapisane 20 liczb
podzielnych liczb bez powtórzeń i teraz 3 param w wywołaniu tego zadania będzie odnosił się do...
jeśli podamy opcję w to ma zapisać do pam.
Wspólnej jeśli podamy opcję s to ma pokazać zawartośc pam/. Wspólnej jeśli podamy c pam. Wspólna zostaje wyczyszczona*/

void LosujLiczby(TYPE* block, int a, int b);
void Generuj(TYPE* block, int a, int b);
unsigned int CzyUnikalne(TYPE* block, int count, int which);
void Wypisz(TYPE* block);

int main(int argc, char** argv)
{
    printf("PID naszego procesu: %d\n", getpid()); // wyswietlanie PID naszego procesu

    key_t key = ftok("/tmp", PROJECTID); // ftok() zwraca klawisz oparty na sciezce
    int flag = IPC_CREAT | 0x1B6;
    TYPE* block; // specjalna zmienna dla pamieci wspoldzielonej
    int size = SIZE * sizeof(TYPE);

    printf("Tworzymy blok pamieci o rozmiarze: %d\n", size);

    //Proces składa żądanie alokacji lub uzyskania dostępu do istniejącego segmentu pamięci
    //współdzielonej wywołaniem funkcji shmget()
    int id = shmget(key, size, flag); // id pamieci zaalokowanej
    
    printf("Zaalokowane ID dla pamieci wspoldzielonej: %d\n", id); // drukowanie id pamieci zaalokowanej

    if (id > 0) // jesli id wieksze od 0
    {
        block = (TYPE*)shmat(id, NULL, 0); // dolaczenie pamieci zaalokowanej pod okreslonym id
        struct shmid_ds buffer;
        
        char opcja;
        printf("Wybierz jedna z dostepnych opcji: \n");
        printf("\n");
        printf("[ 'w' - aby generowac, 's' - aby wypisac, 'c' - aby wyczyscic ]\n");
        scanf("%c",&opcja);
        
        unsigned int poczatek_przedzialu = 0;
        unsigned int koniec_przedzialu = 0;
        
        switch(opcja)
        {
            case 'w':
                printf("Podaj poczatek przedzialu: ");
                scanf("%u",&poczatek_przedzialu);
                printf("Podaj koniec przedzialu: ");
                scanf("%u",&koniec_przedzialu);
                
                
                printf("Nastepuje generowanie liczb losowych z przedzialu [ %u , %u ] \n", poczatek_przedzialu, koniec_przedzialu);
                Generuj(block, (char*)&poczatek_przedzialu, (char*)&koniec_przedzialu); // zapis do pamieci wspolnej
                shmdt((void*)block); // zwalnianie pamieci
            break;
            
            case 's':
                printf("Wyswietlanie wylosowanych liczb! \n");
                Wypisz(block); //wyswietlamy zawartosc pamieci wspolnej
                shmdt((void*)block); // zwalnianie pamieci
            break;
            
            case 'c':    
                shmctl(id, IPC_RMID, &buffer); // czyscimy zawartosc pamieci wspolnej
            break;
        }
    }
    return 0;
}

void Wypisz(TYPE* block) // funkcja wypisujaca rezultaty na ekran
{
    int i = 0;
    for (i=0; i < SIZE; ++i)
    {
        printf("%d\t,", block[i]);
    }

    printf("\n");
}

void Generuj(TYPE* block, int a, int b)
{
    //int _a = atoi(a); // funkcja atoi() odpowiada za parsowanie stringa do inta
    //int _b = atoi(b);
    printf("x: %d, y: %d \n", a, b);
    LosujLiczby(block, a, b);
}

void LosujLiczby(TYPE* block, int a, int b) // funkcja losujaca 20 liczb podzielnych przez 3
{
    srand(time(NULL)); // incjowanie losowania
    
    int i = 0;
    for (i=0; i < SIZE; i++) 
    {
        unsigned int r = (rand() % b)+ a + 1;
        unsigned int dig = (r / 5) * 5;

        if (CzyUnikalne(block, i, dig)) // sprawdzanie czy liczby sa unikalne
        {
            if((dig >= a)) // jesli losowane liczby sa wieksze niż poczatek zakresu a
            {
                if((dig <= b)) // jesli losowane liczby sa mniejsze niż koniec zakresu b
                {
                    block[i] = dig; // dodawanie liczby do bloku naszej pamieci
                    //printf("%d\n", dig);
                }
            }
        }
    }
}

unsigned int CzyUnikalne(TYPE* block, int count,  int which) // funkcja sprawdzajaca czy liczby sa unikalne
{
    int i = 0;
    for (i=0; i < count; ++i)
    {
        if (block[i] == which)
        {
            return 0; // jesli sie powtarza zwraca 0
        }
    }
    return 1; // jesli nie zwraca 1
}


I co tu robie źle?

0

Po wywaleniu tych rzutowań teraz jest konflikt pomiędzy intem a unsigned intem*

z2.c: In function ‘main’:
z2.c5: warning: passing argument 2 of ‘Generuj’ makes integer from pointer without a cast [enabled by default]
Generuj(block, &poczatek_przedzialu, &koniec_przedzialu); // zapis do pamieci wspolnej
^
z2.c6: note: expected ‘int’ but argument is of type ‘unsigned int
void Generuj(TYPE
block, int a, int b);
^
z2.c5: warning: passing argument 3 of ‘Generuj’ makes integer from pointer without a cast [enabled by default]
Generuj(block, &poczatek_przedzialu, &koniec_przedzialu); // zapis do pamieci wspolnej
^
z2.c6: note: expected ‘int’ but argument is of type ‘unsigned int
void Generuj(TYPE
block, int a, int b);

0

Dobra wiem już. Sorki za faile ale zwykle nie programuje w c.

Program juz działą, przyczyną była refererencja w funkcji generuj.

 Generuj(block, poczatek_przedzialu, koniec_przedzialu); // zapis do pamieci wspolnej 

Dziękuję za pomoc!

0

Mam jeszcze jedno pytanie. Da się jakoś tak zrobić aby nie losował 0?

1

Internet podpowiada, żeby zrobić tak:

int wylosowane = rand() % (high - low) + low;
0

Jednak nie do końca. Podaje rzedział np od 10 do 120 i czasami losuje mi 0 :(

void LosujLiczby(TYPE* block, int a, int b) // funkcja losujaca 20 liczb podzielnych przez 5
{
    srand(time(NULL)); // incjowanie losowania
    
    int i = 0;
    for (i=0; i < SIZE; i++) 
    {
        unsigned int wylosowane = ((rand() % (b - a)) + a)+1;
        unsigned int podzielna = (wylosowane / 5) * 5;

        if (CzyUnikalne(block, i, podzielna)) // sprawdzanie czy liczby sa unikalne
        {
            if((podzielna >= a)) // jesli losowane liczby sa wieksze niż poczatek zakresu a
            {
                if((podzielna <= b)) // jesli losowane liczby sa mniejsze niż koniec zakresu b
                {
                    block[i] = podzielna; // dodawanie liczby do bloku naszej pamieci
                    //printf("%d\n", dig);
                }
            }
        }
    }
}
 

1 użytkowników online, w tym zalogowanych: 0, gości: 1