-2

i'm extremely beginner in terms of coding. So, i'm asking my friends to create Floyd Warshall Algorithm in C++ for my thesis. Here is the code :

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define MAX 30

void floyd(int);
int w[MAX][MAX], d[MAX][MAX][MAX];

void main()
{
int i,j,v;
clrscr();
printf("enter the no. of vertices\n");
scanf("%d",&v);
printf("enter the weights \n");

  for(i=1;i<=v;i++)
  {
   for(j=1;j<=v;j++)
    scanf("%d",&w[i][j]);
   }

 floyd(v);
 getch();
 }//end of main

 void floyd(int v)
 {
 int k, i,j;

  k=0;
for(i=1;i<=v;i++)
{
 for(j=1;j<=v;j++)
  d[k][i][j]=w[i][j];
 }

      for(k=1;k<=v;k++)
 {
       for(i=1;i<=v;i++)
{
  for(j=1;j<=v;j++)
   d[k][i][j]=min(d[k-1][i][j], d[k-1][i][k]+ d[k-1][k][j]);
  }
}

 //displayin matrix

 for(k=0;k<=v;k++)
 {
 printf(" k=%d \n",k);
   for(i=1;i<=v;i++)
   {
    printf("\n");
     for(j=1;j<=v;j++)
     printf("\t %d",d[k][i][j]);
    }
    printf("\n \n ");
  }
}

Since, most of my data are using decimal numbers instead of integer, the program doesn't allow me to input it. What changes should i make ? Thanks.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • 3
    First thing to change -- use 0 based indices, not 1 based indices. – R Sahu May 29 '18 at 03:34
  • For starters, you'll never receive a decimal from an integer value, no matter what other integer you're trying to deduct from it. Replace your `floyd` arguments to take a `float` or `double`, and in your main define instead `float i,j,v`. Also, in your `floyd` function, use `float k,i,j`.. Your looping logic should be alright, it seems like. But I agree with @RSahu; you should use `0` as your array starting index; don't initialize with 1, it's like saying a value exists when it shouldn't. – James Whyte May 29 '18 at 03:37
  • 1
    By *decimal* numbers, I assume you meant numbers that are not integral numbers. In that case, you can use `float` or `double` as type instead of `int`. You will need to change format specifer to `%f` or `%lf`, respectively, too. – R Sahu May 29 '18 at 03:37
  • 3
    Unfortunately, "I got this code from somewhere, I don't know how it works, please help me modify it." isn't a good question. This site is for helping people learn, not doing stuff for people. You should actually learn how to code from a [good book](https://stackoverflow.com/q/388242/9254539) so you can do things yourself. Your friend's code contains a bunch of very bad practices by the way, including the 1-indexing, C I/O for no reason, and using macros for constants. You should also improve the indenting to make the code much easier to read. – eesiraed May 29 '18 at 03:41
  • `` is not a standard header. `void main` is wrong; `main` must return `int`. Don't use global variables for no reason. If you do use global variables, don't give them one-letter names. – melpomene May 29 '18 at 03:48
  • Don't use `scanf` for user input. If you do use `scanf`, always check its return value. – melpomene May 29 '18 at 03:50
  • Surely all you need to do is ask your friends again, and be clearer about your requirements. – paddy May 29 '18 at 03:52
  • 1
    Is it C or C++? – schaiba May 29 '18 at 07:01

1 Answers1

0

While I won't address there correctness of your implementation of the "Floyd Warshall Algorithm", I do think I can help you read decimal values.

First, a couple of thoughts, pointers, hints. (1) your code is C and has nothing to do with C++, other than C++ originally being derived as a super-set of C many many years ago (it is now a language unto itself, but still maintains the ability to use the traditional C-library functions); (2) avoid using <conio.h>, it is a windows-only header, and you can use the standard library function getchar() to hold the terminal open until you press return instead of using getch(), and there is simply no need for clrscr(); and finally (3) avoid the use of global variables unless absolutely required. Declare your needed variables in main() and pass them as parameters to any functions that require them.

To begin, the proper declarations for main are int main (void) and int main (int argc, char **argv) (which you will see written with the equivalent char *argv[]). note: main is a function of type int and it returns a value. See: C11 Standard §5.1.2.2.1 Program startup p1 (draft n1570). See also: See What should main() return in C and C++?.

Well done, when you need a constant using #define is the proper way to define one (or you can use a global enum to accomplish the same thing).

What values a variable can hold is determined by the type you declare the variable to be. Your integer types are char, short, int, long, long long (along with their unsigned and exact-width counterparts) and your types for holding decimal (floating-point) values are float and double. (generally 32-bit and 64-bit, respectively). So in your case, if you want w and d to be able to hold decimal values, you need to declare them with the proper type, e.g.

#define MAX 30
...
    double w[MAX][MAX] = {{ 0.0 }},         /* double or float type */
        d[MAX][MAX][MAX] = {{{ 0.0 }}};     /* to hold decimal values */

(it is always a good idea to initialize arrays to all zero to avoid an inadvertent attempt to read from an element that has not yet had its value set. This is also a difference between your global declarations (initialized zero by default) and when declaring the arrays within main() with automatic storage duration)

When you are taking user input -- regardless of the function you use, you need to validate the return of the input function and validate the input itself if it is required to be within a given range, e.g.

    printf ("enter the no. of vertices\n");
    if (scanf ("%d", &v) != 1) {    /* always validate scanf return */
        fprintf (stderr, "error: invalid integer input for v.\n");
        exit (EXIT_FAILURE);    /* exit on failure - adjust as desired */
    }
    if (v < 0 || v > MAX) {     /* validate v within range of MAX */
        fprintf (stderr, "error: v not within 0 - %d.\n", MAX);
        exit (EXIT_FAILURE);
    }

To read double values, you simply need to change your conversion specifier from %d (used to read integer values) to %lf (used to read double values -- you omit the 'l' modifier to read float). You must still provide the same validation, e.g.

    printf ("enter the weights\n");
    for (i = 0; i < v; i++)
        for (j = 0; j < v; j++)
            if (scanf ("%lf", &w[i][j]) != 1) { /* use %lf for double */
                fprintf (stderr, "error: invalid w[%d][%d].\n", i, j);
                exit (EXIT_FAILURE);
            }

Declaring w and d in main() will require that you pass w and d as parameters to floyd(), e.g.

void floyd (double d[][MAX][MAX], double w[][MAX], int v);

and you call it in main as:

    floyd (d, w, v);

Putting it altogether, you could do something like the following (note: I'm on Linux and don't need getchar() (or getch() to hold the terminal open, so I have wrapped that call in preprocessor checks so that it is only called on windows):

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

#define MAX 30

double min (double a, double b)
{
    return a < b ? a : b;
}

void floyd (double d[][MAX][MAX], double w[][MAX], int v);

int main (void) {

    int i, j, v = 0;
    double w[MAX][MAX] = {{ 0.0 }},         /* double or float type */
        d[MAX][MAX][MAX] = {{{ 0.0 }}};     /* to hold decimal values */

    // clrscr();    /* there is no need for clrscr() */

    printf ("enter the no. of vertices\n");
    if (scanf ("%d", &v) != 1) {    /* always validate scanf return */
        fprintf (stderr, "error: invalid integer input for v.\n");
        exit (EXIT_FAILURE);    /* exit on failure - adjust as desired */
    }
    if (v < 0 || v > MAX) {     /* validate v within range of MAX */
        fprintf (stderr, "error: v not within 0 - %d.\n", MAX);
        exit (EXIT_FAILURE);
    }

    printf ("enter the weights\n");
    for (i = 0; i < v; i++)
        for (j = 0; j < v; j++)
            if (scanf ("%lf", &w[i][j]) != 1) { /* use %lf for double */
                fprintf (stderr, "error: invalid w[%d][%d].\n", i, j);
                exit (EXIT_FAILURE);
            }


    floyd (d, w, v);

#if defined (_WIN32) || defined (_WIN64)
    getchar();  /* only keep console open on windows - using getchar() */
#endif

    return 0;
}

/* pass d and w as parameters */
void floyd (double d[][MAX][MAX], double w[][MAX], int v)
{
    int k = 0, i, j;

    for (i = 0; i < v; i++)     /* assign values for k = 0 */
        for (j = 0; j < v; j++)
            d[k][i][j] = w[i][j];

    for (k = 1; k < v; k++)     /* index from 1 based on params for min */
        for (i = 0; i < v; i++)
            for (j = 0; j < v; j++) {   /* assign min k = 1, 2 */
            d[k][i][j] = min(d[k-1][i][j], d[k-1][i][k]+ d[k-1][k][j]);
        }

    /* display in matrix */
    for (k = 0; k < v; k++)
    {
        printf (" k = %d\n", k);
        for (i = 0; i < v; i++) {
            putchar ('\n');     /* use putchar for single characters */
            for (j = 0; j < v; j++)
                printf(" %6.2f", d[k][i][j]);
        }
        printf ("\n\n");
    }
}

Example Use/Output

# ./bin/scanf_double_3d
enter the no. of vertices
3
enter the weights
1.1 2.2 3.3
4.4 5.5 6.6
7.7 8.8 9.9
 k = 0

   1.10   2.20   3.30
   4.40   5.50   6.60
   7.70   8.80   9.90

 k = 1

   1.10   2.20   3.30
   4.40   5.50   6.60
   7.70   8.80   9.90

 k = 2

   1.10   2.20   3.30
   4.40   5.50   6.60
   7.70   8.80   9.90

Look things over and let me know if this is what you intended and whether you have any further questions. Validating your algorithm is left to you.

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