Basic initialization of a function using arrays - c

Currently setting up a function to declare the cases for a 4-part seven-segment display (a digital alarm clock basically) but keep getting errors when trying to confirm that it is properly set (Specifically from the core opening line)
Have tried looking around, but nothing is specific enough to the arrays I need.
Just a note on the code. I have not properly set up a code block before, so I am unsure as to how to highlight syntaxes. If it is properly set up, just ignore this message
Originally had it set as int SegmentWrite(int...[]) but would not produce results.
Other tests I have tried is including a size [10][7] before the opening braces, to declare count and size, changing type from byte to int, char, and float (although only byte produced any sort of result, not being what I wanted)
void SegmentWrite (int SegmentDigits[]){
byte SegmentDigits = zero[7] {1,1,1,1,1,1,0};//0
one[7] = {0,1,1,0,0,0,0};//1
two[7] = {1,1,0,1,1,0,1};//2
three[7] = {1,1,1,1,0,0,1};//3
four[7] = {0,1,1,0,0,1,1};//4
five[7] = {1,0,1,1,0,1,1};//5
six[7] = {1,0,1,1,1,1,1};//6
seven[7] = {1,1,1,0,0,0,0};//7
eight[7] = {1,1,1,1,1,1,1};//8
nine[7] = {1,1,1,1,0,1,1}; //9
This particular snippet of code isn't supposed to do anything - not on it's own, at least. When verifying, to confirm proper formatting, I only got the error report "declaration of 'byte SegmentDigits' shadows a parameter' with the first line highlighted.
-Just a note, found another error, specifically with the opening line - "declaration of 'SegmentWrite' as array of void" or "'SegmentWrite' declared as function returning an array"

You need to use a different name for the parameter array and the local array in the function.
Also, the function should take another parameter, the digit that you're trying to display.
You should then declare a 2-dimensional array, and you can use the digit as an index into it.
void SegmentWrite (int SegmentDigits[7], int digit){
int allSegmentDigits[][7] = {
{1,1,1,1,1,1,0},//0
{0,1,1,0,0,0,0},//1
{1,1,0,1,1,0,1},//2
{1,1,1,1,0,0,1},//3
{0,1,1,0,0,1,1},//4
{1,0,1,1,0,1,1},//5
{1,0,1,1,1,1,1},//6
{1,1,1,0,0,0,0},//7
{1,1,1,1,1,1,1},//8
{1,1,1,1,0,1,1}} //9
memcpy(SegmentDigits, allSegmentDigits[digit], sizeof allSegmentDigits[0]);
}

Related

Frama-C Plugin: Resolve array-values

I'm working on a frama-c plugin that should resolve the values of all kinds of varibles. I managed to dereference pointers and structs and typedefs and print the correspoinding values.
Now I'm struggling with getting the values of an array.
Here is my approach so far, description below:
| TArray (typ, exp, bitsSizeofTypCache, attributes) -> (
let len = Cil.lenOfArray exp in
let rec loc_rec act max =
if act < max then(
let packed = match exp with
| Some x -> x
in
let inc = Cil.increm packed act in
let new_offset = (Index(inc, offset)) in
rec_struct_solver typ (vi_name^"["^(string_of_int act)^"]") (lhost, new_offset);
loc_rec (act+1) max
);
in
loc_rec 0 len
)
I managed to get the length of the array by using Cil.lenOfArray with the expression-option when matching the type.
Now my approach is to go over the length of the array, increment the describing expression and modify the offset, and then handle the variable like a local variable (in the next recursion-step).
I think this idea basically makes sense, but I don't know if the increment is done correctly (value ok, or multiplied by some size or something), or other things don't work.
The program compiles (with the warning that the matching doesn't include all cases, which is irrelevant, since I can only work with expressions, not with NONE), but doesn't output the (correct) results.
Is this the nearly the right approach, or am I doing it completely wrong? Can someone give me some hints on how to get the array's values?
If something is unclear (since it is hard to describe what I want), please let me know, I will modify my question.
EDIT
The expected result of a Code like this
int arr[3];
arr[0]=0;
arr[1]=1;
arr[2]=2;
arr[0]=3;
Should be something like that:
arr[0]=0;3
arr[1]=1
arr[2]=2
I simply want to get all the values at every index of the array over the program.
While I get only empty results, like arr[1]={ } (also for the other Indizes), so I simply don't get results for this Kind of access I use.
Your original code queries the value for the index Index(inc, offset), where inc is Cil.increm packed act, act is the current index, and packed is the size of the array. So you are basically making queries for size+0, size+1 ... size-+(size-1). All these offsets are invalid, because they are out-of-bounds. This is why you obtain the value Cvalue.V.bottom which pretty-prints as .
The simplest fix to your original code would have been to replace packed by a call to Cil.zero Cil_datatype.Location.unknown, but your own fix is fine.
I figured out how to do it:
The trick was, that with Cil.integer, a new constant exp can be built!
With Cil.integer Cil_datatype.Location.unknown act, I created a new exp.
With this exp, I was able to build an Index-Offset. Then I added this new offset to the actual offset of the array. This new offset was used to build a new lval.
By doing this, I got the access to the arrays indizes.
Now my output looks ok:
arrayTest:arr[0]---> 0; 3
arrayTest:arr[1]---> 1
arrayTest:arr[2]---> 2

Issue with managed array in C++/CLI

I'm a c++ programmer and I'm having some issue with managed array. I'll explain what i mean. I'm using Visual Studio to code a Windows Form to handle a device.
I need to plot datas from a MCU connected to my PC thru a serial port. To save the values incoming from serial port, I'm using an array like that:
array<double, 1>^ datas = gcnew array<double, 1>(ndatas);
array<Byte, 1>^ byteDatas = gcnew array<Byte, 1>(2*ndatas);
where ndatas is the number of values of my series and byteDatas is the array where I will save the bytes that compose every value. Every value is made by 2 bytes.
After that, I will fill this array like this:
for(int i = 0; <=ndatas; ) {
if(bytes = serialPort1->BytesToRead>=2) {
datas[i] = getData(serialPort1, byteDatas, i);
}
i++;
}
The funcion getData is this one:
double getData(serialPort^ sp, array<Byte,1> data, int i) {
union Level {
char L[2];
signed short level;
} lvl;
sp->Read(data, i, 2);
for(int j = 0; j<=2; j++) {
lvl.L[j]= data[i+j];
}
return safe_cast<double>(lvl.level/100.00);
}
This function is on another .cpp file, so I had to use the variable SerialPort.
Everything goes like charm. If I try to use a MessageBox to display my datas, I can see how my array is correctly filled with the right values.
My next step to do, is to plot this data on a pictureBox using drawLine. But I really can't cause half of the values of the array datas are set to 0. For istance, if my series has 100 values, I can draw only the first values with the right amplitude. The other are represented, of course, as a horizontal line of zeroes.
To find this out, I have used a for cycle like that.
for(int i = 0; i<=datas->Length; i++) {
MessageBox::Show(Convert::ToString(datas[i]+" " + Convert::ToString(i+1));
}
just to be sure from when I will find the problem.
The strange part of this one is that, if I put the same MessageBox line of code under
datas[i] = getData(serialPort1, byteDatas, i);
I can display all of values without zeroes.
I'm stuck, and I don't know how to get rid of this problem. I hope I can find a little help to overcome this annoying issue.
I wish everything is crystal clear and I would like to thank everyone will give me a feedback.
Cheers,
Emiliano
When you do call getData, you're getting a valid value.
But BytesToRead goes down as you read data. At some point it drops below 2, and the rest of the for loop does nothing.
You might need to save where you are in the array when you run out of data, and when more serial data arrives, continue filling in the array from where you left off.
Plus, of course, right now you appear to be putting every data value into element 0 of the array, because you never increment i.
Also, you're reading each data point at index i, which means that you overwrite the second byte from the previous sample.
There's no need for safe_cast, the result of the division is already a double. And even if you needed a conversion, safe_cast isn't appropriate, since none of these data types are polymorphic.
Furthermore, your use of the union causes undefined behavior.
Finally, you're in C++. So why are you using what is probably the worst designed serial port API Microsoft ever made? This is C++. Calling Win32 APIs is easy, just #include <windows.h> and go, no p/invoke needed.

Need suggestion on Code conversion to Matlab_extension 2

This is an extension of the previously asked question: link. In a short, I am trying to convert a C program into Matlab and looking for your suggestion to improve the code as the code is not giving the correct output. Did I convert xor the best way possible?
C Code:
void rc4(char *key, char *data){
://Other parts of the program
:
:
i = j = 0;
int k;
for (k=0;k<strlen(data);k++){
:
:
has[k] = data[k]^S[(S[i]+S[j]) %256];
}
int main()
{
char key[] = "Key";
char sdata[] = "Data";
rc4(key,sdata);
}
Matlab code:
function has = rc4(key, data)
://Other parts of the program
:
:
i=0; j=0;
for k=0:length(data)-1
:
:
out(k+1) = S(mod(S(i+1)+S(j+1), 256)+1);
v(k+1)=double(data(k+1))-48;
C = bitxor(v,out);
data_show =dec2hex(C);
has = data_show;
end
It looks like you're doing bitwise XOR on 64-bit doubles. [Edit: or not, seems I forgot bitxor() will do an implicit conversion to integer - still, an implicit conversion may not always do what you expect, so my point remains, plus it's far more efficient to store 8-bit integer data in the appropriate type rather than double]
To replicate the C code, if key, data, out and S are not already the correct type you can either convert them explicitly - with e.g. key = int8(key) - or if they're being read from a file even better to use the precision argument to fread() to create them as the correct type in the first place. If this is in fact already happening in the not-shown code then you simply need to remove the conversion to double and let v be int8 as well.
Second, k is being used incorrectly - Matlab arrays are 1-indexed so either k needs to loop over 1:length(data) or (if the zero-based value of k is used as i and j are) then you need to index data by k+1.
(side note: who is x and where did he come from?)
Third, you appear to be constructing v as an array the same size of data - if this is correct then you should take the bitxor() and following lines outside the loop. Since they work on entire arrays you're needlessly repeating this every iteration instead of doing it just once at the end when the arrays are full.
As a general aside, since converting C code to Matlab code can sometimes be tricky (and converting C code to efficient Matlab code very much more so), if it's purely a case of wanting to use some existing non-trivial C code from within Matlab then it's often far easier to just wrap it in a MEX function. Of course if it's more of a programming exercise or way to explore the algorithm, then the pain of converting it, trying to vectorise it well, etc. is worthwhile and, dare I say it, (eventually) fun.

indexed object dot notation method gives scalar property

I'm seeing an issue when I try and reference an object property after having used a dot notation to apply a method.
it only occurs when I try to index the initial object
classdef myclassexample
properties
data
end
methods
function obj = procData(obj)
if numel(obj)>1
for i = 1:numel(obj)
obj(i) = obj(i).procData;
end
return
end
%do some processing
obj.data = abs(obj.data);
end
end
end
then assigning the following
A = myclassexample;
A(1).data= - -1;
A(2).data = -2;
when calling the whole array and collecting the property data it works fine
[A.procData.data]
if i try and index A then i only get a scalar out
[A([1 2]).procData.data]
even though it seems to do fine without the property call
B = A([1 2]).procData;
[B.data]
any ideas?
I would definitely call this a bug in the parser; A bug because it did not throw an error to begin with, and instead allowed you to write: obj.method.prop in the first place!
The fact that MATLAB crashed in some variations of this syntax is a serious bug, and should definitely be reported to MathWorks.
Now the general rule in MATLAB is that you should not "index into a result" directly. Instead, you should first save the result into a variable, and then index into that variable.
This fact is clear if you use the form func(obj) rather than obj.func() to invoke member methods for objects (dot-notation vs. function notation):
>> A = MyClass;
>> A.procData.data % or A.procData().data
ans =
[]
>> procData(A).data
Undefined variable "procData" or class "procData".
Instead, as you noted, you should use:
>> B = procData(A): % or: B = A.pocData;
>> [B.data]
FWIW, this is also what happens when working with plain structures and regular functions (as opposed to OOP objects and member functions), as you cannot index into the result of a function call anyway. Example:
% a function that works on structure scalar/arrays
function s = procStruct(s)
if numel(s) > 1
for i=1:numel(s)
s(i) = procStruct(s(i));
end
else
s.data = abs(s.data);
end
end
Then all the following calls will throw errors (as they should):
% 1x2 struct array
>> s = struct('data',{1 -2});
>> procStruct(s).data
Undefined variable "procStruct" or class "procStruct".
>> procStruct(s([1 2])).data
Undefined variable "procStruct" or class "procStruct".
>> feval('procStruct',s).data
Undefined variable "feval" or class "feval".
>> f=#procStruct; f(s([1 2])).data
Improper index matrix reference.
You might be asking yourself why they decided to not allow such syntax. Well it turns out there is a good reason why MATLAB does not allow indexing into a function call (without having to introduce a temporary variable that is), be it dot-indexing or subscript-indexing.
Take the following function for example:
function x = f(n)
if nargin == 0, n=3; end
x = magic(n);
end
If we allowed indexing into a function call, then there would be an ambiguity in how to interpret the following call f(4):
should it be interpreted as: f()(4) (that is call function with no arguments, then index into the resulting matrix using linear indexing to get the 4th element)
or should it interpreted as: f(4) (call the function with one argument being n=4, and return the matrix magic(4))
This confusion is caused by several things in the MATLAB syntax:
it allows calling function with no arguments simply by their name, without requiring the parentheses. If there is a function f.m, you can call it as either f or f(). This makes parsing M-code harder, because it is not clear whether tokens are variables or functions.
parentheses are used for both matrix indexing as well as function calls. So if a token x represents a variable, we use the syntax x(1,2) as indexing into the matrix. At the same time if x is the name of a function, then x(1,2) is used to call the function with two arguments.
Another point of confusion is comma-separated lists and functions that return multiple outputs. Example:
>> [mx,idx] = max(magic(3))
mx =
8 9 7
idx =
1 3 2
>> [mx,idx] = max(magic(3))(4) % now what?
Should we return the 4th element of each output variables from MAX, or 4th element from only the first output argument along with the full second output? What about when the function returns outputs of different sizes?
All of this still applies to the other types of indexing: f()(3)/f(3), f().x/f.x, f(){3}/f{3}.
Because of this, MathWorks decided avoid all the above confusion and simply not allow directly indexing into results. Unfortunately they limited the syntax in the process. Octave for example has no such restriction (you can write magic(4)(1,2)), but then again the new OOP system is still in the process of being developed, so I don't know how Octave deals with such cases.
For those interested, this reminds me of another similar bug with regards to packages and classes and directly indexing to get a property. The results were different whether you called it from the command prompt, from a script, or from a M-file function...

New to programming, don't get 2D/3D arrays

Hey everyone, I'm basically new to programming. I've decided to try and get started with C (not C++ or C#) and so far I've been doing pretty well. I managed to get far as two-dimensional arrays before I started to falter. While I think I broadly understand 2D integer arrays, I certainly don't understand 3D string arrays.
I'm learning by taking the techniques and applying them in an actual program I've created, an exchange rate "calculator" that basically takes asks the user to select a base currency then prints its value in USD. There's no maths involved, I simply googled stuff like EUR/USD and set the values manually in the array which I discuss below.
But here's where I'm getting stuck. I figure the best way to learn multi-dimensional arrays is to practically apply the theory, so here's what I've typed so far (I've omitted the other functions of my program (including the code which calls this function) for brevity):
char currencies[5][3][4] = {
{'1','2','3','4','5'},
{'GBP','EUR','JPY','CAD','AUD'},
{'1.5','1.23','0.11','0.96','0.87'}
};
int point, symbol, value;
displayarraycontents()
{
for(point=1;point<5;point++){
for(symbol=1;symbol<5;symbol++){
for(value=1;symbol<5;symbol++)
printf("%s ", currencies[point][symbol][value]);
printf("\n");
}}
}
Because C doesn't feature a string data type, building string arrays completely messes with my head.
Why currencies[5][3][4]? Because I'm storing a total of 5 currencies, each marked by a 3-letter symbol (eg EUR, CAD), which have a value of up to 4 digits, including the decimal point.
I'm trying to display this list:
1 GBP 1.5
2 EUR 1.23
3 JPY 0.11
4 CAD 0.96
5 AUD 0.87
When I click build, the line where I specify the values in the array is highlighted with several instances of this warning:
warning: overflow in implicit constant conversion
...and the line where I print the contents of the array is highlighted with this warning:
warning: format '%s' expects type 'char *', but argument 2 has type 'int'
Upon running the code, the rest of the program works fine except this function, which produces a "segmentation error" or somesuch.
Could somebody give me a hand here? Any help would be greatly appreciated, as well as any links to simple C 2D/3D string array initialisation tutorials! (my two books, the K&R and Teach Yourself C only provide vague examples that aren't relevant)
Thanks in advance!
-Ryan
EDIT: updated code using struct:
struct currency {
char symbol[4];
float value[5];
};
void displayarraycontents(){
int index;
struct currency currencies[] {
{"GBP", 1.50},
{"EUR", 1.23},
{"JPY", 0.11},
{"CAD", 0.96},
{"AUD", 0.87},};
}
I get the following errors:
main.c:99: error: nested functions are disabled, use -fnested-functions to re-enable
main.c:99: error: expected '=', ',', ';', 'asm' or 'attribute' before '{' token
main.c:100: error: expected ';' before '}' token
main.c:100: error: expected expression before ',' token
In the actual code window itself, every symbol is flagged as an "unexpected token".
In this case, you don't actually want a 3D array. In fact, since you have a table of values, all you need is a 1D array.
The tricky part is that each element of the array needs to store two things: the currency symbol, and the associated exchange rate. C has a way of building a type that stores two things - it's the struct mechanism. We can define a struct to hold a single currency:
struct currency {
char symbol[4];
char value[5];
};
(Note that this does not create a variable; it creates a type. struct currency is analagous to char, except that we defined the meaning of the former ourselves).
...and we can now create an array of 5 of these:
struct currency currencies[5] = {
{"GBP", "1.5" },
{"EUR", "1.23" },
{"JPY", "0.11" },
{"CAD", "0.96" },
{"AUD", "0.87" } };
To iterate over them and print them out, the code would look like:
void displayarraycontents(void)
{
int point;
for(point = 0; point < 5; point++)
{
printf("%d %s %s\n", point + 1, currencies[point].symbol, currencies[point].value);
}
}
You need a to correct your array dimensions, and you also need to declare your strings as strings, not as multibyte character constants:
char currencies[3][5][5] = {
{"1","2","3","4","5"},
{"GBP","EUR","JPY","CAD","AUD"},
{"1.5","1.23","0.11","0.96","0.87"}
};
Your logic for the array dimensions is wrong - what you want is 3 columns, each with 5 entries, each of which is a string 5 bytes long.
Your for loop should index from 0, not from 1.
There is also a oops in for statements:
for(point=1;point<5;point++)
First item in an array is in 0 position, so for statements should be like this:
for(point=0;point<5;point++)
It would make more sense to use structs here rather than a multi-dimensional array.
#include <stdio.h>
typedef struct Currency {
const char* symbol;
double value;
} Currency;
Currency CURRENCIES[] = {
{"GBP", 1.5},
{"EUR", 1.23},
{"JPY", 0.11},
{"CAD", 0.96},
{"AUD", 0.87},
};
size_t NUM_CURRENCIES = sizeof(CURRENCIES) / sizeof(Currency);
int main()
{
size_t index;
for (index = 0; index < NUM_CURRENCIES; index++)
{
printf("%zu %s %.2f\n",
index + 1, CURRENCIES[index].symbol, CURRENCIES[index].value);
}
return 0;
}
It should be
char currencies[3][5][5] = {
because it contains 3 lists containing 5 strings each.
Each string has a max of 4 characters, but you need the additional NUL character, so 5 at the end.
-- EDIT
You have the array access confused. Using your array definition (fixed as above) it would be currencies[data_type][index] to get a string.
data_type = 0 -> the index
data_type = 1 -> the symbol
data_type = 2 -> the value
the first line
{'1','2','3','4','5'},
is redundant.
Fixed code:
char currencies[2][5][5] = {
{"GBP","EUR","JPY","CAD","AUD"},
{"1.5","1.23","0.11","0.96","0.87"}
};
void displayarraycontents()
{
int index;
for(index = 0;index < 5;index++) {
printf("%i %s %s\n", index, currencies[0][index], currencies[1][index]);
}
}
In C/C++ you would normally read your array dimentions from right to left to get a good idea of how the compiler will see it. In this case, you need to store strings of 4 characters each which requires storage for 5 chars (to include the trailing \0) therefore [5] will be the array size. Next you are storing groups of 5 items, therefore the middle value will be [5] and finally, you are storing a total of 3 groups of these items, therefore [3]. The final result of all of this is char currencies[3][5][5] = . . .;
Of course, as replied elsewhere, you need to use the double quotes for string values.
If you want to solve this with multi-dimensional arrays, as #Forrest says, you need [3][5][5]. Look at it this way: in the initializer, find the outermost braces: inside that, on the top level, how many elements are there? 3. Now, each of these elements (one level in), how many elements? 5. Drilling further down, inside each of those, you have a string of 4 elements, plus one for the terminator, again 5.
Second error: you can only ever have one character in single quotes, like 'a'; that's char type, and equivalent to ASCII code (97 in this case). For strings, you have to use double quotes ("abc", which is equivalent to {97, 98, 99, 0}).
Third error: loops. You are not actually iterating over all three loops while printing a string at a time (since printf will actually do one of the loops for you) - so you should only have 2 loops (or, less efficiently, you can keep all three loops, but then print only a character at a time). Also, you need to be aware of the loop limits; you are going up to 5 in each case, but this will give you runtime garbage (in the best case) or runtime crash (in the worst case) when you go out of your [3] dimension. Thus, something like this:
Then again, your innermost loop is inconsistent in your variable usage (copy-paste error).
However, there will almost never be need to write code like this. You mainly use 2D arrays for matrix operations. Something like this should only have a one-dimensional array, storing record elements.
struct currency {
int id;
char[4] symbol;
float value;
} currencies[5];
You don't need to store the indices (1-5) as you can access the array (0-4) and thus know the indices. You can encapsulate the other values in a struct or two seperate arrays which gets your array(s) down to one dimension as it should be... In that way the items have proper types and you don't misuse two-dimensional arrays.
A 2D or 3D area shouldn't be filled with items that should be of a different type, it is needed when you have items that are of the same type and have a logic 2D or 3D structure. The pixels on your screen are a good example of something that needs a 2D structure, coordinates in a 3D graph are a good example of something that needs a 3D structure.

Resources