-1

I know my error is within the arrangement of the {} but can't tell where. I've been trying to fix it for an hour. I'm not sure if there's something wrong with my code. Also, I'm new in coding so please baby steps if you can.

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

int main (void)
{
    int ch, dots, bytes, temp;
    dots = bytes = temp = 0;
    printf ("Enter IP address (x.x.x.x): ");
    while ((ch = getchar ()) != '\n' && ch != EOF) {
        if (ch < '0' || ch != EOF) {
            if (ch == '.') {
                dots++;
            }
            if (temp != -1) {
                if (temp > 255) {
                    printf
                        ("Error: The value of each byte should be in [0,255]\n");
                    return 0;
                }

                bytes++;
                temp = -1;      //The value -1 means current address byte is checked
            } else {
                printf ("Error: Acceptable chars are only digits and dots\n");
                return 0;
            }
        } else {
            if (temp == -1)
                temp = 0;       //Make it 0, to start checking the next address byte
            temp = 10 * temp + (ch - '0');
        }
        if (temp != -1)         //Check the value of the last address byte
        {
            if (temp > 255) {
                printf
                    ("Error: The value of each byte should be in [0, 255]\n");
                return 0;
            }
            bytes++;
        }
    }
    if (dots != 3 || bytes != 4) {
        printf ("Error: The IP format should be x.x.x.x\n");
    }
    return 0;
}
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • 1
    Indentation would help readability. – tkausl May 10 '18 at 05:33
  • Have you checked [Determine if a string is a valid IP address in C](https://stackoverflow.com/questions/791982/determine-if-a-string-is-a-valid-ip-address-in-c) also always look at the **Related** links at the right side of the page `:)` – David C. Rankin May 10 '18 at 05:35
  • `if (ch < '0' || ch != EOF)` -> `if (ch < '0' || '9' < ch)` – David C. Rankin May 10 '18 at 05:44
  • 1
    Compile with all warnings and debug info: `gcc -Wall -Wextra -g` with [GCC](http://gcc.gnu.org/). Improve your code to get no warnings at all. Then **use the debugger** (e.g. [`gdb`](https://sourceware.org/gdb/onlinedocs/gdb/)) to understand the behavior of your program. Improve it. Repeat till satisfied. Your *do-my-homework* question is **off-topic** here – Basile Starynkevitch May 10 '18 at 05:47
  • @BasileStarynkevitch dude is not a hw, I'm just practicing. I have lit spent an hour trying to find the error. Because if I inpute 1.2.3.4 it outputs Error: Acceptable chars are only digits and dots. So it's def something wrong with the {} I just cant figure it out. If you don't want to help, then just don't comment – Nor Escartin May 10 '18 at 05:52
  • So **use the debugger** to find your bug. StackOverflow is *not* a *fix-my-code* service, and being able to debug your own program is a core skill to have for software developers. Sometimes you will spend (like most of us) several weeks of work to find a bug. Only one hour of work is not enough. – Basile Starynkevitch May 10 '18 at 05:53
  • @BasileStarynkevitch I don't know how to do that. And nobody is going to fix my code. The code is already made. – Nor Escartin May 10 '18 at 05:55
  • What compiler and debugger is on your system is known to you (not to us) since we don't know what is on your computer and what operating system and compiler you are using. But *you* need to find out what it is, and *you* need to spend hours in learning to use the debugger which is available on your computer. – Basile Starynkevitch May 10 '18 at 05:56
  • GCC on a windows @BasileStarynkevitch – Nor Escartin May 10 '18 at 05:58
  • That should go into your question. If you are using [GCC](http://gcc.gnu.org/), compile with `gcc -Wall -Wextra -g`. Then you probably have `gdb` on your system. So read the [documentation of `gdb`](https://sourceware.org/gdb/onlinedocs/gdb/). Understand what goes wrong in your program (using `gdb`). Then improve it. And your question should have an [MCVE] with a example of run. – Basile Starynkevitch May 10 '18 at 06:00
  • BTW, you might read a line with [fgets](http://en.cppreference.com/w/c/io/fgets) and [parse](https://en.wikipedia.org/wiki/Parsing) it, perhaps using [sscanf](http://en.cppreference.com/w/c/io/fscanf) or [strtoul](http://en.cppreference.com/w/c/string/byte/strtoul) – Basile Starynkevitch May 10 '18 at 06:09

1 Answers1

1

Your code actually compiles cleanly, you have an error in logic. You will need to spend a bit of time with a debugger, See How to debug small programs -- OR -- you can make life quite a bit easier on yourself...

Your task is not a difficult one, if you just approach it in a different way. You are only validating whether there are periods '.' between 4 octets of 3 numbers each. (an IPv4 address affectionately referred to as a dotted-quad). If these are the only tests you are making, you can simply let sscanf do it for you. You then only need check that the values are between 0 and 255.

(you can also grab the 1st character after the last quad and validate it is the '\n' character to insure there are no extraneous characters tacked onto the end of the IP)

This greatly simplifies the logic (and the amount of time you will spend with the debugger). Implementing the above logic, you could whittle your code down to the following and still use a proper fgets followed by sscanf, e.g.

#include <stdio.h>

#define QUAD  4     /* if you need a constant define one (or more) */
#define MAXC 32     /* don't skimp on buffer size */

int main (void)
{
    char buf[MAXC] = "",    /* buf to hold IP read by fgets */
        nl = 0;             /* charater to validate newline following IP */
    int ip[QUAD] = {0};     /* array to store each quad for testing */

    printf ("Enter IP address (x.x.x.x): ");
    if (fgets (buf, MAXC, stdin)) {         /* read IP into buf */
        if (sscanf (buf, "%d.%d.%d.%d%c",   /* parse with sscanf */
                    &ip[0], &ip[1], &ip[2], &ip[3], &nl) != 5) {
            fprintf (stderr, "error: invalid IPv4 format.\n");
            return 1;
        }
        for (int i = 0; i < QUAD; i++)      /* loop over each quad */
            if (ip[i] < 0 || 255 < ip[i]) { /* validate 0-255 */
                fprintf (stderr, "error: invalid quad '%d'.\n", ip[i]);
                return 1;
            }
    }

    if (nl != '\n') {   /* validate following char is '\n' */
        fprintf (stderr, "error: additional characters following IP.\n");
        return 1;
    }

    printf ("valid IP: %s", buf);   /* all tests passed - good address */

    return 0;
}

Example Use/Output

$ ./bin/chkip
Enter IP address (x.x.x.x): 12.23.34.45
valid IP: 12.23.34.45

$ ./bin/chkip
Enter IP address (x.x.x.x): 12.23.34.45a
error: additional characters following IP.

$ ./bin/chkip
Enter IP address (x.x.x.x): 12.23.34.450
error: invalid quad '450'.

$ ./bin/chkip
Enter IP address (x.x.x.x): 12.32.foo
error: invalid IPv4 format.

Look things over and let me know if you have further questions. If you must use getchar(), it is doable, but I'll need to find some aspirin before wading through each bit of your loop logic with you. Let me know if that is the case.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85