0

I am new to C programming and would like to create a char that puts text before an int.

char charPin[] = ("PIN%d",pin);

I want it so I can pass charPin to an external function. I am receiving an invalid initializer on the beginning of the line.

jrcichra
  • 335
  • 5
  • 16
  • 3
    Check the sprintf_s function. –  Jun 19 '16 at 21:25
  • 1
    Is `pin` an `int`? If `pin` has the value `42`, do you want `charPin` to have the value `"PIN42"`? If so, please update your question to make that clear. Show us the declaration of `pin`, and tell us what value you want `charPin` to have for a given value of `pin`. You can't solve a problem without first clearly stating what you're trying to accomplish. – Keith Thompson Jun 19 '16 at 22:03
  • This question shouldn't have been downvoted in my opinion – roschach Feb 05 '19 at 13:23

3 Answers3

2

You need a constant initialiser for incomplete arrays, so the compiler can determine the size at run-time. So it is not easily possible to use a variable for the pin-number.

If you can live with a constant pin, the following works:

#define STRINGIZE(x)    #x
#define CONCAT(a,b)     STRINGIZE(a##b)

static const char p10[] = CONCAT(PIN, 10);

int main(void)
{
    printf("%s\n", p10);
    return 0;
}

The # yields the argument enclosed with quotation marks, the concatenation operator ## concatenates the two arguments to a single one. They are preprocessor operators, which is the reason this does not work with variables.

A more useful example woud be to parametrize the pin-number only and use a macro to generate the rest of the text:

#define PIN(n)   STRINGIZE(PIN, n)

// usage:
... PIN(10) ...

That way you can change the text with just changing a single macro definition, e.g. for a different language:

#define PIN(n)   STRINGIZE(Anschluss, n)

If you need a variable, you have to put some more effort into it. However, if that is an example for the text you want to get, it might be easier to generate the names on-the fly along with the rest of the text you want to output, instead of storing into some array.

The best code depends on context you did not provide.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
1

Your statement

char charPin[] = ("PIN%d",pin);

is attempting to initialize an unspecified-length array of char with the expression ("PIN%d",pin). That expression looks Pythonesque, but it is syntactically valid in C: the parentheses perform their ordinary grouping function around an expression involving the comma (,) operator. Evaluated in a context that actually allows that expression, the result would have the same type and value as pin. That's not at all what you intend, and luckily the problem is of a type that the compiler rejects, as opposed to the one for which the compiler generates code to do the unintended thing you actually told it to do.

The initializer for an array of char can take either of two forms:

  • a string or UTF-8 literal, or
  • a brace-enclosed array of individual elements.

Neither of those suits your purpose, so you'll have to fill the array with your desired contents separately from its declaration. Moreover, that means you'll have to declare an explicit size for your array. You need space for the text part (whose size you know), for the integer part (whose size is variable, within limits), and for a one-byte string terminator.

If you're willing to make the very reasonable assumption that pin's data type (int?) is no wider than 64 bits, then 20 characters will be sufficient for the maximum possible 19 decimal digits plus a sign, therefore 24 characters should be enough for the whole string. It's usually best to avoid magic numbers in your code, so you might declare charPin like so:

#define PIN_BUFFER_SIZE 24

// ...

char charPin[PIN_BUFFER_SIZE];

There are several ways you could fill set the array contents, but the most straightforward way for your case would be to use either sprintf() or snprintf(). Suppose we're not entirely confident in our size computation, or that the text part is variable. We might then declare a bit more space in charPin than we think we'll need, but ultimately we want to ensure that we do not overwrite the bounds of the array. snprintf() is intended for that purpose:

int result = snprintf(charPin, PIN_BUFFER_SIZE, "PIN%d", pin);

That's the basic answer, but a careful programmer would not leave it at that. Supposing we want to be alerted in the event that our assumption about the needed space was wrong, instead of just letting the data be truncated, we would want to test the function's return value and handle any error that it indicates. We would also want to check for a general error code, as generally we should do for every function call that can signal an error:

if (result >= PIN_BUFFER_SIZE) {
    fprintf(stderr, "PIN truncated\n");
    exit(EXIT_FAILURE);  // or handle it some less-drastic way
} else if (result < 0) {
    // should not happen, but we're being thorough
    fprintf(stderr, "Internal I/O error\n");
    exit(EXIT_FAILURE);  // or handle it some less-drastic way
}
John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

What you are looking for is the sprintf function. First you have to declare an array big enough to store the result (which might not be easy, so in my example I'm using a fixed size of 50 characters), then using the function you initialize it with formatted data. You don't have to check the resulting string's length with strlen, because sprintf returns it already.

size_t arraySize = 50;
char charPin[arraySize];
int resultSize = sprintf(charPin, "PIN%d", pin);

If sprintf failed, resultSize will be a negative value. You can handle it with

if (resultSize < 0) {
    // react to failure here
}

Now to print the result you can use printf("%s", charPin);.

If you are trying to initialize the char array with a constant value, you can just write the PIN number (52 in my example) inside a string literal.

char charPin[] = "PIN52";
Community
  • 1
  • 1
Jezor
  • 3,253
  • 2
  • 19
  • 43
  • `snprintf` cannot be used to initialise an array. – too honest for this site Jun 19 '16 at 21:41
  • What am I doing in my example then? https://en.wikipedia.org/wiki/Initialization_(programming) - initialization doesn't mean one-line value assignment, array can be initialized using any number of operations and it is still considered an "initialization". – Jezor Jun 19 '16 at 21:46
  • While you initialise `resultSize`, you don't initialise the array, but write to it. The standard is very clear what an initialisation is. Typ using your code for static variables. – too honest for this site Jun 19 '16 at 21:53
  • 2
    `printf` returns an `int` intentionally, not a `size_t`. – too honest for this site Jun 19 '16 at 22:01
  • Could you please add a link to where the standard says that variable initialization have to be inlined? As for the int/size_t, I edited my answer - thanks! – Jezor Jun 19 '16 at 22:21
  • 1
    The term "initialisation" is a well-defined term in the standard and has its own section (6.7.9). And there is no "inlining" of initialisation either. Please use standard terms. An - to repeat - your code does not work where a _constant expression_ is required. Let along the waste of space for more than 300% unused memory overhead. – too honest for this site Jun 19 '16 at 22:27
  • I've read it and I see my mistake now, thank you. I have always assumed that initialization means just "to assign a value to a freshly declared variable". Anyways, Demodude123 is using a `pin` variable in his example, so I think that what he really wants after all is to know how to convert integer to a char sequence - which my answer explains how to do. If the `pin` variable is constant though, is there any way to initialize char array with it? – Jezor Jun 19 '16 at 22:44
  • I answered right on that, but you apparently cannot use a variable. That's what the preprocessor is for. – too honest for this site Jun 19 '16 at 22:49