Cannot return values of char variable

P

Pedro Pinto

Hi there once more........

Instead of showing all the code my problem is simple.

I've tried to create this function:

char temp(char *string){

alterString(string);
return string;
}

char alterString(char *string){}

temp receives a string and uses the alterString to modify it.

My issue is simple, when i pass the argument string to alterString it
appears in the function alterString has being empty.

I've tried changing the signatures of the functions to
char temp(char string){
char alterString(char string){}


but the issue still occurs......


Can please somebody give me just a little example of the working
function.......... it would really help.....

thanks in advance for every support you have given to me this night.
 
T

T.M. Sommers

Pedro said:
Hi there once more........

Instead of showing all the code my problem is simple.

I've tried to create this function:

char temp(char *string){

alterString(string);
return string;
}

This function is defined as returning a char, but it is trying to
return a char *.
char alterString(char *string){}

temp receives a string and uses the alterString to modify it.

My issue is simple, when i pass the argument string to alterString it
appears in the function alterString has being empty.

Maybe it was empty when passed to temp. There is no way to tell
from what you have given. Create a small, complete program that
displays the problem, and post it. Then people might be able to
help.
 
M

Martin Ambuhl

Pedro said:
Hi there once more........

Instead of showing all the code my problem is simple.

I've tried to create this function:

char temp(char *string){

alterString(string);
return string;
}

'string' is a char *; your function returns a char.
 
P

Pedro Pinto

Ok here it goes:

The problem is, when the function menu starts, i insert the information


CREATE TABLE [tab] col1,col2,col3

that starts the function criaRespCreate and the buf variable, when
exported into the program, before is ok, i print it to the screen and
appears well, but when returned it comes empty.......

I start the client socked, the result of the printf's:

sd075@lab1215-31:~/Desktop/teste/Cliente$ ./clisql 17500
Sintaxe do programa cliente:
clisql -s <endereço_servidor> <porto_servidor>
-endereço_servidor: (opcional) IP do servidor
-porto_servidor: porto do servidor
Insira comando:
CREATE TABLE [tab] col1,col2,col3
1 - buffer =

2 - buffer =

passei o primeiro divide com aux[0] = CREATE TABLE

passei o primeiro divide com aux[1] = tab] col1,col2,col3


passei o segundo divide com aux[0] = tab

passei o segundo divide com aux[1] = col1,col2,col3


dpx do memcpy aux[0] = tab

dpx do memcpy aux[1] = col1,col2,col3


buffer =

antes do strcpy - aux[1] =

argv[0] = (null)
No test to search.




Code --------------------------


cliente_aux.c



#include "cli.h"


void syntax() {



printf("Sintaxe do programa cliente:\n");

printf(" clisql -s <endereço_servidor>
<porto_servidor>\n");

printf(" -endereço_servidor: (opcional) IP do
servidor\n");

printf(" -porto_servidor: porto do servidor\n");

}

void sintaxe(){
printf("Sintaxe do programa cliente:\n");

printf("CREATE TABLE [table_name] coluna1,coluna2,coluna3...\n");

printf("INSERT INTO [table_name] VALUES
(coluna1_value,coluna2_value,coluna3_value...) \n");

printf("UPDATE [table_name] SET (Coluna) WHERE (expressao)\n");
printf("SELECT [Coluna] FROM (table_name) WHERE (expressao)\n");

}

char menu(){

char buf[BUFFSIZE];
char bufSaida[BUFFSIZE];

char *tmp = buf;
int cod = 0;
int id = random();
int tamanhoMsg;

printf("Insira comando:\n");

// le uma linha de input
if (fgets(buf,sizeof(buf),stdin) == NULL)
perror("fgets");

char comando[10];
memset(comando,0,sizeof(comando));
if (sscanf(buf,"%9s",comando) < 1)
perror("scanf");

if (strncmp(buf,"CREATE",6) == 0){
cod = 11;

tamanhoMsg = criaRespCreate(cod,id, buf,bufSaida);
}
else if(strncmp(buf,"INSERT",6) == 0){
cod = 12;
//buffer =criaRespInsert(cod,id, buf);
}
else if(strncmp(buf,"UPDATE",6) == 0){
cod = 13;
//buffer =criaRespUpdate(cod,id, buf);
}
else if(strncmp(buf,"SELECT",6) == 0){
cod = 14;
//buffer =criaRespSelect(cod,id, buf);
}
else if(strncmp(buf,"QUIT",4) == 0){
exit(0);
}
else { printf("Comando Desconhecido\n");
}


return bufSaida;
}



int criaRespCreate(int cod, int id, char *argv, char *buffer){

int tam = 0;
int nRows = 0;
char *aux[strlen(argv)];
char str[]=" // ";
int h = 0;
//tamanho do caracter delimitador
int tcd = strlen(str);

// inserir codigo

memcpy(buffer,&cod,LENGTH);
tam += LENGTH;

printf("1 - buffer = %s\n", buffer);

// inserir caracter delimitador //
memcpy(buffer+tam,&str,strlen(str));
tam += tcd;

printf("2 - buffer = %s\n", buffer);
// inserir id da mensagem
memcpy(buffer+tam, &id, LENGTH);
tam += LENGTH;

// inserir caracter delimitador //
memcpy(buffer+tam,&str,strlen(str));
tam += tcd;

// dividir string e inserir nome tabela
divide(argv,aux,"[");

printf("passei o primeiro divide com aux[0] = %s\n\n", aux[0]);
printf("passei o primeiro divide com aux[1] = %s\n\n", aux[1]);

memset(argv,0,strlen(aux));
strcpy(argv,aux[1]);
memset(aux,0,strlen(argv));
divide(argv,aux,"]");

printf("passei o segundo divide com aux[0] = %s\n\n", aux[0]);
printf("passei o segundo divide com aux[1] = %s\n\n", aux[1]);
memcpy(buffer+tam,&aux[0],strlen(aux[0]));
tam += strlen(aux[0]);


printf("dpx do memcpy aux[0] = %s\n\n", aux[0]);
printf("dpx do memcpy aux[1] = %s\n\n", aux[1]);
// inserir caracter delimitador
memcpy(buffer+tam,&str,strlen(str));
tam += tcd;
printf("buffer = %s\n", buffer);

// inserir numero e nome colunas

memset(argv,0,strlen(aux[1]));
printf("antes do strcpy - aux[1] = %s\n\n", aux[1]);
strcpy(argv,aux[1]);
printf("argv[0] = %s\n", argv[0]);
memset(aux,0,strlen(argv));
divide(argv,aux,",");

printf("passei o terceiro divide com aux[0] = %s\n\n", aux[0]);
printf("passei o terceiro divide com aux[1] = %s\n\n", aux[1]);
printf("passei o terceiro divide com aux[2] = %s\n\n", aux[2]);

printf("str(aux) = %d\n", strlen(aux));
// inserir numero de colunas
for(h=0; aux[h]!=NULL;h++){
nRows++;
}

memcpy(buffer+tam, nRows, LENGTH);
tam += LENGTH;

// inserir caracter delimitador
memcpy(buffer+tam,&str,strlen(str));
tam += tcd;


// inserir colunas

for(h=0; aux[h]!=NULL;h++){
memcpy(buffer+tam,&aux[h],strlen(aux[h]));
tam += tcd;
// inserir caracter delimitador
memcpy(buffer,&str,strlen(str));
tam += tcd;

}
return buffer;
}


-------------------------------------------

clisql.c--------------






#include "cli.h"




/* Funcao Main */

int main (int argc, char *argv[]) {



syntax();
/* Funcaoo que apresenta sintaxe do programa */







int sock;

int broadcast = 1;

struct sockaddr_in server;

struct sockaddr_in cli;

int porto_servidor;
char buffer[BUFFSIZE];
char *tmp = buffer;
tmp = buffer;

char input[1024];


/* Limpa a estrutura */

bzero((char *)&server, sizeof(server));

bzero((char *)&cli, sizeof(cli));

/* Limpar o buffer */

memset(buffer, 0, BUFFSIZE);


input[0] = menu(buffer);





/* Criacao da socket */

if ((sock = socket(AF_INET,SOCK_DGRAM,0)) <0) {

perror("socket");

exit(1);

}

else {

printf("Cliente: socket criada \n");

}



/* Verificar ip */
if(strcmp(argv[1], "-s") == 0) {

printf("entrei n o verifica ip, estamos a funcionar com endereco ip
inserido\n");

inet_aton(argv[2], &server.sin_addr);
porto_servidor = atoi(argv[3]);


}

else {//enviar em broadcast

printf("Não foi fornecido o endereço IP, a enviar em broadcast\n");

porto_servidor = atoi(argv[1]);
server.sin_addr.s_addr = htonl(INADDR_BROADCAST);


/* Activar broadcast na socket */

if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast,
sizeof (int)) <0) {

perror("setsockopt");

exit(1);

}

}


/* verifica se a porta esta entre os valores pretendidos,

* visto o número de grupo ser o 75, port vai variar entre

* 17500 e 17599 */
void checkPort(porto_servidor) {



if(porto_servidor < 17500 || porto_servidor > 17599) {

printf("Cliente: O porto tem de ser entre 17500 e 17599!\n");

exit(-1);

}

}







/* Definir a familia de protocolo e porto */

server.sin_family = AF_INET;

server.sin_port = htons(porto_servidor);






/* Inicio da comunicacao com o servidor */










/* Enviar a mensagem para o servidor*/

if(sendto(sock, tmp, strlen(buffer), 0, (struct sockaddr *)&server,
sizeof(server)) <0) {

perror("sendto\n");

exit(1);

}

else {

printf("Cliente: Mensagem enviada com sucesso\n");



}



while(1){
printf("entrei no while\n");

/* timeout de 10 segundos */
struct timeval timeout;
timeout.tv_sec = 10; //segundos

timeout.tv_usec = 0; //microsegundos



fd_set readfds;

int sel;

// char buf1[64];



/* limpar a fd_set */

FD_ZERO(&readfds);



/* colocar o file descriptor no fd_set */

FD_SET(sock, &readfds);

printf("vou ver agora o select\n");

if((sel = select(sock+1, &readfds, NULL, NULL, &timeout)) <0)
perror("select\n");




else if (sel == 0){

printf("Ocorreu um timeout! Nao foi recebida nenhuma mensagem em
10s.\n");

exit(0);
}

memset(buffer,0,BUFFSIZE);


printf("vou agora ler a resposta do servidor\n");

/* ler a resposta do servidor */

if(recvfrom(sock, buffer, BUFFSIZE, 0, NULL, NULL) < 0) {
printf("entrei no recv por ser < 0\n");

perror("recvfrom\n");

exit(1);

}

else {

printf("Cliente: Mensagem recebida com sucesso\n");

printf("buffer = %s\n", buffer);
exit(0);
}

}





/* fecho da socket */

close(sock);


}




----------------------cli.h--------------------------------------

#ifndef CLI_H
#define CLI_H

#include "projecto.h"


/* Definicao das funcoes definidas em cliente_aux.c */



void syntax();

char menu();

int criaRespCreate(int cod, int id, char *argv, char *buffer);









#endif



--------------------------projecto.h----------------------------------------


#ifndef PROJECTO_H

#define PROJECTO_H



#define BUFFSIZE 6804
#define LENGTH 4



/* Bibliotecas necessarias */

#include <sys/socket.h>

#include <sys/types.h>

#include <stdio.h>

#include <errno.h>

#include <sys/time.h>

#include <stdlib.h>
#include <arpa/inet.h>

#include <netinet/in.h>

#include <netdb.h>
#include <string.h>





#endif
 
M

mark_bluemel

Pedro said:
Hi there once more........

Instead of showing all the code my problem is simple.

OK - so give us a simple testcase.
I've tried to create this function:

char temp(char *string){

alterString(string);
return string;
}

char alterString(char *string){}

temp receives a string and uses the alterString to modify it.

OK - so write a minimal testcase which uses these functions to work
with a string, show us the whole code (cut and paste, don't retype),
tell us what input you gave it, what output you expected and what
output you got. Then we've got something to work on.

Here's the sort of thing I mean (this is just an example, which I
didn't expect to work) :-

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

char alterString(char *string){}

char temp(char *string){

alterString(string);
return string;
}

int main(void) {

char myString[]="Hello Pedro";
printf("I started with [%s]\n",myString);

printf("I got [%s]\n",temp(myString));

return EXIT_SUCCESS;
}


When I compiled it, I had this warning from gcc:-
pedro.c: In function `temp':
pedro.c:9: warning: return makes integer from pointer without a
cast

When I ran it, this happened:-
./pedro
I started with [Hello Pedro]
Segmentation fault

Which is fair - temp() returns a char, not a char *, but I told printf
to treat it as the address of (the first of) a null-terminated set of
characters.

I think part of your problem is that temp() and alterString() should be
declared as returning char *, not char, but beyond that - who knows?
 
M

mark_bluemel

Pedro said:
Ok here it goes:
[unnecessary detail snipped]

What part of Thomas Sommers' message - "Create a small, complete
program that
displays the problem, and post it." - don't you understand?

You said your problem was with two small functions, so write a small
program that just contains those functions and enough code (in a main()
function) to test them. This is, IMHO, basic programming craft...
 
P

Pedro Pinto

Ok, here it goes.

The problem is that i cannot, like in this example, return a char[]
correctly.

in this case i have do create a void function.

Although *array[] param keeps the alteration made to it i cannot do
this function with this signature:

char divide(char search_string[], char *array[], char *delimiter)

and return correctly the string.


Can you give me some tips on how i could return a string (or char
array) in this divide function?

Thank for all the help!
--------------------------------------------


void divide(char search_string[], char *array[], char *delimiter){



int loop;



array[0]=strtok(search_string,delimiter);

if(array[0]==NULL)

{

printf("No test to search.\n");

exit(0);

}



for(loop=1;loop<50;loop++)

{

array[loop]=strtok(NULL,delimiter);

if(array[loop]==NULL)

break;

}



for(loop=0;loop<50;loop++)

{

if(array[loop]==NULL)

break;



//printf("\nDivide - array[%d] = %s", loop,array[loop]);



}

}
 
C

CoL

Hi,
yup fuction sinature should be char* and more over when you passing
char* from main to temp and temp to alterstring make sure in
alterstring plays around with its value not address.
else pass alterstring(&string)----making its signature.
char* alterstring(char** str).This way your return string would hold
the new allocated memory address and its value.

Regards
Ap
 
M

mark_bluemel

Pedro said:
Ok, here it goes.

The problem is that i cannot, like in this example, return a char[]
correctly.

in this case i have do create a void function.

Although *array[] param keeps the alteration made to it i cannot do
this function with this signature:

char divide(char search_string[], char *array[], char *delimiter)

(Yet again) That function would be have to return a single character.

If you want to return a string, you must return a pointer to the first
character of the null delimited array of characters - e.g. char
*divide(...).

If you want to return an array of strings, meaning an array of pointers
to null-delimited arrays of characters, using char **divide() would be
appropriate.
 
P

Prasad

Pedro said:
Ok, here it goes.
<problem description and code snippet sniped>

For your implementation of the divide function , i have created the
following test case (which I guess was what Mark was asking you to do).

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

void divide(char search_string[], char *array[], char *delimiter){
int loop;
array[0]=strtok(search_string,delimiter);

if(array[0]==NULL)
{
printf("No test to search.\n");
exit(0);
}

for(loop=1;loop<50;loop++)
{
array[loop]=strtok(NULL,delimiter);

if(array[loop]==NULL)
break;
}

for(loop=0;loop<50;loop++)
{
if(array[loop]==NULL)
break;
//printf("\nDivide - array[%d] = %s", loop,array[loop]);
}
}

int main(void) {
int i = 0 ;
char *arr[50];

divide("this,is,comma,separated,string", arr ,",");

printf("Divided contents\n");
for(i = 0; i < 50; i++)
{
if(arr==NULL)
break;

printf("%s \n", arr);
}
return 0;
}

Compilation :

Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.00.9466 for 80x86
Copyright (C) Microsoft Corporation 1984-2001. All rights reserved.

sample.c
sample.c(6) : warning C4047: '=' : 'char *' differs in levels of
indirection from 'int'
sample.c(16) : warning C4047: '=' : 'char *' differs in levels of
indirection from 'int'
Microsoft (R) Incremental Linker Version 7.00.9466
Copyright (C) Microsoft Corporation. All rights reserved.

/out:sample.exe
sample.obj

Execution Result :

Divided contents
this
is
comma
separated
string

I am not sure what you want to return from divide function.
 
P

Pedro Pinto

Prasad escreveu:
Pedro said:
Ok, here it goes.
<problem description and code snippet sniped>

For your implementation of the divide function , i have created the
following test case (which I guess was what Mark was asking you to do).

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

void divide(char search_string[], char *array[], char *delimiter){
int loop;
array[0]=strtok(search_string,delimiter);

if(array[0]==NULL)
{
printf("No test to search.\n");
exit(0);
}

for(loop=1;loop<50;loop++)
{
array[loop]=strtok(NULL,delimiter);

if(array[loop]==NULL)
break;
}

for(loop=0;loop<50;loop++)
{
if(array[loop]==NULL)
break;
//printf("\nDivide - array[%d] = %s", loop,array[loop]);
}
}

int main(void) {
int i = 0 ;
char *arr[50];

divide("this,is,comma,separated,string", arr ,",");

printf("Divided contents\n");
for(i = 0; i < 50; i++)
{
if(arr==NULL)
break;

printf("%s \n", arr);
}
return 0;
}

Compilation :

Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.00.9466 for 80x86
Copyright (C) Microsoft Corporation 1984-2001. All rights reserved.

sample.c
sample.c(6) : warning C4047: '=' : 'char *' differs in levels of
indirection from 'int'
sample.c(16) : warning C4047: '=' : 'char *' differs in levels of
indirection from 'int'
Microsoft (R) Incremental Linker Version 7.00.9466
Copyright (C) Microsoft Corporation. All rights reserved.

/out:sample.exe
sample.obj

Execution Result :

Divided contents
this
is
comma
separated
string

I am not sure what you want to return from divide function.



I can do that inside main. What i can't do is with divide:

char divide(char search_string[], char *array[], char *delimiter)

and return the string you printed! Can this be done?
 
J

Jens Thoms Toerring

Pedro Pinto said:
Ok here it goes:
The problem is, when the function menu starts, i insert the information
CREATE TABLE [tab] col1,col2,col3
that starts the function criaRespCreate and the buf variable, when
exported into the program, before is ok, i print it to the screen and
appears well, but when returned it comes empty.......
I start the client socked, the result of the printf's:
sd075@lab1215-31:~/Desktop/teste/Cliente$ ./clisql 17500
Sintaxe do programa cliente:
clisql -s <endere?o_servidor> <porto_servidor>
-endere?o_servidor: (opcional) IP do servidor
-porto_servidor: porto do servidor
Insira comando:
CREATE TABLE [tab] col1,col2,col3
1 - buffer =
2 - buffer =
passei o primeiro divide com aux[0] = CREATE TABLE
passei o primeiro divide com aux[1] = tab] col1,col2,col3
passei o segundo divide com aux[0] = tab
passei o segundo divide com aux[1] = col1,col2,col3
dpx do memcpy aux[0] = tab
dpx do memcpy aux[1] = col1,col2,col3
buffer =
antes do strcpy - aux[1] =
argv[0] = (null)
No test to search.
Code --------------------------

#include "cli.h"
void syntax() {
printf("Sintaxe do programa cliente:\n");
printf(" clisql -s <endere?o_servidor>
<porto_servidor>\n");
printf(" -endere?o_servidor: (opcional) IP do
servidor\n");
printf(" -porto_servidor: porto do servidor\n");
}
void sintaxe(){
printf("Sintaxe do programa cliente:\n");
printf("CREATE TABLE [table_name] coluna1,coluna2,coluna3...\n");
printf("INSERT INTO [table_name] VALUES
(coluna1_value,coluna2_value,coluna3_value...) \n");
printf("UPDATE [table_name] SET (Coluna) WHERE (expressao)\n");
printf("SELECT [Coluna] FROM (table_name) WHERE (expressao)\n");
}
char menu(){

Since you seem to be trying to return a char pointer (not just a char)
the function must be declared accordingly (and it doesn't take an
argument, so tell the compiler):

char *menu( void )
char buf[BUFFSIZE];
char bufSaida[BUFFSIZE];
char *tmp = buf;
int cod = 0;
int id = random();
int tamanhoMsg;
printf("Insira comando:\n");
// le uma linha de input
if (fgets(buf,sizeof(buf),stdin) == NULL)
perror("fgets");

I gues it would make no sense to continue if fgets() failed to
obtain user input, does it?
char comando[10];

Please remember that defining new variables randomly within a function
is a C99 feature - you may run into trouble with this if your compiler
doesn't support C99.
memset(comando,0,sizeof(comando));

This is not necessary.
if (sscanf(buf,"%9s",comando) < 1)
perror("scanf");

Again, is it a good idea to continue even though sscanf() failed?
But then, what is 'comando' used for at all? It's not used anywhere
below.
if (strncmp(buf,"CREATE",6) == 0){
cod = 11;
tamanhoMsg = criaRespCreate(cod,id, buf,bufSaida);
}
else if(strncmp(buf,"INSERT",6) == 0){
cod = 12;
//buffer =criaRespInsert(cod,id, buf);
}
else if(strncmp(buf,"UPDATE",6) == 0){
cod = 13;
//buffer =criaRespUpdate(cod,id, buf);
}
else if(strncmp(buf,"SELECT",6) == 0){
cod = 14;
//buffer =criaRespSelect(cod,id, buf);
}
else if(strncmp(buf,"QUIT",4) == 0){
exit(0);
}
else { printf("Comando Desconhecido\n");
}
return bufSaida;

Now, here's a very serious problem (beside the one that you defined
menu() to return a char, not a char pointer): you return a pointer
to an array that is only defined while you're within the menu()
function. Once you have left the function you can't use the buffer
anymore! Once the function has ended 'bufSaida' goes out of scope
and doing anything with the return value is wrong and it can crash
your program, it can seem to work flawlessly or it can seem to work
at first but then result in strange results.
}

int criaRespCreate(int cod, int id, char *argv, char *buffer){

I would recommend _not_ to use 'argv' as a variable or argument
name since everybody reading your code will be confused since
'argv' (and 'argc') are the traditional names of the arguments
main() is invoked with.
int tam = 0;
int nRows = 0;
char *aux[strlen(argv)];

Some compilers will complain here since the length of that array
isn't known at compile time (but since you seem to be using a
C99 compiler anyway it's ok).
char str[]=" // ";
int h = 0;
//tamanho do caracter delimitador
int tcd = strlen(str);
// inserir codigo
memcpy(buffer,&cod,LENGTH);

Why would you directly copy an integer to a char buffer? That hardly
makes any sense. You won't have a textual representation of the number
in the buffer but some bytes that don't make any sense when the
content is interpreted as a string. Moreover, you don't have a '\0'
character at the end, so trying to use 'buffer' as it were a string
(as you do below) is a receipe for disaster. Perhaps waht you really
want here is sprintf()?

And if you really want to copy the bytes of an integer than you
should use 'sizeof(int)' or 'sizeif cod' instead of LENGTH (which
is defined as 4, which can be the right size, but that's not
guaranteed).
tam += LENGTH;
printf("1 - buffer = %s\n", buffer);

Here things get badly wrong: 'buffer' doesn't end in a '\0', so
it's not a string, so it can't be used as an argument to printf()
with "%s". And then, having an int copyied into a string doesn't
make it a string representation of that value. I guess you're
assuming that there's some automatic conversion happening but
that's not the case.
// inserir caracter delimitador //
memcpy(buffer+tam,&str,strlen(str));
tam += tcd;

'buffer' still has no '\0' at the end since you didn't copy that
from 'str'. Perhaps the fucntion you are looking for is strcpy()?
printf("2 - buffer = %s\n", buffer);

And thus this is the next point where things go wrong.
// inserir id da mensagem
memcpy(buffer+tam, &id, LENGTH);
tam += LENGTH;

Same problem as above, copying an integer to a char buffer doesn't
make any sense if you expect the char buffer to contain a represen-
tration of the int that would make sense as a string.
// inserir caracter delimitador //
memcpy(buffer+tam,&str,strlen(str));
tam += tcd;
// dividir string e inserir nome tabela
divide(argv,aux,"[");

Unfortunately, there's neither a declaration nor a definition
of divide() in what you posted so it's impossible to say if
the way you call it is correct (and if it does what you seem
to expect) or what effect of 'aux' (which you use in the
following) it has...
printf("passei o primeiro divide com aux[0] = %s\n\n", aux[0]);
printf("passei o primeiro divide com aux[1] = %s\n\n", aux[1]);
memset(argv,0,strlen(aux));
strcpy(argv,aux[1]);
memset(aux,0,strlen(argv));
divide(argv,aux,"]");

printf("passei o segundo divide com aux[0] = %s\n\n", aux[0]);
printf("passei o segundo divide com aux[1] = %s\n\n", aux[1]);
memcpy(buffer+tam,&aux[0],strlen(aux[0]));

Since 'buffer' as a fixed, final size and you don't have any idea
how long the string aux[0] points to is you could easily write
past the end of 'buffer' if the string is too long. Let's
just hope that your divide function at least works in a way
that the strings the elements of 'aux' point to have an '\0' at
the end, or there would be lots errors in the things to come...
tam += strlen(aux[0]);
printf("dpx do memcpy aux[0] = %s\n\n", aux[0]);
printf("dpx do memcpy aux[1] = %s\n\n", aux[1]);
// inserir caracter delimitador
memcpy(buffer+tam,&str,strlen(str));
tam += tcd;
printf("buffer = %s\n", buffer);

Since you still have no '\0' at the end of 'buffer' you still can't
use it as the argument to printf() with "%s".
// inserir numero e nome colunas
memset(argv,0,strlen(aux[1]));

How do you know for sure that the amount of memory 'argv' points
to is large enough to hold as many 0s as auy[1] has characters?
printf("antes do strcpy - aux[1] = %s\n\n", aux[1]);
strcpy(argv,aux[1]);
printf("argv[0] = %s\n", argv[0]);

Since what you defined as 'argv' is a char pointer, argv[0] is
a char, so you can't use it with "%s", you would need "%c".
memset(aux,0,strlen(argv));

'aux' is an array of pointers (as many as 'argv' has characters.
If you want to zero them all, then you would need

memset( aux, 0, strlen(argv) * sizeof *aux );

But then there's also the problem that 0 is not necessarily a NULL
pointer...
divide(argv,aux,",");
printf("passei o terceiro divide com aux[0] = %s\n\n", aux[0]);
printf("passei o terceiro divide com aux[1] = %s\n\n", aux[1]);
printf("passei o terceiro divide com aux[2] = %s\n\n", aux[2]);
printf("str(aux) = %d\n", strlen(aux));

Since 'aux' is not a string but an array of pointers calling strlen()
on it is simply wrong.
// inserir numero de colunas
for(h=0; aux[h]!=NULL;h++){
nRows++;
}

Let's hope either a NULL pointer is represented by all bits 0 or
your divide() function did the right thing...

memcpy(buffer+tam, nRows, LENGTH);
tam += LENGTH;

Again, copying the bits of an int into a char array may not be what
you want...
// inserir caracter delimitador
memcpy(buffer+tam,&str,strlen(str));
tam += tcd;
// inserir colunas
for(h=0; aux[h]!=NULL;h++){
memcpy(buffer+tam,&aux[h],strlen(aux[h]));
tam += tcd;
// inserir caracter delimitador
memcpy(buffer,&str,strlen(str));
tam += tcd;
}
return buffer;
}



#include "cli.h"
/* Funcao Main */
int main (int argc, char *argv[]) {
syntax();
/* Funcaoo que apresenta sintaxe do programa */

Calling a function before you have defined all variables is only
working with a C99 compiler.
int sock;
int broadcast = 1;
struct sockaddr_in server;
struct sockaddr_in cli;
int porto_servidor;
char buffer[BUFFSIZE];
char *tmp = buffer;
tmp = buffer;
char input[1024];
/* Limpa a estrutura */
bzero((char *)&server, sizeof(server));
bzero((char *)&cli, sizeof(cli));

Why not use memset()?
/* Limpar o buffer */
memset(buffer, 0, BUFFSIZE);
input[0] = menu(buffer);

Do you remember? menu() was defined to return a char, but in reality
it did return a pointer to a char buffer that you can't use here
anymore. So whatever is stored in 'input[0]' is rather likely to
be complete garbage. Luckily, you never use 'input' in the following.
But then what's the reason for this assignment?

Even worse, menu() doesn't accept any arguments, but you call it
with one. That should make your compiler complain loudly. And
'buffer' is never going to be set up to anything you seem to
expect, so using it in the following is a bad mistake.

I am not going to comment on the use of non-standard functions like
socket() etc. in the following, these are things better left for groups
like comp.unix.programmer, and you have enough problems with C anyway
that you should deal with first.
/* Criacao da socket */
if ((sock = socket(AF_INET,SOCK_DGRAM,0)) <0) {
perror("socket");
exit(1);
}
else {
printf("Cliente: socket criada \n");
}
/* Verificar ip */
if(strcmp(argv[1], "-s") == 0) {
printf("entrei n o verifica ip, estamos a funcionar com endereco ip
inserido\n");
inet_aton(argv[2], &server.sin_addr);
porto_servidor = atoi(argv[3]);
}

Checking that argc is at least 4 and that the elements of argv are
really strings of the form you expect would be the RIGHT thing to
do before using them.
else {//enviar em broadcast
printf("N?o foi fornecido o endere?o IP, a enviar em broadcast\n");
porto_servidor = atoi(argv[1]);
server.sin_addr.s_addr = htonl(INADDR_BROADCAST);
/* Activar broadcast na socket */
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast,
sizeof (int)) <0) {
perror("setsockopt");
exit(1);
}
}
/* verifica se a porta esta entre os valores pretendidos,
* visto o n?mero de grupo ser o 75, port vai variar entre
* 17500 e 17599 */

You already have been told that defining a function within another
function isn't allowed in C.
void checkPort(porto_servidor) {

You need to supply the type of the argument (probably 'int').
if(porto_servidor < 17500 || porto_servidor > 17599) {
printf("Cliente: O porto tem de ser entre 17500 e 17599!\n");
exit(-1);
}
}
/* Definir a familia de protocolo e porto */
server.sin_family = AF_INET;
server.sin_port = htons(porto_servidor);
/* Inicio da comunicacao com o servidor */
/* Enviar a mensagem para o servidor*/
if(sendto(sock, tmp, strlen(buffer), 0, (struct sockaddr *)&server,
sizeof(server)) <0) {

Let's assume 'buffer' was set up in menu() (which didn't hapen, see
above) via the call to criaRespCreate() (but only under certain circum-
stances, in most cases it would just contain garbage), and the way it's
potentially would be set up there does't make sure there's a '\0' at its
end, so using it as the argument to strlen() is not going to work.
perror("sendto\n");
exit(1);
}
else {
printf("Cliente: Mensagem enviada com sucesso\n");
}
while(1){
printf("entrei no while\n");
/* timeout de 10 segundos */
struct timeval timeout;
timeout.tv_sec = 10; //segundos
timeout.tv_usec = 0; //microsegundos
fd_set readfds;
int sel;
// char buf1[64];
/* limpar a fd_set */
FD_ZERO(&readfds);
/* colocar o file descriptor no fd_set */
FD_SET(sock, &readfds);
printf("vou ver agora o select\n");
if((sel = select(sock+1, &readfds, NULL, NULL, &timeout)) <0)
perror("select\n");
else if (sel == 0){
printf("Ocorreu um timeout! Nao foi recebida nenhuma mensagem em
10s.\n");
exit(0);
}
memset(buffer,0,BUFFSIZE);
printf("vou agora ler a resposta do servidor\n");
/* ler a resposta do servidor */
if(recvfrom(sock, buffer, BUFFSIZE, 0, NULL, NULL) < 0) {
printf("entrei no recv por ser < 0\n");
perror("recvfrom\n");
exit(1);
}
else {
printf("Cliente: Mensagem recebida com sucesso\n");
printf("buffer = %s\n", buffer);

What makes you sure that what you received from the server has a '\0'
character at the end, so you can use 'buffer' with "%s" in printf()?
exit(0);
}
}

You will never get here because of the infinite while loop above
without any 'break' that would you get you out of it (actually
the loop will only repeat as long as select() returns a negative
value, i.e. indicates an error happened, in all other cases you
just exit from the program).
/* fecho da socket */
close(sock);
}


#ifndef CLI_H
#define CLI_H
#include "projecto.h"
/* Definicao das funcoes definidas em cliente_aux.c */
void syntax();
char menu();
int criaRespCreate(int cod, int id, char *argv, char *buffer);


#ifndef PROJECTO_H
#define PROJECTO_H
#define BUFFSIZE 6804
#define LENGTH 4
/* Bibliotecas necessarias */
#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <sys/time.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>

I can only recommend that you start with something more simple, like
some functions for manipulating strings and non-string memory, testing
them carefully, in order to get a better idea what's the difference.
Try to figure out when you have to allocate memory and when not, how
to return memory from functions etc. before you embark on a complex
project involve both dealing with difficult user input, communication
with a server (and getting the protocol right) etc.

Regards, Jens
 
C

Chris Dollin

Pedro said:
I can do that inside main. What i can't do is with divide:

char divide(char search_string[], char *array[], char *delimiter)

and return the string you printed! Can this be done?

No. You /cannot/ return a string from a function with return type
`char`. Surely this is obvious?
 
P

Prasad

Pedro said:
>
>
> I can do that inside main. What i can't do is with divide:
>
> char divide(char search_string[], char *array[], char *delimiter)
>
> and return the string you printed! Can this be done?
>

As I understand, you want to create the array which holds the divided
tokens inside divide function and return it (instead of passing
char *array[] as argument). Please find below the code which does that.

Please note that this is my first answer to a question here.
So I would suggest you to wait, for any responses from the more
experienced members of c.l.c.

Also after posting my previous testcase, i have noticed few issues in
it. This version is better (I guess).


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

char **divide(char search_string[], char *delimiter){
int loop;
char **array = malloc(50 * sizeof(char *));
array[0]=strtok(search_string,delimiter);

if(array[0]==NULL)
{
printf("No test to search.\n");
exit(0);
}

for(loop=1;loop<50;loop++)
{
array[loop]=strtok(NULL,delimiter);

if(array[loop]==NULL)
return array;
}

return array;
}

int main(void) {
int i = 0 ;
char **arr;

char input[] ="this,is,comma,separated,string";

arr = divide(input, ",");

printf("Divided contents\n");
for(i = 0; i < 50; i++)
{
if(arr==NULL)
break;

printf("%s \n", arr);
}

free(arr);
return 0;
}

Hope this helps.
 
R

Richard Heathfield

Prasad said:

Please note that this is my first answer to a question here.
So I would suggest you to wait, for any responses from the more
experienced members of c.l.c.

It's a pretty good answer, actually. I only spotted two minor nits and one
major one:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char **divide(char search_string[], char *delimiter){

Make the second parameter const char *, to show the compiler that you aren't
planning on modifying the delimiter string. (You pass it a string literal,
so that allows the compiler to check that you don't modify it by mistake.)
int loop;
char **array = malloc(50 * sizeof(char *));

Better:
char **array = malloc(50 * sizeof *array);

Better still, replace the 50 with a #define or use a parameter.
array[0]=strtok(search_string,delimiter);

This is the important one. Here, you are relying on malloc not returning a
null pointer. Not a good idea. Check for it:

if(array != NULL)
{
array[0] = etc...

Also, add a check in main for this function returning NULL.

Apart from those few points, it was a fine answer.
 
K

Keith Thompson

Pedro Pinto said:
I can do that inside main. What i can't do is with divide:

char divide(char search_string[], char *array[], char *delimiter)

and return the string you printed! Can this be done?

As others have mentioned multiple times, your divide() function returns
a single char value. It cannot return a string.

In general, a function cannot directly return a string or array; it
has to be done indirectly somehow. There are several ways to do this.

The comp.lang.c FAQ is at <http://www.c-faq.com/>. Read section 6,
"Arrays and Pointers".
 
P

Prasad

Richard said:
It's a pretty good answer, actually. I only spotted two minor nits and one
major one:
<snipped>

Seems I did not think about proper error checks and good practices,
before posting code (which I should have done).

Thank you for pointing them out.
 
R

Richard Heathfield

Prasad said:
Seems I did not think about proper error checks and good practices,
before posting code (which I should have done).

You're not the first to make that mistake - and neither was I!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top