Warning przy kompilacji, jak poprawić?

0

Cześć,
podczas kompilacji tego kodu:

/* proces klienta */

#include <netdb.h> 
#include <string.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/un.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "baza.h"

#define SIZE sizeof(struct sockaddr_in)

int main()
{
	int sockfd;
	char c, rc;
	struct sockaddr_in server = {AF_INET, 7000};

	/* przeksztalc i zapamietaj adres ip serwera */
	server.sin_addr.s_addr = inet_addr("127.0.0.1");

	/* ustaw punkt koncowy transportu: */
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket call failed");
		exit(1);
	}

	/* polacz gniazdo z adresem serwera: */
	if (connect(sockfd, (struct sockaddr *)&server, SIZE) == -1)
	{
		perror("connect call failed");
		exit(1);
	}

	/* wysylaj i odbieraj informacje od serwera: */
	while(1)
	{
		rc='b';
			printf("Wybierz opcje:\nq - wyjscie\na - dodaj\nd - usun\ns - wyszukaj\n");
		
		scanf(" %c",&c);
		if (c == 'q')
			{	send(sockfd, &c, 1, 0);
				printf("Program konczy prace...\n");
				exit(0);
			}
		produkt * temp;
		int tempNumer;
			
		switch(c)
		{
			case 'a':
				temp = malloc(sizeof(produkt));

				printf("Podaj numer produktu[spacja]nazwa do 20 znakow[spacja]cena\n");
				scanf(" %d %s %f",&temp->numer, &temp->nazwa, &temp->cena);
				
				send(sockfd, &c, 1, 0);
				send(sockfd, temp, sizeof(produkt), 0);

				if(recv(sockfd, &rc, 1, 0) > 0)
				{
					if(rc == 'A')
						printf("Dodano pomyslnie!");
					else if(rc =='b')
						printf("Blad dodawania!");
				}
				else
				{
					printf("Server has died.\n");
					close(sockfd);
					exit(0);
				}
				free(temp);
			break;	
			
			case 'd':
				printf("Podaj numer produktu do usuniecia\n");
				scanf(" %d",&tempNumer);

				send(sockfd, &c, 1,0);
				send(sockfd, &tempNumer, sizeof(int), 0);

				if(recv(sockfd, &rc, 1, 0) > 0)
				{
					if(rc == 'D')
						printf("Usunieto pomyslnie!");
					else if(rc =='b')
						printf("Blad usuwania!");
				}
				else
				{
					printf("Server has died.\n");
					close(sockfd);
					exit(0);
				}
			break;
			
			case 's':
				printf("Podaj nr do wyszukania:\n");
				scanf(" %d", &tempNumer);

				send(sockfd,&c, 1, 0);
				send(sockfd,&tempNumer, sizeof(int), 0);

				produkt * temp = malloc(sizeof(produkt));
				if(recv(sockfd, &rc, 1, 0) > 0)
				{
					if(rc == 'S')
					{
						if(recv(sockfd, temp, sizeof(produkt), 0)>0)
						{
							printf("Znaleziono: %d %s %.2f", temp->numer, temp->nazwa, temp->cena);
							free(temp);
						}
						else
						{
							printf("Blad odpowiedzi na zapytanie!");
						}
					}
					else if(rc =='b')
						printf("Blad szukania!");
				}
				else
				{
					printf("Server has died.\n");
					close(sockfd);
					exit(0);
				}
			break;
		}


	}
}

otrzymuję taki warning:

gcc -o klient klient.c
klient.c: In function ‘main’:
klient.c5: warning: format ‘%s’ expects argument of type ‘char ’, but argument 3 has type ‘char ()[21]’ [-Wformat=]
scanf(" %d %s %f",&temp->numer, &temp->nazwa, &temp->cena);
^

Jak to poprawić?

0

Podaj definicję produkt

1

Popraw na:

scanf(" %d %s %f",&temp->numer, temp->nazwa, &temp->cena);

bo temp->nazwa już jest wskaźnikiem na blok pamięci (nieściśle: tablicę), więc nie należy brać adresu tego wskaźnika.

0

twonek dziękuję bardzo, działa!!! :)

Czy mógłbyś jeszcze "rzucić okiem" na ten kod i powiedzieć, czy widzisz tam jakąś oczywistą głupotę czy może tak zostać? (program do szkoły na zaliczenie)

1

Każdą z opcji (każdy case w switchu) obsłużyłbym w osobnej funkcji, a cały kod bym wrzucił do http://format.krzaq.cc/ żeby poprawił wcięcia (styl file).

0

Dzięki za porady, skorzystam z tego formatowania kodu, nawet nie wiedziałem, że coś takiego jest :)

A rzuciłbyś okiem jeszcze na kod serwera?

/* proces serwera */

#include <netdb.h> 
#include <string.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/un.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "baza.h"

#define SIZE sizeof(struct sockaddr_in)
#define ROZMIARBAZY 100

produkt * baza[ROZMIARBAZY];

produkt * wyszukajWBazie(int szukanyNumer);
int dodajDoBazy(produkt * dodawanyProdukt);
int usunZBazy(int szukanyNumer);
void drukujBaze();
void wczytajBaze();
void zapiszBaze();
void catcher(int sig);
int newsockfd;


int main()
{
	printf("Serwer jest gotowy aby przyjac zapytanie...\n");

	int sockfd;
	char c;
	/* zainicjuj gniazdo internetowe z numerem portu 7000
	 * i adres lokalny, okreslany jako INADDR_ANY
	 */
	struct sockaddr_in server = {AF_INET, 7000, INADDR_ANY};
	static struct sigaction act;

	act.sa_handler = catcher;
	sigfillset(&(act.sa_mask));
	sigaction(SIGPIPE, &act, NULL);

	/* ustaw punkt koncowy transportu: */
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket call failed");
		exit(1);
	}

	/* zwiaz adres serwera z punktem koncowym */
	if (bind(sockfd, (struct sockaddr *)&server, SIZE) == -1)
	{
		perror("bind call failed");
		exit(1);
	}

	/* zacznij nasluchiwac przychodzacych polaczen */
	if (listen(sockfd, 5) == -1)
	{
		perror("listen call failed");
		exit(1);
	}
	
	wczytajBaze();



	for( ; ; )
	{
		/* przyjmij polaczenie */
		if((newsockfd = accept(sockfd, NULL, NULL)) == -1)
		{
			perror("accept call failed");
			continue;
		}

			/* odbierz dane: */
			while (recv(newsockfd, &c, 1, 0) > 0)
			{
				/* zamien na wielkie litery i odeslij z powrotem: */
						if (c == 'q')
						{
							printf("Program konczy prace...\n");
							zapiszBaze();
							exit(0);
						}
						else if(c == 'a')
						{
							produkt *temp = malloc(sizeof(produkt));
							if(recv(newsockfd, temp, sizeof(produkt),0)>0)
							{
								if(!dodajDoBazy(temp))
								{
									c = toupper(c);
									send(newsockfd, &c, 1, 0);
								}
								else
								{
									c='b';
									send(newsockfd, &c, 1, 0);
								}
							}
							else
							{
								c = 'b'; //blad
								send(newsockfd, &c, 1, 0);
							}
							drukujBaze();
						}
						else if(c == 'd')
						{
							int numer;
							if(recv(newsockfd, &numer, sizeof(int),0)>0)
							{
								if(!usunZBazy(numer))
								{
									c = toupper(c);
									send(newsockfd, &c, 1, 0);
								}
								else
								{
									c='b';
									send(newsockfd, &c, 1, 0);
								}
							}
							else
							{
								c='b';
								send(newsockfd, &c, 1, 0);
							}
							drukujBaze();
						}
						else if(c == 's')
						{
							int numer;
							if(recv(newsockfd, &numer, sizeof(int),0)>0)
							{
								produkt *temp = malloc(sizeof(produkt));
								temp = wyszukajWBazie(numer);
								if(temp)
								{
									c = toupper(c);
									send(newsockfd, &c, 1, 0);
									send(newsockfd, temp, sizeof(produkt),0);
								}
								else
								{
									c = 'b';
									send(newsockfd, &c, 1, 0);
								}
							}
							else
							{
								c='b';
								send(newsockfd, &c, 1, 0);
							}
							drukujBaze();
						}
						else
						{
							c = 'b';
							send(newsockfd, &c, 1, 0);
						}
				
		}
	}
}

void catcher (int sig)
{
	close(newsockfd);
	exit (0);
}

produkt * wyszukajWBazie(int szukanyNumer)
{
	int i =0;
	while(baza[i] != NULL) //dopoki cos jest w bazie pod tym wskaznikiem
	{
		if(baza[i]->numer == szukanyNumer)
		{
			return baza[i];//znaleziono pod i
		}
		i++;
	}
	return NULL; //nic nie znaleziono
}

int dodajDoBazy(produkt * dodawanyProdukt)
{
	if(wyszukajWBazie(dodawanyProdukt->numer))
	{
		return -1; //juz istnieje
	}

	int i =0;
	while(baza[i] != NULL)
	{
		i++;
		if(i==(ROZMIARBAZY-1))
		{
			return -1; //blad
		}
	}

	baza[i] = dodawanyProdukt;
	return 0;//jest ok
}

int usunZBazy(int szukanyNumer)
{
	printf("Wywolano usun z kodem: %d\n", szukanyNumer);
	produkt * temp = wyszukajWBazie(szukanyNumer);
	if(!temp)
	{
		return -1; //taki produkt nie istnieje
	}
	
		int i = 0;
		while((baza[i] != NULL) && (baza[i]->numer != szukanyNumer))
		{
			i++;
		}

		free(baza[i]);
		
		while(baza[i+1]!= NULL)
		{
			baza[i] = baza[i+1];
			i++;
		}
	
		baza[i] = NULL;
		
		return 0; //operacja sie powiodla, pacjent zmarl :)
}

void drukujBaze()
{
	printf("-----------------------Wydruk Bazy----------------\n");
	int i = 0;
	while(baza[i] != NULL)
	{
		printf("%d  %s  %.2f\n",baza[i]->numer,baza[i]->nazwa,baza[i]->cena);
		i++;
	}
}

void wczytajBaze()
{
	FILE * fp;
	char * linia =NULL; 
	size_t dlu = 0;
	ssize_t odczyt;

	fp = fopen("baza.txt","r");
	if(fp == NULL)
	{
		exit(-1);
	}
	int i = 0;
	while((odczyt = getline(&linia, &dlu, fp))!= -1)
	{
		char ogranicznik[] = "@";//musi byc w tablicy bo gcc sie pluje, tak podaja wszystkie poradniki, zawsze mozna to rozszerzyc:)
		baza[i] = malloc(sizeof(produkt));//alokacja pamieci na produkt
		baza[i]->numer = atoi( (char *)strtok(linia,ogranicznik) ); //atoi konwertuje stringa na inta, strtok opisze pod spodem
		strncpy(baza[i]->nazwa, (char *)strtok(NULL, ogranicznik), 20); //kopiowanie do 20 znakow 
		baza[i]->cena = atof( (char *)strtok(NULL, ogranicznik)); //atof = atoi tylko na floata
		printf("Wczytano: %d  %s  %.2f\n",baza[i]->numer,baza[i]->nazwa,baza[i]->cena); //wydruk %.2f oznacza drukuj float do dwoch liczb po ,
		i++;
	}

	if(linia)
	{
		free(linia);
	}

	fclose(fp);
}

void zapiszBaze()
{
	FILE *fp = fopen("baza.txt","wt"); //write, text
	
	if(!fp)
	{
		printf("BLAD ZAPISU");
		exit(-1);
	}
	
	int i = 0;
	
	while(baza[i] != NULL)
	{
		printf("%d@%s@%.2f\n",baza[i]->numer,baza[i]->nazwa,baza[i]->cena);
		fprintf(fp,"%d@%s@%.2f\n",baza[i]->numer,baza[i]->nazwa,baza[i]->cena);
		i++;
	}
	fclose(fp);
}
0

Witam,
a o co chodzi z tym warningiem ppodczas kompilacji serwera z opcją -Wall???

gcc -Wall serwer.c -o serwer
serwer.c: In function ‘main’:
serwer.c12: warning: missing braces around initializer [-Wmissing-braces]
struct sockaddr_in server = { AF_INET, 7000, INADDR_ANY };
^
serwer.c12: warning: (near initialization for ‘server.sin_addr’) [-Wmissing-braces]

0

Pierwszy wynik, który google wypluł po wpisaniu "missing braces around initializer":
http://stackoverflow.com/questions/11551986/gcc-missing-braces-around-initializer

0

Hmm chyba chodzi o to że czegoś nie zadeklarowałem jeszcze... gdzieś trzeba będzie 0 dopisać... pewnie w tej strukturze:
{ AF_INET, 7000, INADDR_ANY };
Dobrze myśle?

Mój angielski pozostawia wiele do życzenia :D

0
struct in_addr {
    unsigned long s_addr;  // load with inet_aton()
};

struct sockaddr_in {
    short            sin_family;   // e.g. AF_INET
    unsigned short   sin_port;     // e.g. htons(3490)
    struct in_addr   sin_addr;     // see struct in_addr, below
    char             sin_zero[8];  // zero this if you want to
};

Ta struktura ma 4 składowe, a podałeś tylko 3

struct sockaddr_in address = { AF_INET, 7000, {INADDR_ANY}, {0} };

Klamry są tam, gdzie składowa nie jest zmienną prostą, tylko strukturą lub tablicą. Jeśli tego nie rozumiesz to wyobraź sobie

int tab[10] = 0;
int tab[10] = {0};

który z powyższych wariantów jest poprawny?

0

Cześć!
Więc wg mnie to jest zapis poprawny:

int tab[10] = 0;

gdzie do 11 elementu tablicy wpisuje cyfrę 0.

Ten zapis:

int tab[10] = {0};

jest jakiś taki egzotyczny :-) Przypomina mi "zbiór pusty" z matematyki :-)

Rozumiem, że inicjowanie struktury lub tablicy wartościami odbywa się w klamrach {} ale czemu nie może być tak:

struct sockaddr_in address = {AF_INET, 7000, INADDR_ANY, 0};

Przecież np. numer portu - 7000 podaje się bez klamerek a to też integer tak samo jak zero 0 ??

Pozdrawiam!
Krzysiek.

0
Mały Kaczor napisał(a):

Więc wg mnie to jest zapis poprawny:

int tab[10] = 0;

Źle Ci się wydaje.

gdzie do 11 elementu tablicy wpisuje cyfrę 0.
tab[10] nie ma 11-stego elementu. Poza tym to ma być inicjalizacja całej tablicy, a nie wpisanie jednego elementu do tablicy.

Ten zapis:

int tab[10] = {0};

jest jakiś taki egzotyczny :-) Przypomina mi "zbiór pusty" z matematyki :-)
Jak więcej kodu zobaczysz, to przestanie się wydawać egzotyczny.

Rozumiem, że inicjowanie struktury lub tablicy wartościami odbywa się w klamrach {} ale czemu nie może być tak:

struct sockaddr_in address = {AF_INET, 7000, INADDR_ANY, 0};

Przecież np. numer portu - 7000 podaje się bez klamerek a to też integer tak samo jak zero 0 ??
Bo powiedzenie zmienna prosta X ma wartość 7000 ma sens, natomiast tablica Y ma wartość 0 już nie. Trzeba powiedzieć każda komórka tablicy Y ma wartość 0.

0

Aaaaa....
Teraz jak to napisałeś te dwa ostatnie zdania to faktycznie ma sens!!!

1

int tab[10] = {0};

To jest inicjalizacja pierwszego ([0]) elementu tablicy wartością podaną (0) a pozostałych wartością domyślną (0).

Takie coś

int tab[10] = {1, 2, 3, [8]=42, 10};

jest równoważne temu:

int tab[10] = {1, 2, 3, 0, 0, 0, 0, 0, 42, 10};
0

int tab[10] = {0};

To jest inicjalizacja pierwszego ([0]) elementu tablicy wartością podaną (0) a pozostałych wartością domyślną (0).

W takim razie co oznacza poniższy zapis?

int tab[1] = {0} 

??

To co napisał Azarien to jest chyba inicjalizacja 10tego elementu tablicy..

2

Mylisz 2 zapisy:

int tab[10] = ...

oraz

tab[10] = ... 

W pierwszym przypadku to inicjalizacja tablicy 10-elementowej. W drugim przypisanie do 11-stego elementu tablicy (o indeksie 10) jakiejś wartości.

Tym samym

int tab[1] = {0};

to inicjalizacja tablicy 1-elementowej. Sensu większego nie ma, bo można użyć zwykłej zmiennej, ale jest poprawne. Tylko potem trzeba pamiętać, że taka tablica ma tylko jeden element o indeksie 0.

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