0

I am trying to port to C. Since there's no vectors in C, I used a normal array, but I don't know how I'm going to deal with the ranged based loop on line 18.

    for (int u : d[i]) if (dfs(rev[u])) {
        par[i] = u;
        rev[u] = i;
        return true;
    } 

Complete code:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>

using namespace std;
const int Maxn = 200;
vector<int> d[Maxn];
int par[Maxn];
int rev[Maxn];
bool vs[Maxn];
bool dfs(int i) {
    if (i < 0) return true;
    if (vs[i]) return false;
    vs[i] = true;
    for (int u : d[i]) if (dfs(rev[u])) {
        par[i] = u;
        rev[u] = i;
        return true;
    }
    return false;
}
int main() {
    ios_base::sync_with_stdio(false);
    int n;
    cin >> n;
    string s;
    getline(cin, s);
    for (int i = 0; i < n; i++) {
        getline(cin, s);
        stringstream ss(s);
        vector<int> mk(n, 1);
        mk[i] = 0;
        int x;
        while (ss >> x)
            mk[x] = 0;
        for (int x = 0; x < n; x++)
            if (mk[x])
                d[i].push_back(x);
    }
    memset(par, -1, sizeof par);
    memset(rev, -1, sizeof rev);
    for (bool ok = true; ok; ) {
        ok = false;
        memset(vs, 0, sizeof vs);
        for (int i = 0; i < n; i++)
            if (par[i] < 0) {
                ok |= dfs(i);
            }
    }
    int ans = 0;
    for (int i = 0; i < n; i++)
        ans += (par[i] < 0);
    cout << ans;
}
user4581301
  • 33,082
  • 7
  • 33
  • 54
  • 2
    Please don't post links to other site with code, post the code here in your question. – Pablo Jan 12 '18 at 23:46
  • `for (int u = 0; u < sizeof(d)/sizeof(int); i++) { if (dfs(rev[u])) { ... return true; } }` – Tibrogargan Jan 12 '18 at 23:52
  • @Elie Kahwaji I see that `d` is an array of vectors in your C++ code. When I edited my answer, I did not notice that. How did you convert `d` in your C code, as `int **d`? – Pablo Jan 13 '18 at 00:25
  • It depends on how you have mapped an array of `std::vector` (which is what `d` is) to C. Since a `std::vector` encapsulates a resizable dynamically allocated array, there are many ways you could do that mapping, which in turn would affect how you handle loops. You have given NO INFORMATION AT ALL on how you have done that mapping, so cannot expect useful help. Voting to close accordingly. – Peter Jan 13 '18 at 06:20

2 Answers2

2

In C there is no std::vector, the closes would be an array.

int array[] = [ 1, 3, 5, 7, 9 ];

for(int i = 0; i < sizeof array / sizeof *array; ++i)
    printf("array[%d] = %d\n", i, array[i]);

If you get a pointer of an array of int, the you have to pass the length of the array as well, as sizeof arr / sizeof *arr works with arrays only.

void foo(in *array, size_t len)
{
    for(int i = 0; i < len; ++i)
        printf("array[%d] = %d\n", i, array[i]);
}

void bar(void)
{
    int array[] = [ 1, 3, 5, 7, 9 ];

    foo(array, sizeof array / sizeof *array);
}

edit 2

I noticed that you've posted your code and that d is declared as vector<int> d[Maxn];. Also taking in consideration your recent comment

So this is an array of vectors. Do you have any idea how i can work with arrays taking that in consideration in C

There a couple of ways to convert the array of vectors in C. But this depends on your needs. If for example you know that all vectors are going to have the same size (for example int vectsize = 100), then you can create a two dimensional array with the sizes1

int Maxn = 200;
int vectsize = 100;

int d[Maxn][vectsize];
memset(d, 0, sizeof d); // initialize all elements with 0

// filling the data
for(int i = 0; i < Maxn; ++i)
{
    for(j = 0; j < vectsize; ++j)
        d[i][j] = get_value_for(i, j); 
}

The the range-loop is very easy:

// assuming that the variables i, par, rev are valid, i between 0 and Maxn-1
for(int j = 0; j < vectsize; ++j)
{
    int u = d[i][j];
    if (dfs(rev[u])) {
        par[i] = u;
        rev[u] = i;
        return true;
    } 
}

It gets a little more complicated if you only know one dimension, for example every vector in the array could have a different size.

d[0].size() --> 10
d[1].size() --> 1
d[2].size() --> 3
...

The you can create an array of pointers to int, but you would have to keep another array of ints with the length for every d[i] vector.

int Maxn = 200;
int *d[Maxn]; // pointer to int[Maxn] arrays
int vectsize[Maxn];

// initializing with 0
memset(d, 0, sizeof d);
memset(vectsize, 0, sizeof vectsize);

// filling the data
for(int i = 0; i < Maxn; ++i)
{
    vectsize[i] = get_length_for(i);
    d[i] = malloc(vectsize[i] * sizeof *d[i]);
    if(d[i] == NULL)
        // error handling

    for(j = 0; j < vectsize[i]; ++j)
        d[i][j] = get_value_for(i, j); 
}

Note that I'm using here (and in the last example) get_length_for() and get_value_for() as placeholders2.

Now your range-base loop would look like this:

// assuming that the variables i, par, rev are valid, i between 0 and Maxn-1
for(int j = 0; j < vectsize[i]; ++j)
{
    int u = d[i][j];
    if (dfs(rev[u])) {
        par[i] = u;
        rev[u] = i;
        return true;
    } 
}

At some point however you would have to free the memory:

for(int i = 0; i < Maxn; ++i)
    free(d[i]);

The third option would be using a double pointer and using malloc/realloc to allocate the memory. This is the more general solution, but you have to take care of memory management and that can be sometimes difficult, especially when you haven't programmed in C to much. But also in case where both dimension are unknown, this is the way to go:

int Maxn = get_some_maxn_value();
int **d, *vectsize;

d = malloc(Maxn * sizeof *d);
if(d == NULL)
    // error handling

vectsize = malloc(Maxn * sizeof *vectsize);
if(vectsize == NULL)
    // error handling,
    // if you exit the function, don't forget
    // to do free(d) first as part of the
    // error handling

// initialize all elements with 0
memset(d, 0, Maxn * sizeof *d);
memset(vectsize, 0, Maxn * sizeof *vectsize);

// filling the data (the same as above)
for(int i = 0; i < Maxn; ++i)
{
    vectsize[i] = get_length_for(i);
    d[i] = malloc(vectsize[i] * sizeof *d[i]);
    if(d[i] == NULL)
        // error handling

    for(j = 0; j < vectsize[i]; ++j)
        d[i][j] = get_value_for(i, j); 
}

In this case the range-loop would look exactly as for the array of pointers. Freeing the memory is a little bit different though:

for(int i = 0; i < Maxn; ++i)
    free(d[i]);
free(d);
free(vectsize);

Like I said earlier, which one of these three methods to use depends on the way the original C++ code fills the values, how long the vectors are, etc. Judging form the C++ code you posted, you read an integer from the user and store it in n. Then you read more values from the user and push then in the vector d[i] for all i between 0 and Maxn-1. It seems that all vectors have at most length n, but because of

if (mk[x])
    d[i].push_back(x);

they also could have less than n elements. That's why I think that the third solution is preferable here.


Annotations

1Prior to C99, Variable Length Arrays (VLA) were not supported, so if you had the dimension in a variable, you had to use malloc to allocate enough memory. C99 supports VLAs, but I'm not quite sure how well supported they are and/or whether your compiler supports them.

I personally don't use them in my code at all, that's why I really don't know. I compiled this examples with GNU GCC 6.4.0 (on linux) and they worked fine.

The first two options use VLAs, if your compiler doesn't support that, then you have to use the third option.

For more information about VLAs:

2How you really get this values depends on the original C++ code. So far I've only looked very briefly over your C++ code. Using the values from my example get_length_for(0) would return 10, get_length_for(1) would return 1, get_length_for(2) would return 3, etc.

Pablo
  • 13,271
  • 4
  • 39
  • 59
  • @Tibrogargan I pressed saved to quickly without reviewing my own answer, I fixed the mistakes, thank you for the feedback. But *`d.size()` is not defined*. I said *`d` should be `vector`*. – Pablo Jan 13 '18 at 00:10
  • @Tibrogargan Ah stupid me, of course, at that point I was still thinking in C++. I'll fix my answer. – Pablo Jan 13 '18 at 00:13
  • 1
    Ok, for stupid mistakes like this, the downvote is deserved. It would be nice however, if the person downvoting leaves comments so that the answers can be fixed. – Pablo Jan 13 '18 at 00:17
  • https://meta.stackexchange.com/questions/228358/why-are-my-questions-on-stack-overflow-getting-downvotes-without-explanation – Tibrogargan Jan 13 '18 at 00:19
  • @Tibrogargan thanks for the link. It was deserved, I should have read my answer before hitting *Post your answer*, I'll be more careful in the future. – Pablo Jan 13 '18 at 00:23
  • So this is an array of vectors. Do you have any idea how i can work with arrays taking that in consideration in C. – Elie Kahwaji Jan 13 '18 at 00:35
  • @ElieKahwaji yes, I'm editing right now my answer to address your last comment, it will take me a couple of minutes. – Pablo Jan 13 '18 at 00:45
  • Alright, ill check this section tomorrow. Thanks for your help. – Elie Kahwaji Jan 13 '18 at 01:34
  • @ElieKahwaji I made an update of my answer, hope this help you. – Pablo Jan 13 '18 at 02:37
  • @Pablo Thank you so much with your help. One last thing, what can I do about the second vector (the mk vector) also I tried replacing the stringstream with char pointer but I have no idea how to deal with the >> operator with C or how to iterate that while loop in C – Elie Kahwaji Jan 13 '18 at 11:31
  • 1
    @ElieKahwaji This is getting out of hand, there are too many questions and I don't want my answer to be longer. It would be best if you start a new question just focusing on how to translate the vector and stringstream mechanics into C. `mk` is vector that has `n` elements all initialized with 1. Read the first part of my answer, it tells you how to emulate the behaviour of vectors with arrays, with that you can convert `mk` (to be continued) – Pablo Jan 13 '18 at 16:22
  • @ElieKahwaji the stringstream is used to parse the values. The user enter a line like `1 2 3 4 5` and every number is assigned to `x` and push into the vector. In C you would have to use something like `sscanf` or `strtok` to get the values and put them in the array. – Pablo Jan 13 '18 at 16:24
-1

Assuming d[i] is a vector, this is a similar loop:

for (size_t s = 0; s < d[i].size(); s++)
{
    int u = d[i][s];
    if (dfs(rev[u]))
    {
        par[i] = u;
        rev[u] = i;
        return true;
    }
}
Sid S
  • 6,037
  • 2
  • 18
  • 24