CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 3 FirstFirst 123 LastLast
Results 16 to 30 of 33
  1. #16
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Help with C simple loop.

    Another important point if this is really a 'C' program:

    You should post a full program, including headers that you included. The reason is that a C program will and can behave differently if headers are missing. If you post code with no headers (as you did in your initial post), then there is no telling how the program will behave.

    Regards,

    Paul McKenzie

  2. #17
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Help with C simple loop.

    Quote Originally Posted by willn View Post
    OK, I am sorry, I see what you are saying. I am in the process of debugging, but since I am in windows, I cannot find a good debugger that will work well. I have visual studio, but it does not include all the classes that I am using in my program and from what I read it is not recommended to add them. Any suggestions on this?
    Visual Studio has one of, if not, the most powerful debuggers out there. People debug all sorts of programs, from student programs to full-fledged systems of all types. So I don't know what you mean by "all the classes you're using".

    I will cautiously say that you're not using the Visual Studio debugger correctly.

    Regards,

    Paul McKenzie

  3. #18
    Join Date
    Mar 2013
    Posts
    13

    Re: Help with C simple loop.

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include  <netdb.h>
    
    
    	//Function to prompt user if they don't enter all necessary switches
    void Usage(char *progname)
    {
        fprintf(stderr,"Usage: %s -p [protocol] -e [port_num]\n", progname);
        exit(1);
    }
    
    
    	
    	  
     const char * getServer(char *svrList)
    	{
    	
    
    	char *srList;
    
    	srList = strtok(svrList, " ," );
    	printf("Contents of srList b4 loop: %s\n", srList);
    	printf("Server List: %s\n", svrList);
    		while(srList !=NULL)
    			{
    			
    			printf("result is \"%s\"\n", srList);
    			char pComm[512];
    			//memset(pComm, '\0', sizeof(512));
    			sprintf(pComm, "ping -c 1 %s > /dev/null", srList);
    			
    		if((system (pComm))==0)
    			{
    			printf("result is \"%s\"\n", srList);
    			return ( srList );
    			}
    			else
    			{
    			printf("Hitting else loop\n");
    			srList = strtok(NULL, " ," );
    			printf("Contents of srList in else: %s\n", srList);
    			}
    			
    			
    			}
    
    	return "0";
    	}
    	
    	
    	
    int main(int argc, char *argv[])
    {
    	//Declare global variables
        char sendBuff[128];
        const char *server_name= NULL;
        unsigned short port;
        int value, loopflag = 0;
        int i, loopcount, maxloop=-1;
        unsigned int addr;
        int socket_type;
        struct sockaddr_in server;
        struct hostent *hp;
        int connSocket;
    	char svrList[] = "129.120.151.254, 129.120.151.95, 129.120.151.96, 129.120.151.97";
     
    	 //Check arguments
        if (argc >1)
           {
            for(i=1; i<argc; i++)
            {	
    			// User can enter - or / as the switch
                if ((argv[i][0] == '-') || (argv[i][0] == '/'))
               {	
    				// Change lowercase, so switches aren't case-sensative
                    switch(tolower(argv[i][1]))
                     {
                        case 'p':
                            if (!strcasecmp(argv[i+1], "TCP"))
                                socket_type = SOCK_STREAM;
                            else if (!strcasecmp(argv[i+1], "UDP"))
                                socket_type = SOCK_DGRAM;
                            else
                                Usage(argv[0]);
                            i++;
                            break;
                       case 'n':
                            server_name = argv[++i];
                            break;
                        case 'e':
                            port = atoi(argv[++i]);
                            break;
                        default:
                            Usage(argv[0]);
                            break;
                    }
                }
                else
                    Usage(argv[0]);
            }
        }
     
    	// If port or socket type are missing, show user help command line
        if (port == 0 || socket_type == 0)
           {
            Usage(argv[0]);
        }
     
     
    
     
     
     while(1)
        {
    	printf("Checking which server to use.\n");
    	if (getServer(svrList) != "0")
    	{
    	server_name= getServer(svrList);
    	printf("The server is %s\n",server_name);
    	//Should we lookup hostname or just use IP
        if (isalpha(server_name[0]))
        {   // server address is a name
            hp = gethostbyname(server_name);
        }
        else
        { // Convert to internet useable address
            addr = inet_addr(server_name);
            hp = gethostbyaddr((char *)&addr, 4, AF_INET);
        }
        if (hp == NULL )
        {
            printf("Client: Cannot resolve address %s!", server_name);
            
            exit(1);
        }
        else
           printf("Client: Hostname setup successfully!\n");
    			
    	
    		
    		
    		
    		
    
        
    	// Copy the resolved information into the sockaddr_in structure
        memset(&server, 0, sizeof(server));
        memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
        server.sin_family = hp->h_addrtype;
        server.sin_port = htons(port);
     
        connSocket = socket(AF_INET, socket_type, 0); /* Open a socket */
        if (connSocket <0 )
        {
            printf("Client: Error Opening socket!\n");
            return -1;
        }
        else
           printf("Client: Socket established!\n");
     
       // printf("Client: Client connecting to: %c.\n", server_name);
      // addr = inet_addr(server_name);
      // printf("%d\n", addr);
        if (connect(connSocket, (struct sockaddr*)&server, sizeof(server)) < 0)
        {
            printf("Client: Can't connect to server!\n");
            return -1;
        }
        else
           printf("Client: Connected to server!\n");
     
        // Gather input from user to send to server
       
    	   	printf("Please enter a floating point number: ");
    		float number1;
    		fscanf(stdin,"%f", &number1);
    
    		printf("Please enter a mathematical operator (+,-,*,/): ");
    		char mathOperator;
    		fscanf(stdin,"%c", &mathOperator);
    
    		fflush(stdin);
    		mathOperator = (char)fgetc(stdin);
    
    		printf("Please enter a floating point number: ");
    		float number2;
    		fscanf(stdin,"%f", &number2);
    	   
    	   //Store input into buffer
    	   sprintf(sendBuff, "%f,%f,%c", number1,number2,mathOperator);
           value = send(connSocket, sendBuff, sizeof(sendBuff), 0);
    
            printf("Client: Sending data complete!\n");
            //Tell user was data was sent to server
    		printf("Client: Sent data \"%s\"\n", sendBuff);
    		//Receive the data back from the server
    		value = recv(connSocket, sendBuff, sizeof(sendBuff), 0);
    		printf("Client: Received data from the server!\n");
    		fflush(stdin);
    		//If the socket goes down, kill the connection
            if (value == 0)
           {
                printf("Client: Server closed connection.\n");
               close(connSocket);
                return -1;
            }
    		
    		//Inform user what was received and terminate the connection
            printf("Client: Received %d bytes, data \"%s\" from server.\n", value, sendBuff);
                printf("Client: Terminating connection...\n");
    			//break;
    			//close(connSocket);
    		/*		char cont;
    		printf("Do you want to continue? [Y/N]");
    			
    			fscanf(stdin,"%s", &cont);
    			printf("%s\n", &cont);
    		if (cont = "Y" || "y")
    		{
    			continue;
    		}
    		else
    		{
    			break;
    			break;
    		}		*/
    			
    }
    		else
    		{
    		printf("There are no available servers!\n");
    		break;
    		}
        
       
     }
    return 0;
    }
    This is the full code for the client side. It works except for the getservers function. May not be the best as far as structure, but I just need to do certain things. The visual studio was giving me cannot open source file for the following:
    #include <socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>

    I am assuming this means that these are classes that are used mainly in Linux and not windows.

  4. #19
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Help with C simple loop.

    Quote Originally Posted by willn View Post
    I am assuming this means that these are classes that are used mainly in Linux and not windows.
    Most of those headers are non-standard, more precisely the ones that deal with sockets. If you want to use sockets on both Windows and Linux, then you need to get a cross-platform solution, otherwise you have to write two different sets of code for Linux and Windows.

    Secondly, sockets just confuse the issue. The problem is that you cannot take a string that is separated by commas, and produce each field -- in other words, a CSV parser. It doesn't matter what the data is going to be used for. If you wrote a simple function to do this first, then you can use any compiler to test the code since no sockets are involved. Instead, you're trying to learn basic 'C' coding within a larger program, and it's all of that unnecessary noise that this socket code is causing that is confusing the issue.
    Code:
    #include <stdio.h>
    
    const char * getServer(char *svrList)
    {
        char *srList;
        srList = strtok(svrList, " ," );
        while(srList !=NULL)
        {
    	char pComm[512];
    	sprintf(pComm, "ping -c 1 %s > /dev/null", srList);
            if ((system (pComm))==0)
                return srList;
    	else
                srList = strtok(NULL, " ," );
        }
        return "0";
    }
    
    int main()
    {
      // write a test here
    }
    This is what you should be doing to test your code.

    The first thing to realize is that strtok() messes up your original char array by placing NULLs in the data. Do you want that to happen? If not, then you need to copy the data to a temporary array and use that instead. The other thing is that strtok() can only be used in a "serial" way, i.e. you can't have two or more places where strtok() is being called interchangeably with different strings, where one strtok() is being called during the processing of the other strtok(). This is all due to strtok() using static variables.

    http://www.cplusplus.com/reference/c...tok/?kw=strtok

    Also, your code still doesn't suggest that it is really C that you're using. I still see variables being declared after executable statements, like this:
    Code:
    printf("Please enter a floating point number: ");
    float number2;
    If you tried to compile this with Visual Studio as a 'C' module, it will give you an error stating that you can't declare a float at that point in the code. Visual C++ follows the rules of ANSI 'C', and if you turned on the ANSI 'C' switch for gcc (that is if this is really and truly a 'C' program), you will get the same error using gcc. The only way to not get an error for this construct is if the code is C++, and so far, you haven't confirmed what language you're really compiling for.

    If it is really C++, this job becomes much easier and safer.

    Finally, you need to properly indent your code. It is almost impossible to follow with the indentation all over the place like that.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; April 9th, 2013 at 04:47 AM.

  5. #20
    Join Date
    Mar 2013
    Posts
    13

    Re: Help with C simple loop.

    So, the function is working like I want it to. When I run it by itself or output the result of the function to a printf, it has the correct return value. Where the problem comes in is when I call the function a second time. It seems like after this, something is different and it doesn't run the same the second time. I am referring to the code snippet that I added in my main program:

    Code:
    while(1)
    	{
    	printf("Checking which server to use.\n");
    	printf("Function return is: %s:\n", getServer(svrList));
    	if (getServer(svrList) != "0")
    	{
    Then the output is this:

    Code:
    Checking which server to use.
    Function return is: 129.120.151.95:
    There are no available servers!
    Which if you look at the main program, it is returning the "0" value on the second time the function is run, but the correct value the first time. Am I missing something in the way it is running the function?
    Last edited by willn; April 9th, 2013 at 09:16 AM.

  6. #21
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: Help with C simple loop.

    I haven't read the thread, but this is wonky.
    return "0";

    More than likely you mean
    return 0;
    or even better, return NULL; (same thing, just more clear)

    When you test it here,
    if (getServer(svrList) != "0")
    you're actually comparing pointers, not the value they point to, so they'll never be equal. Return 0 and test for 0, not "0".

  7. #22
    Join Date
    Mar 2013
    Posts
    13

    Re: Help with C simple loop.

    Quote Originally Posted by GCDEF View Post
    I haven't read the thread, but this is wonky.
    return "0";

    More than likely you mean
    return 0;
    or even better, return NULL; (same thing, just more clear)

    When you test it here,
    if (getServer(svrList) != "0")
    you're actually comparing pointers, not the value they point to, so they'll never be equal. Return 0 and test for 0, not "0".
    I changed the return to a NULL in the function and that line 'if (getServer(svrList) != "0")' to 'if (getServer(svrList) != NULL)' and it made no difference on the output. I do thank you for helping me with a better way of returning from the function. That helps me write a little better code. I know I am completely green right now.

  8. #23
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Help with C simple loop.

    Code:
    if (getServer(svrList) != "0")
    You can't compare c-type NULL terminated strings like this. To compare these type of strings, you use

    Code:
    if (!strcmp(getServer(srvList) , "0"))
    A better way as GCDEF said would be for getServer to return NULL instead of returning "0".

    You also need to note, as said in previous posts, that strtok alters the contents of the string on which it is used. So if you call it more than once on the same string it will produce different answers! As said previously, copy the string first before using strtok. This is why calling getSever with the same argument more than once produces different results!
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  9. #24
    Join Date
    Mar 2013
    Posts
    13

    Re: Help with C simple loop.

    Quote Originally Posted by Paul McKenzie View Post
    The first thing to realize is that strtok() messes up your original char array by placing NULLs in the data. Do you want that to happen? If not, then you need to copy the data to a temporary array and use that instead. The other thing is that strtok() can only be used in a "serial" way, i.e. you can't have two or more places where strtok() is being called interchangeably with different strings, where one strtok() is being called during the processing of the other strtok(). This is all due to strtok() using static variables.

    http://www.cplusplus.com/reference/c...tok/?kw=strtok

    Also, your code still doesn't suggest that it is really C that you're using. I still see variables being declared after executable statements, like this:
    Code:
    printf("Please enter a floating point number: ");
    float number2;
    If you tried to compile this with Visual Studio as a 'C' module, it will give you an error stating that you can't declare a float at that point in the code. Visual C++ follows the rules of ANSI 'C', and if you turned on the ANSI 'C' switch for gcc (that is if this is really and truly a 'C' program), you will get the same error using gcc. The only way to not get an error for this construct is if the code is C++, and so far, you haven't confirmed what language you're really compiling for.

    If it is really C++, this job becomes much easier and safer.

    Finally, you need to properly indent your code. It is almost impossible to follow with the indentation all over the place like that.

    Regards,

    Paul McKenzie

    What can I use instead of strtok() because I will need to call this function multiple times to make sure that the server is still up and if not, move to the next one in the list, so dealing with a function that modifies my array is not good? I have verified in codelite that the string is being modified (not that I didn't believe you guys, just cool to see it for myself in the debugger). Also, as far as C versus C++, the requirement for this program is C, so I am kinda stuck on that one. I am still not sure why the code compiles with the way it is structured, but as long as it works, I can clean it up later. Just wanted to say I really appreciate the responses I have gotten on this, you guys are freakin awesome!!

  10. #25
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Help with C simple loop.

    As said previously, in getServer copy the string first before using strtok and then use strtok on the copied string
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  11. #26
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Help with C simple loop.

    Quote Originally Posted by willn View Post
    What can I use instead of strtok() because I will need to call this function multiple times to make sure that the server is still up and if not, move to the next one in the list, so dealing with a function that modifies my array is not good?
    There is no out-of-the-box 'C' function to parse without altering the string. You need to write it yourself or get one off the Net somewhere.
    Also, as far as C versus C++, the requirement for this program is C, so I am kinda stuck on that one.
    The problem is that what you wrote violates C rules, so it isn't really a C program.
    I am still not sure why the code compiles with the way it is structured,
    Please check all of your gcc command-line options. One of them is more than likely the ANSI switch that turns on ANSI C compilation. Once you compile with that option, you will see that the code I pointed out will fail to compile. I'm sure gcc has this option, as there still is a lot of 'C' code out there that requires ANSI 'C' compatibility without any extensions or C99 support.

    Regards,

    Paul McKenzie

  12. #27
    Join Date
    Mar 2013
    Posts
    13

    Re: Help with C simple loop.

    I think I finally got it!!! Thanks to you guys' help! The answer was the strcpy() function. One other question though, why can't I use a dynamic array with strcpy()? In the final code, I get an error if I use char *temp; but it works with char[512] as a static array. Couldn't find an explanation for that one. The explanation of strcpy says to prevent overflows, the size of destination has to be long enough to contain the same C string as source, but that doesn't explain why a dynamic array wouldn't work, because I would assume it should allocate it accordingly. That may be my wondering mind thinking without knowing how it works.... Also, do I have to have the exact array size as the source also or is it bad practice to add a little bit for "cushion"?

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    
     const char * getServer(char *svrList)
    {
    	char temp[512];
        strcpy (temp,svrList);
    	char *srList = NULL;
    	srList = strtok(temp, " ," );
    		while(srList !=NULL)
    			{
    			printf("result is \"%s\"\n", srList);
    			char pComm[512];
    			sprintf(pComm, "ping.exe -n 1 %s", srList);
    			
    		if((system (pComm))==0)
    			return srList;
    				else
    			srList = strtok(NULL, " ," );
    			continue;
    			}
    	
    	//return "0";
    }
    	
    	
    int main(int argc, char *argv[])
    {
    	//Declare global variables
        //char sendBuff[128];
        const char *server_name= NULL;
       // unsigned short port;
        //int value, loopflag = 0;
        //int i, loopcount, maxloop=-1;
        //unsigned int addr;
        //int socket_type;
        //struct sockaddr_in server;
        //struct hostent *hp;
        //int connSocket;
    	char svrList[] = "129.120.151.254, 129.120.151.95, 129.120.151.96, 129.120.151.97";
     
    
     
    
     
     
     while(1)
        {
    	printf("Checking which server to use.\n");
    	if (getServer(svrList) != "0")
    	{
    	server_name= getServer(svrList);
    	printf("The server is %s\n",server_name);
    	//Should we lookup hostname or just use IP
    	break;
    	}
    		else
    		{
    		printf("There are no available servers!\n");
    		break;
    		}
        
       
    	}
    	return 0;
    }
    Last edited by willn; April 9th, 2013 at 12:00 PM.

  13. #28
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: Help with C simple loop.

    Why is return commented out in getServer?

    char* temp is an uninitialized pointer to unallocated memory.

  14. #29
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Help with C simple loop.

    Quote Originally Posted by willn View Post
    One other question though, why can't I use a dynamic array with strcpy()?
    There is no such thing as a dynamic array in 'C'. All arrays are fixed in size.
    In the final code, I get an error if I use char *temp; but it works with char[512] as a static array.
    There is a big difference between a pointer and an array. A pointer must point somewhere valid before you read or write to where it's pointing. Did you do that?
    The explanation of strcpy says to prevent overflows, the size of destination has to be long enough to contain the same C string as source, but that doesn't explain why a dynamic array wouldn't work, because I would assume it should allocate it accordingly.
    C has none of these "automatic" facilities to resize strings or arrays. Arrays are fixed in size. The closest you can get is by using the heap (malloc(), calloc(), realloc(), etc.). However, once you go down that route, then you better know what you're doing.

    That's why I asked whether you are really compiling a C++ module (that looks like it's C). With C++, you do have the facilities to resize strings and arrays using the various container and string classes.
    Also, do I have to have the exact array size as the source also or is it bad practice to add a little bit for "cushion"?
    If you overflow the boundaries of the array, the result is undefined behaviour. Even if you're off by one byte, the program is flawed.

    So yes, you should leave yourself more room, but that is not the greatest of solutions. The best solution would be to write a library of dynamic string routines for 'C', and use them instead of raw char* pointers and arrays. However, that is an undertaking for someone who knows 'C' fairly well and knows what to look out for.

    Regards,

    Paul McKenzie

  15. #30
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Help with C simple loop.

    As to your code:
    Code:
     const char * getServer(char *svrList)
    {
        char temp[512];
        strcpy (temp,svrList);
    What if svrList points to a string that is more than 512 bytes? What if I pass a NULL to getServer()? Your code is now broken.
    Code:
    	//return "0";
    What is returned if the code falls through to this line that you commented out? The return value is now undefined.

    Regards,

    Paul McKenzie

Page 2 of 3 FirstFirst 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured