-1

I'm new to C programming and have been reading about it here.

I found out that int data types can be used to declare variables for a number/integer with value range between -32,768 to 32,767 or -2,147,483,648 to 2,147,483,647.

While char data types can be used to store -128 to 127 or 0 to 255 value.

What about an IP Address? I've tried int however only first octet of the IP is recognized.

It also doesn't work well with char.

Codes

C:\Codes>more input_output.c
#include <stdio.h>

int main()
{
        int a;
        int b;
        char c;

        printf("\n1. Enter a number : ");
        scanf("%d",&a);
        printf("You've entered %d\n",a);

        printf("\n2. Enter an IP Address : ");
        scanf("%d",&b);
        printf("You've entered %d\n",b);

        printf("\n3. Enter an IP Address : ");
        scanf("%c",&c);
        printf("You've entered %d\n",c);

        return 0;
}

C:\Codes>

Compiling

C:\Codes>gcc input_output.c -o input_output

C:\Codes>

Final Output

C:\Codes>input_output.exe

1. Enter a number : 5
You've entered 5

2. Enter an IP Address : 8.8.8.8
You've entered 8

3. Enter an IP Address : You've entered 46

C:\Codes>
  • 1
    char* might help – StaticBeagle Mar 10 '18 at 13:35
  • 1
    Store as a string (`char *`) or as an array of 4 bytes (`uint_8 ip[4];`). If you want to store it as 4 bytes, you'd still need to read it in as a string and parse it, or parse it while you are reading it. If you try to read it as an `int`, then `scanf` stops at the first point (`.`) since that's not part of a valid integer. – lurker Mar 10 '18 at 13:38
  • 1
    @lurker Have you missed the dots(.) ? The array must accomodate them too. – machine_1 Mar 10 '18 at 13:41
  • 1
    @machine_1 no, the array does not need to accommodate the dots since the dots are an understood part of IP address formatting. Any time it would be printed, you would print the dots in between. Or if the IP address needed to be passed as a string, it could be formatted with the dots inserted at that time. Nothing wrong with that at all. – lurker Mar 10 '18 at 13:42
  • 1
    should we close this as duplicate of https://stackoverflow.com/questions/19558013/ip-address-input-in-c ? not sure. – Jean-François Fabre Mar 10 '18 at 13:43
  • 2
    @Jean-FrançoisFabre Good question. I find that particular q&a maybe just shy of being a good and complete answer for this particular question since it's fairly narrow. This Op has asked how to store an IP address and I think there are a couple of ways. I would definitely not do it as shown in that other question where each octet is a discrete named `char` variable (I don't like that they're discrete instead of an array, and they are signed `char`). That's just my opinion. – lurker Mar 10 '18 at 13:47
  • @Jean-FrançoisFabre, I tried that code ... it's not working as expected. I also get a different output `C:\Codes>ip_address_test.exe 8.8.8.8 0 0 0 8 C:\Codes>` And this error when compiling it `unknown conversion type character 'h' in format` Full codes and error here ... https://pastebin.com/0qqwY7uR –  Mar 11 '18 at 01:42

3 Answers3

1

The IP address is truly 32-bit integer represented typically in a string form like 192.0.2.33. It is kept in the structure struct sockaddr_in.

The best approach is to use a specialized function inet_pton to convert your string to a IP address and get it back via inet_ntop

#include <stdio.h>

#ifdef _WIN32
 #include <winsock2.h>
#else
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <netinet/ip.h>
#endif

int main (void) 
{
   int parts[4];

   struct sockaddr_in sa;
   char str[64]; 

   // naive approach:
   printf ("\n Enter 4 IP Address parts : \n");

   scanf ("%d", &parts[3]);
   scanf ("%d", &parts[2]);
   scanf ("%d", &parts[1]);
   scanf ("%d", &parts[0]);

   printf ("%d.%d.%d.%d\n", parts[3], parts[2], parts[1], parts[0]);

   // The best:
   printf ("\n Enter IP Address in a format: 192.0.2.33 :\n");
   scanf ("%s", str);

   // store this IP address in sa:
   inet_pton(AF_INET, str, &(sa.sin_addr));

   // now get it back and print it
   inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN);

   printf("%s\n", str); 

   return 0;
} 

Output:

 Enter 4 IP Address parts :                                                                                                                   
190                                                                                                                                           
0                                                                                                                                             
2                                                                                                                                             
33                                                                                                                                            
190.0.2.33                                                                                                                                    

 Enter IP Address in a format: 192.0.2.33 :                                                                                                   
190.0.5.22                                                                                                                                    
190.0.5.22      
sg7
  • 6,108
  • 2
  • 32
  • 40
  • Thanks @sg7. I guess your code is in Linux. Mine is in Windows. I'm getting the following errors when compiling the code. `fatal error: sys/socket.h: No such file or directory` Found a solution here https://stackoverflow.com/questions/1517762/sockets-in-mingw and replaced `#include ` with `#include ` However, I can't find a replacement for `fatal error: netinet/in.h: No such file or directory` –  Mar 10 '18 at 15:04
  • 1
    @Sabrina OK! You are on Windows. Remove this include file: ``. `#include ` should be enough. At link-time, remember to include `ws2_32.lib` to provide linkage to the required system `DLL` – sg7 Mar 10 '18 at 15:15
  • There is also error for `netinet/ip.h` `fatal error: netinet/ip.h: No such file or directory` However, when I remove this, I'm getting another error Due to limited space in comment, I've paste the error in link below. https://pastebin.com/QCsyWBh6 –  Mar 10 '18 at 15:20
  • 1
    @Sabrina I have updated the program. You you can remove `#include ` and replace `INET_ADDRSTRLEN` with `64`. I hope it helps. – sg7 Mar 10 '18 at 15:31
  • Thanks @sg7, however I'm still not able to compile it. Here is another error with the new code. `warning: implicit declaration of function 'inet_pton' [-Wimplicit-function-declaration] inet_pton(AF_INET, str, &(sa.sin_addr));` `undefined reference to `inet_pton'` `undefined reference to `inet_ntop'` Full code and error here ... https://pastebin.com/Y0rxhpup –  Mar 11 '18 at 01:23
0

scanf("%d",&b); stops when a number has been scanned (stops/doesn't read the following dot char), but you entered 8.8.8.8

Next time you're scanning a char you're getting the code for . (ASCII for dot is 46)

A proper way to read an IP address is described in this Q&A: IP address input in C

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
0

Have you learnt about strings? These are basically lots of chars in a row. You can write something like this in C.

const char* ip = "127.0.0.1"

or read it using scanf

char ip[256];
scanf("%s", ip);

The line char ip[256] defines an array of char. Then next line scanf("%s", ip); reads whatever is entered from the keyboard into the array of char.

Just because an ip address has numbers in it, it doesn't mean you should use ints to store. An ip address is more like a phone number. Arithmetic doesn't make sense on them.

sashang
  • 11,704
  • 6
  • 44
  • 58