3

Normally I always compiled my C code like this: g++ program.c -o program.exe

But my college professor requires me to compile using:g++ -o -Wall -Wextra -Werror -pedantic -std=c++0x program.exe program.c

(Which is new for me).

So ... I run the command and get the following error:

eda.c: In function ‘int main()’:
eda.c:200: error: ISO C++ forbids variable-size array ‘v’
eda.c:207: error: ISO C++ forbids variable-size array ‘nfloat’
cc1plus: warnings being treated as errors
eda.c:215: warning: suggest a space before ‘;’ or explicit braces around empty body in         ‘while’ statement

And this is the code of my program:

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


typedef struct {
    float* data;
    int size;
} vector;


/* Metodos Básicos */
vector *create_vector(int n, float* comps){
    vector *newvect = (vector*)malloc(sizeof(*newvect));
    newvect->data = (float*)malloc(n*sizeof(float));
    memcpy(newvect->data, comps, sizeof(float) * n);
    newvect->size = n;
    return newvect;
}

void destroy_vector(vector* v){
    free(v->data);
    free(v);
}

void print(vector* v){
    int size = v->size, i;
    for (i = 0; i < size; ++i)
    {
        if(i == 0) printf("[%.1f,", v->data[i]);
        else if(i == (size-1)) printf("%.1f]\n", v->data[i]);
        else printf("%.1f,", v->data[i]);
    }
}

/* Metodos Intermedios */
float dotDiferentSizes(vector* v1, vector* v2, int smax, int smin){
    double product;
    int i;
    for(i = 0; i < smin; i++){
        product += (v1->data[i])*(v2->data[i]); // += means add to product
    }
    for(i = smin; i < smax; i++){
        product += (v1->data[i])*0; // += means add to product
    }
    return product;
}

float dot(vector* v1, vector* v2){
    int smax = (v1->size), smin;
    int v1size = smax;
    int v2size = (v2->size);
    float product = 0.0;
    if (v2->size > smax) {
        smax = v2->size; //max_size checking
        smin = v1->size; //min_size checking
    }
    else if (v2->size < smax){
            smin = v2->size;
    }
    else smin = smax;
    // compute
    if(smax == smin){
        int i;
        for(i = 0; i < smin; i++){
            product += (v1->data[i])*(v2->data[i]); // += means add to product
        }
    }
    else{
        if(v1size == smax){
            product = dotDiferentSizes(v1,v2,smax,smin); //v1>v2
        }
        if(v2size == smax){
            product = dotDiferentSizes(v2,v1,smax,smin); 
        }
    }
    return product;
}

float norm(vector* v){
    int size = v->size, i;
    float norm = 0.0;
    for(i= 0; i < size; i++){
        norm += (v->data[i])*(v->data[i]);
    }
    norm = sqrt( norm );
    return norm;
}

void normalize(vector* v){
    int size = v->size, i;
    float norma = 0.0;
    norma = norm(v);
    for(i= 0; i< size; i++){
        v->data[i] = v->data[i] / norma;
    }
    for (i = 0; i < size; ++i)
    {
        if(i == 0) printf("NORMALIZED VECTOR:[%.2f,", v->data[i]);
        else if(i == (size-1)) printf("%.2f]\n", v->data[i]);
        else printf("%.2f,", v->data[i]);
    }
}

/* Metodos Avanzados */
vector* add(vector* v1, vector* v2){
    vector *vadd;
    int v1size, v2size, i;
    v1size = v1->size;
    int size = v1size;
    v2size = v2->size;
    if(v2size > v1size) {
        size = v2size;
        vadd = create_vector(size, v2->data);
        for(i = 0; i < v1size; i++){
            vadd->data[i] += v1->data[i];
        }
    }
    else {
        vadd = create_vector(size, v1->data);
        for(i = 0; i < v1size; i++){
            vadd->data[i] += v2->data[i];
        }
    }
    return(vadd);
}

vector* sub(vector* v1, vector* v2){
    vector *vsub;
    int v1size, v2size, i;
    v1size = v1->size;
    int size = v1size;
    v2size = v2->size;
    if(v2size > v1size) {
        size = v2size;
        vsub = create_vector(size, v2->data);
        for(i = 0; i < v1size; i++){
            vsub->data[i] = v1->data[i] - vsub->data[i]; /* restamos siempre v1 - v2*/
        } /* en el bucle forzamos a restar v1 - v2, evitando el caso v2 - v1*/
        for(i = v1size; i < size; i++){
            vsub->data[i] = (v2->data[i])*(-1);
        }
    }
    else { /* v1size >= v2size */
        vsub = create_vector(size, v1->data);
        for(i = 0; i < v2size; i++){
            vsub->data[i] -= v2->data[i];
        }
    }
    return(vsub);
}

void incr(vector* source, vector* other){
    int smax, i, ssize = source->size, osize = other->size;
    vector *vincr;
    if(ssize > osize) smax = ssize;
    else {
        if(ssize < osize) smax = osize;
        else smax = ssize;
    }
    vincr = add(source, other);
    if(ssize > osize){
        for(i = 0; i < smax; i++){
            source->data[i] = vincr->data[i];
        }
    }
    else{
        source->data = (float*)realloc(source->data, sizeof(float) * smax);
        source->size = smax;    
        for(i = 0; i < smax; i++){
            source->data[i] = vincr->data[i];
        }
    }
    print(source);
    free(vincr);
}

//NumsVector, funcion que nos devuelve el numero de "numeros" que hay en cada vector del .txt,
//es decir, los n floats por cada vector

int NumsVector(char *linea, ssize_t size){
    int numsvector = 1; //Inicializamos a 1 ya que no podemos suponer valor maximo segun enunciado, pero si minimo >= 1
    int n;
    for(n = 2; n<= size; n++){ //como ya suponemos que el primer valor despues del corchete es un numero y ya lo hemos contado, empezamos en 2
        if (linea[n] != '[' && linea[n] != ']'){
            if(linea[n] == 44){
                numsvector = numsvector + 1;
            }
        }
    }
    return numsvector;
}


int main(){
    int n, i;
    scanf("%d\n", &n);
    vector *v[n];
    for(i = 0; i<n; ++i) { 
        char *line = NULL;  //ponemos *line y len a valores 0 y null para que automaticamente getline nos haga el malloc y nos asigne el tamanyo
        size_t len = 0;
        ssize_t read; //en la variable read guardamos el valor de getline, contiene el numero de caracteres que tiene el string
        read = getline(&line,&len,stdin);
        int numsvector = NumsVector(line, read); 
        float nfloat[numsvector]; //sabemos el tamanyo del vector que hemos leido, creamos array de floats y lo llenamos de los floats
        //empieza el proceso para obtener los floats a partir de string de chars
        int j = 0;
        line[strlen(line) - 1] = ','; /* Replaces the end ] with a , */
        char *p = line + 1; /* creates a new pointer, pointing after the first [ in the original string */
        do
        {
            sscanf(p, "%f,", &nfloat[j]); /* grabs up to the next comma as a float */       
            while (*(p++) != ',') ; /* moves pointer forward to next comma */
        }
        while (++j < numsvector); /* stops when you've got the expected number */     
        v[i] = create_vector(numsvector, nfloat);//conseguimos almacenar el contenido del string en un vector del tipo float (nfloat)
        int aux;
        for(aux = 0; aux<numsvector; ++aux){ 
            printf("V[%d]->data[%d] = : %.1f\n", i, aux, v[i]->data[aux]); //test de que la memoria se almacena bien, luego se borra
        }
        free(line);
    }
}

These are the lines that give errors:

200: vector *v[n];
207: float nfloat[numsvector];
215: while (*(p++) != ',') ; //Now I think works fine with the extra space..

please could someone help me compile the file?

11
  • You sure you want C++ for this? This code looks like C to me. Commented Oct 16, 2013 at 19:34
  • 1
    If this is a C++ program, don't use malloc and free. Try new and delete instead. Commented Oct 16, 2013 at 19:36
  • 4
    @Gerard So why is this tagged C++? Why are you using g++? If you can use only C, then write C code and compile it as C code. Commented Oct 16, 2013 at 19:40
  • 1
    @Voo It is the desire of my teacher, we can only use g+ + and c language Commented Oct 16, 2013 at 19:44
  • 3
    @Gerard: it's worse than annoying; C and C++ have different semantics in some fundamental areas (size and types of character constants, types of c-style strings, treatment of void pointers, etc.). If he's demanding you compile C code with a C++ compiler, then he's setting you up for problems later on. There's no good justification for it. Commented Oct 16, 2013 at 20:17

3 Answers 3

5

The problem is that the feature your are using(Variable Length Arrays or VLA) is a C99 feature and is not part of C++ standard but gcc supports it as an extension, -pedantic will force gcc to warn you when you are using extensions and -Werror will make warnings errors which will effectively prevent you from using extensions.

One option if you are are able to use C++ would be to use std::vector. Another option would be to use dynamic allocation via new or malloc depending on which you are allowed to use.

It is a bit odd that it seems like you have to program in C but use C++ compiler, I would expect at least that you could use -x c to make g++ to act as a C compiler. Here is an article that covers the Compatibility of C and C++, you should also read Keith's comments as well.

Sign up to request clarification or add additional context in comments.

4 Comments

@ShafikYaghmour My teacher forced us to use the g++ compiler and C language :(
@Gerard: Your teacher is making a serious mistake. g++ is not a C compiler, it's a C++ compiler, and C is most definitely not a proper subset of C++. The main problem is that C++ forces a cast on the result of malloc, which is legal but poor style in C (int *p = malloc(sizeof *p); is valid C, but C++ doesn't do the implicit conversion). If that's what you're stuck with, make sure your code compiles cleanly with both g++ -Wall -Wextra -Werror -pedantic -std=c++0x and gcc -Wall -Wextra Werror -pedantic -std=c99`.
@crashmstr If I could I would :)
@KeithThompson I would have added this previous thread to my answer as well but alas the article the top answers link to seems to not work.
2

Normally I always compiled my C code like this: g++ program.c -o program.exe

That's incorrect. g++ is a C++ compiler, not a C compiler. (I know, you can specify -x c to force the language, but why would you do that when you have a C compiler as well?)

C code should be compiled with a C compiler. C++ code should be compiled with a C++ compiler. Any other combination is erroneous.

If you are required to write C++ code, then write C++ code. In C++, you can't have C99-style variable-length arrays. You will need to use std::vector instead. Like this:

std::vector<some_type> theVector(initial_size);

1 Comment

@Gerard What kind of brain-dead school are you attending? Using C with a C++ compiler is wrong. Just like compiling C++ code with a C compiler. You simply can't do that.
1

200: vector *v[n]; can be fixed by initializing the vector:

vector* v = new vector[n];

207: float nfloat[numsvector]; can be fixed by dynamically allocating the array:

float* nfloat = new float[numsvector]

I believe these are the corresponding C memory allocations:

vector* v = malloc(n * sizeof(vector));

float* nfloat = malloc(numsvector * sizeof(float));

9 Comments

Caution, his code declares a struct by the same name, vector.
The question is about building a vector in C, not using std::vector.
I've edited the code so it doesn't use std::vector. Only the memory allocation needs to be in C now.
@DaanKolthof the memory allocation for nfloat works, many thanks!, but for v I think is incorrect, I tried: vector *v[n] = (vector*)malloc(sizeof(*v[n])); And I get on screen: iMac-de-Gerard:Desktop Gera$ g++ -Wall -Wextra -Werror -pedantic -o eda.exe eda.c eda.c: In function ‘int main()’: eda.c:225: error: ISO C++ forbids variable-size array ‘v’ eda.c:225: error: variable-sized object ‘v’ may not be initialized
In C you wouldn't cast the return of malloc, this is frowned upon. This is one of the differences that make compiling C code with a C++ a completely stupid idea.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.