0

Is there a way to get an array of exactly n elements as a function input? (I know I can use an if statement to check the input, but I need a "live warning" or a "compile error".)

Something like:

void getInt(int number /*This number must be exactly four digits, to be printed on four 7-segments*/){

}

void getCh(char *names /*exactly 4 chars*/){
    
}

int main(){
    char boy[5] = "David";
    char girl[4] = "Jane";
    getCh(boy); //I need a compile error here (Or any other run-time warnings)
    getCh(girl); //"Jane" is 4 characters. OK.
    int num = 40, num2 = 12000;
    getInt(num);
    getInt(num2); //I need a warning/compile error here.
    return 0;
}

Is there any feature? Like macros, pointers, etc.

Mohammad Kholghi
  • 533
  • 2
  • 7
  • 21
  • Both, `boy` and `girl` are to small to store what you try to init them to. I hence suspect that you understand `girl` to be an array of size 4. That in turn makes me wonder why you want the error for `getCh(girl)` but apparantly NOT for `getCh(boy)`. – Yunnosch May 05 '21 at 05:08
  • @Yunnosch Oh thanks. It was a typo. I edited it. – Mohammad Kholghi May 05 '21 at 05:26
  • @Yunnosch No. I have four 7-segments (Do you know what a 7-Segment is?) and I need the input string to have exactly four characters. – Mohammad Kholghi May 05 '21 at 05:29
  • Did you read [*Modern C*](https://modernc.gforge.inria.fr/) and [this C reference](https://en.cppreference.com/w/c) and [n1570](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) and the documentation of your C compiler (e.g. [GCC](http://gcc.gnu.org/)...)? Are you allowed to use `struct`-s? – Basile Starynkevitch May 05 '21 at 05:30
  • maybe you can use assert – Hancel Lin May 05 '21 at 05:30
  • Did you read the wikipedia page on [integers](https://en.wikipedia.org/wiki/Integer) ? Are you allowed to use a debugger like [GDB](https://www.gnu.org/software/gdb/) ? Or static analysis tools like [Frama-C](https://frama-c.com/) ? – Basile Starynkevitch May 05 '21 at 05:32
  • I voted to reopen as the proposed dupe didn't answer this question IMO. – Support Ukraine May 05 '21 at 05:39
  • @4386427 yeah same – M.M May 05 '21 at 05:40
  • I agree with rejecting my dupe. Because of info in later comments. – Yunnosch May 05 '21 at 05:42
  • You want to notice at runtime when a string longer than 4 is used (not including terminator `'\0'`). Please explain why using `strlen()` and a simple `if` is not the solution. Might need terminated strings. – Yunnosch May 05 '21 at 05:43
  • @Yunnosch JAnE in 7-segment seems fine – M.M May 05 '21 at 05:50
  • @M.M I take that as agreeing with "extremely creative font". But I could have specified that a font for all letters of a language (even one with only puny 26 letters) needs to be creative, as opposed to one which can only show digits and "Jane". ;-) Of course "bobb" is OK, and a rendering for "M.M." is of course also obvious. .... Hmm, wait. – Yunnosch May 05 '21 at 05:53
  • @HancelLin How can I use `assert`? – Mohammad Kholghi May 05 '21 at 06:00
  • @BasileStarynkevitch I use the Keil compiler. It's for microcontrollers programming. – Mohammad Kholghi May 05 '21 at 06:02
  • @MohammadKholghi Regarding `assert` - did you read my answer? – Support Ukraine May 05 '21 at 06:02
  • @Yunnosch No problem. I have to remove some characters. For example, `o` and `a` are the same, so `a` is removed and `A` is used. I'm creating a character table. Thanks for the reminder. I just need the compiler to have an error when a string of more than four characters is used. Just that. – Mohammad Kholghi May 05 '21 at 06:04
  • @MohammadKholghi BTW: When you say that `number` must be exactly 4 digits, do you consider leading zeros as acceptable. I wonder because it seems you want to accept `getInt(40);` – Support Ukraine May 05 '21 at 06:06
  • Did you read the documentation of your Keil compiler? Are you allowed to try the [GCC](http://gcc.gnu.org/) compiler (invoke it as `gcc -Wall -Wextra -g`) on your C code? If using GCC is allowed, you could write your [GCC plugin](https://gcc.gnu.org/onlinedocs/gccint/Plugins.html) to detect *some* errors at compile time. But be aware of [Rice's theorem](https://en.wikipedia.org/wiki/Rice%27s_theorem) – Basile Starynkevitch May 05 '21 at 06:10
  • @4386427 I'm using `NetBeans`. There is no keyword as `assert`. What should I do? It's C99. There is no problem with 40. As you mentioned, I have to see it as 0040. – Mohammad Kholghi May 05 '21 at 06:15
  • @MohammadKholghi Please clarify this: Is the input to `getCh` expected to be a) a C-style string with length 4 or b) a char array with 4 elements ? This makes an important difference – Support Ukraine May 05 '21 at 06:15
  • @MohammadKholghi Did you include assert.h ? – Support Ukraine May 05 '21 at 06:16
  • @MohammadKholghi Also clarify whether `char str[4] = "a"; getCh(str);` is to be considered valid or not? – Support Ukraine May 05 '21 at 06:22
  • @Yunnosch A microcontroller (MCU for microcontroller unit) is a small computer on a single metal-oxide-semiconductor (MOS) integrated circuit (IC) chip. A microcontroller contains one or more CPUs (processor cores) along with memory and programmable input/output peripherals. It's a cool chip, widely used in almost everything, like a refrigerator or a washing machine. I don't have any idea about "M.M", or even "MMM". Maybe I have to write a user document. For example, the bottom and top segments (A and D) means "M". – Mohammad Kholghi May 05 '21 at 06:24
  • @4386427 It's the first time I am adding assert to my code. It was cool. Thanks. What is the difference between the C-Style String and Char Array? Could you please make an example? IMO, `char str[4] = "a"; getCh(str);` should be valid. I turn other 7-segments off. – Mohammad Kholghi May 05 '21 at 06:26
  • 1
    :-) Nowadays I know what a microcontroller is. Thanks for explaining anyway. I put within "" what I was not knowing as a kid. Microcontrollers then were a rare thing and personal computers for much wealthier kids.... – Yunnosch May 05 '21 at 06:26
  • @MohammadKholghi A C-style string is a special application of a char-array. For a char-array to be a valid C-style string at least one element in the char-array must have the value `'\0'` (or just decimal 0). This indicates the end-of-string and is often called the string-termination character. So all C-style strings are stored in char-arrays but not all char-arrays contain valid C-style strings. – Support Ukraine May 05 '21 at 06:30
  • @4386427 Aha thanks. It's not important, I just need it to be 4 characters, to be printed on four 7-segments. `\0` is not important. – Mohammad Kholghi May 05 '21 at 06:33
  • @4386427 Well.... Nowadays a personal computer for the kids needs about as wealthy a family as owning two cars, maybe one. Then it was for families who also had a helicopter. – Yunnosch May 05 '21 at 07:11

3 Answers3

4

Disclamer: For getCh this answer expect the input to be a valid C-style string. I have asked OP to clarify whether this is a valid assumption. I'll update the answer when/if OP clarifies this.

There is no way to get a compiler warning/error for this. All you can do is to implement your own run-time check.

To generate a run-time warning do:

void getInt(int number)
{
    // Check that input is a 4 digit int
    if (number < 1000 || number > 9999)
    {
        puts("Warning: Illegal call");
        return;
    }

    ....
}

void getCh(char *names)
{
    // Check that input length is 4
    if (strlen(names) != 4)
    {
        puts("Warning: Illegal call");
        return;
    }

    ....    
}

To generate a run-time error (program halt) do:

void getInt(int number)
{
    assert(number >= 1000 && number <= 9999);

    ....
}

void getCh(char *names)
{
    assert(strlen(names) == 4);

    ....    
}

BTW:

Your arrays are to short for the initializers:

char boy[5] = "David"; --> char boy[6] = "David";
char girl[4] = "Jane"; --> char girl[5] = "Jane";

or better - leave the size-stuff to the compiler (then you wont get it wrong)

char boy[] = "David";
char girl[] = "Jane";

EDIT

If you don't like using strlen, you can check the first 5 chars one-by-one. For instance:

assert(names[0] != '\0' &&
       names[1] != '\0' &&
       names[2] != '\0' &&
       names[3] != '\0' &&
       names[4] == '\0');
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • The `strlen` suggestion does not work for OP's original code , where the strings being passed are not null-terminated – M.M May 05 '21 at 05:42
  • @M.M I consider that to be a bug in OPs code. I'm pretty sure OP didn't intend to use "too long" initializers. Just a classic C bug. – Support Ukraine May 05 '21 at 05:48
  • Maybe not a bug, but an unexplained restriction. Might have a reason, might be a design accident that can be changed. – Yunnosch May 05 '21 at 05:58
1

Both boy and girl are wrong defined, it should be:

char boy[6] = "David";
char girl[5] = "Jane";

I need a warning/compile error here.

You could have a look at signals to build your own error logic. https://man7.org/linux/man-pages/man0/signal.h.0p.html

  • 1
    OP's definition is allowed , and creates arrays that don't contain null-terminated strings – M.M May 05 '21 at 05:44
  • @M.M you're right it is valid C code. But it wouldn't work strlen() for example. –  May 05 '21 at 05:58
1

You can get a compile error for other sizes by having:

#define getCh(x) (_Static_assert(sizeof(x) == 4, "Size is not 4"), getCh(x))

Note that this only works when you supply an array as the argument, it doesn't work for pointers.

For added safety it is possible to have the macro reject pointers at compile time, see Array-size macro that rejects pointers .

M.M
  • 138,810
  • 21
  • 208
  • 365
  • While this is "pretty cool" I don't think it really solves the problem. Example: `char str[4] = "ab";` would pass the macro-check but pass a too short string – Support Ukraine May 05 '21 at 05:50
  • @4386427 well you can only get so far , trying to stop someone shooting themself in the foot. In any case, the function would need to have runtime checks for valid characters in order to generate the commands for the LED – M.M May 05 '21 at 05:52
  • After thinking a bit more about this, your answer may be the correct one. I just assumed input to be a valid C-style string but OP never stated that clearly. I have asked OP for clarification and added a disclamer to my answer. Let's see what happens... – Support Ukraine May 05 '21 at 06:20
  • I wanna learn your suggestion too, but I can't get it to work, as I have a lot of errors. Would you please add some more codes? Maybe I'm using it in a wrong way. – Mohammad Kholghi May 05 '21 at 06:38
  • @4386427 What is OP? – Mohammad Kholghi May 05 '21 at 06:38
  • 1
    @MohammadKholghi See https://meta.stackoverflow.com/questions/253162/what-is-an-op-when-referring-to-stack-exchange – Support Ukraine May 05 '21 at 06:51