-3

I would like to run C code in C++, using Xcode 8.33 on MacOS Sierra 10.12. I am new to C/C++, compilers, etc so please bear with me. The C code, when compiled and ran with make via Terminal, works. But when I throw all the same files into a XCode C++ project, there is an error with the data file. Note: I did change main.c to main.cpp.

//**** main.cpp *****

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>

extern "C" {
#include "msclib.h"
}

int main(int argc, char** argv)
{
    assert(argc >= 1);
    return msc_get_no(argv[1]);

}

The file msclib.c calls on the data file mscmix_dat.c. Here is also msclib.h

// ***** msclib.h *****

extern size_t msc_get_no(const char*); 

// ***** msclib.c *****

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>

#include "msclib.h"

struct msc_data
{
   const char* code;
   const char* desc;
};

typedef struct msc_data MSCDat;

static const MSCDat mscdat[] =
#include "mscmix_dat.c"
   ;

static const size_t msccnt = sizeof(mscdat) / sizeof(mscdat[0]);

static int msc_cmp(const void* a, const void* b)
{
   const char*   msc_code = a;
   const MSCDat* p        = b;   
   return strcmp(msc_code, p->code);
}

size_t msc_get_no(const char* msc_code)
{
   assert(NULL != msc_code);
   assert(strlen(msc_code) == 5);

   MSCDat* p = bsearch(msc_code, &mscdat[0], msccnt, sizeof(mscdat[0]), msc_cmp);

   if (NULL == p)
   {
      fprintf(stderr, "MSC \"%s\" not valid\n", msc_code);
      return 0;
   }

   assert(NULL != p);
   return p - &mscdat[0];
}

When running/compiling, the mscmix_dat.c file gets the error Expected identifier or ( - which is what I need help with. Even when I replace mscmix_dat.c with .cpp, I get the error Expected unqualified-id

// ***** mscmix_dat.c *****
{ //<-- Xcode highlights this line and gives the error
   { "*****", "Error" },
   { "00-01", "Instructional exposition (textbooks, tutorial papers, etc.)" },
   { "00-02", "Research exposition (monographs, survey articles)" },
   { "00A05", "General mathematics" },
   .
   .
   .
}

I would appreciate explanations as to why this error is occurring, suggestions on how to fix it, and if necessary alternatives to processing this data file. Thank you!

tamtam
  • 641
  • 9
  • 24
  • Can you call `sizeof` like that outside of a function? – tadman Apr 02 '18 at 22:51
  • 2
    @tadman: Sure you can, why wouldn't you be? – einpoklum Apr 02 '18 at 22:54
  • 4
    We need a [miminal, complete and verifiable example](https://stackoverflow.com/help/mcve) to help you. You didn't even say where you get the compilation error at. – einpoklum Apr 02 '18 at 22:55
  • 1
    Don't try to "conserve space" - post code we can at least attempt to compile. –  Apr 02 '18 at 22:56
  • @NeilButterworth: On second thought, I'm not sure about my previous comment. Who knows? He made his comment about this weird syntax within the quoted source file, not outside of it. – einpoklum Apr 02 '18 at 22:57
  • @einpoklum There's a limit on what functions you can run at compile time, and I wasn't sure if `sizeof` was limited that way. – tadman Apr 02 '18 at 23:02
  • 1
    @tadman: Just because something is initialised at namespace scope doesn't mean it's "run at compile time" – Lightness Races in Orbit Apr 02 '18 at 23:06
  • @LightnessRacesinOrbit That's the explanation I was looking for, that makes sense. – tadman Apr 02 '18 at 23:07
  • @tadman: I do try :) – Lightness Races in Orbit Apr 02 '18 at 23:07
  • 2
    @tadman: ... in this case it's moot anyway as `sizeof` is an _operator_ that requires only information known to the type system, i.e. at compile time. So even _if_ this had to be a constant-expression (which it doesn't), you'd be okay. – Lightness Races in Orbit Apr 02 '18 at 23:08
  • @NeilButterworth Per your comments, I have made the edits. All the code is now included to reproduce the same problem. – tamtam Apr 02 '18 at 23:12
  • @einpoklum Per your comments, I have made the edits. All the code is now included to reproduce the same problem. (couldn't tag multiple people in one comment) – tamtam Apr 02 '18 at 23:13
  • It's still not a [MCVE]. – Lightness Races in Orbit Apr 02 '18 at 23:15
  • @LightnessRacesinOrbit what am I missing? – tamtam Apr 02 '18 at 23:16
  • 1
    Click on the link. Currently you have not given us something we can copy/paste into a compiler and reproduce your problem. It is split into multiple files, and has nonsense like "..." in it. It's also almost certainly not _minimal_, which means we have to sift through it to find the problematic code when you should have done this during debugging! – Lightness Races in Orbit Apr 02 '18 at 23:16
  • This (http://coliru.stacked-crooked.com/a/349833022cafd0b8) is a bit closer to an MCVE. It does not reproduce the reported error, but only problems relating to attempted implicit conversion to `void*` (which is expected - C and C++ are different in this regard - you can't just take a C program and pretend it's a C++ program...) – Lightness Races in Orbit Apr 02 '18 at 23:18
  • @tadman you don't ***call*** `sizeof` it is not a function but evaluated by the compiler. – Weather Vane Apr 02 '18 at 23:25
  • @LightnessRacesinOrbit Ok noted. I did not know such merges were possible before. Regarding the issues with implicit conversion, do you have suggestions? I have tried `static_cast` and `reinterpret_cast`, but that causes "casts away qualifiers" – tamtam Apr 02 '18 at 23:53
  • Without any idea of what this program is supposed to do, no. – Lightness Races in Orbit Apr 02 '18 at 23:56

1 Answers1

0

OP here. These are the steps I took to resolve my issue, based on the last edit of my question:

  1. With the separate files, as given in my question, the error was Expected identifier in mscmix_dat.c.
  2. Per @LightnessRacesinOrbit's suggestion, I consolidated the multiple main.cpp, msclib.h, msclib.c, and mscmix_dat.c files into two files: main.cpp and msclib.c, by replacing the #include thisfile.c with the actual file code content. I also changed msclib.c to .cpp via simple rename. This eliminated the original error of Expected identifier, but a new one arose.
  3. Compiling the two files gave multiple errors in msclib.cpp, all wrt variable type conversions.
  4. Because of C++ differences from C, I handled the type conversion issue via casting, but also respecting const.

Below is my final, successfully compiling code.

// **** main.cpp ****
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>

#include<string>
#include<iostream>
using namespace std;

extern size_t msc_get_no(const char*);

int main(int argc, char** argv)
{
    assert(argc >= 0);
    return (int)msc_get_no(argv[1]); // casting

}

// **** msclib.cpp ****
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>

extern size_t msc_get_no(const char*);

struct msc_data
{
   const char* code;
   const char* desc;
};

typedef struct msc_data MSCDat;

static const MSCDat mscdat[] =
{
    { "*****", "Error" },
    { "00-01", "Instructional exposition (textbooks, tutorial papers, etc.)" },
    { "00-02", "Research exposition (monographs, survey articles)" },
    { "00A05", "General mathematics" }
}
   ;

static const size_t msccnt = sizeof(mscdat) / sizeof(mscdat[0]);

static int msc_cmp(const void* a, const void* b)
{
   const char*   msc_code = static_cast<const char*>(a); //<----
   const MSCDat* p        = static_cast<const MSCDat*>(b); // (const MSCDat*)b also works
   return strcmp(msc_code, p->code);
}


size_t msc_get_no(const char* msc_code)
{
   assert(NULL != msc_code);
   assert(strlen(msc_code) == 5);

    MSCDat* p; // changed initialization of p
   p = (MSCDat*) bsearch(msc_code, &mscdat[0], msccnt, sizeof(mscdat[0]), msc_cmp);

   if (NULL == p)
   {
      fprintf(stderr, "MSC \"%s\" not valid\n", msc_code);
      return 0;
   }

   assert(NULL != p);
   return p - &mscdat[0];
}
tamtam
  • 641
  • 9
  • 24