I declared a table of unsigned char as follow:
unsigned char buf[10]={'1','5',0x00,'8'};
in order to know the number of elements of this table i implemented this function
int tablength(unsigned char *buf)
{
int i=0;
for (i=0;buf[i];i++)
;
return i;
}
However this function don't give me the right result when the buffer contains 0 in the middle .Sizeof don't give me the right result since it returns 10 in this case i can't neither use strlen since this is a table of unsigned char.
Do you have any idea to improve this function or any predefined function that help me solve my problem (the result that i 'am waiting for is 4)
Technically, since you declared a statically allocated array of 10 elements, the size of the array is 10. Even though you may not have initialized every element, there is something filling that space. C++ cannot determine whether the value in the array means anything or not.
After
unsigned char x[10] = {1, 2, 3};
the variable x (an array) has 10 elements, the first three initialized to 1, 2 and 3 and all the others initialized to 0. In other words that definition is absolutely identical to
unsigned char x[10] = {1, 2, 3, 0, 0, 0, 0, 0, 0, 0};
An array in C and C++ is just a fixed area of memory and doesn't include a counter of how many "interesting" elements are there.
If you are looking for a container with a variable number of elements consider instead std::vector (C++ only). With that std::vector::size() returns the current number of elements in the container.
If you need the array to contain exactly the number of elements you've specified, just declare it without a specific size:
unsigned char buf[]={'1','5',0x00,'8'};
cout << sizeof(buf); // should be 4
If you want to store a variable amount of data (in C++) use std::vector instead of an array.
Otherwise you'll need to keep track of the number of valid elements yourself. There's nothing in the language that will do it for you.
Compilers cannot know how you would like to use an array instance.
Therefore you must follow the language's semantics. By declaring your array globally or locally, but with the storage class specifier static you are initializing every element to 0 on default and your function will work.
0x00 is false. 0x00 (which same as 0x0) is a hex number representing 0 (false). This is where your counting loop will stop at - the 3rd element.
Another thing you can do is declare your array with non-fixed size.
unsigned char buf[]={'1','5',0x00,'8'};
In that case, the sizeof operator works as expected.
Because that way, you will have an array of 4 elements.
strlen() obviously won't work as it is designed to work with strings, not a buffer.
As for a function that counts on a smarter way:
size_t arrcnt (unsigned char source[], size_t size)
{
size_t i;
for(i = size; i >= 0 && !source[i]; i--);
return i + 1;
}
Usage:
printf("size of buf: %u", arrcnt(buf, sizeof(buf));
buf[i] evaluates to false when buf[i] contains 0.
You cannot do what you want unless you know one value which can never occur in your array between 0 to UCHAR_MAX (255). Say the value is 255, then you first preinitialize the full array to 255 before you start filling it up.
memset(buf, 255, sizeof(char) * sizeof(buf));
Then you fill other elements like you want and then you can use the following
for(i = 0; buf[i] != 255, ++i)
try putting :
for(int i=0;buf[i]!= 0;i++)
count++;
return count;
Related
I'm trying to make an array which have it's element coming from a user input. This array would first have it's size undefined since we don't know how much int would the user input, but then I'm not able to find the amount of element in the array like this unless I put a counter on the loop function.
Here is the code that I've made:
int cross[] = {0};
int k;
for (k = 0; k >= 0; k++){
scanf("%d", &cross[k]);
if (cross[k] == -1){
break; //stop the user from inputing numbers if user input -1
}
int p = sizeof(cross) / sizeof(cross[0]);
If I were to do printf("%d", p), it would always give me 1 as a result. I'm wondering if there is any other way of doing this other than putting a counter on the for loop.
Thanks!!
This phrase from your question is both wrong and dangerous: "This array would first have it's size undefined".
The following line of code defines a fixed-size array that has exactly one element:
int cross[] = {0};
The compiler knows it's one element because you supplied one initializer value {0}. If you supplied this {0, 5, 2}, it would allocate 3 integers, and so on.
This means when you store into cross[k] and k is larger than zero, you're actually exceeding the bounds of your allocated array, which C doesn't catch at compile time, but could cause nasty problems at run time.
I'm having trouble with the following: I want to take a large number (cca. 15-digit) and turn it into individual digits and store them in an array. I will need these digits further on in the code. The problem is, if I declare the array outside the while loop, it stores the first four values, but then I get a segmentation fault. If I declare it within the loop, the code works as I want it to, but then I don't know how to move the array out of that loop, so that I could use it further. How can I solve this? This is what I've compiled:
unsigned long long card_num;
printf("Enter your credit card number:\n");
scanf("%llu", &card_num);
int count = 0;
while (card_num != 0)
{
int digits[count]; //declaring array into which digits will be stored
digits[count] = card_num%10; // get last digit, store it in array
card_num = card_num/10; //remove last digit
printf("Digit[%i] = %i\n", count, digits[count]);
printf("Number of digits: %i\n", count);
count ++;
}
In your code, for the very first iteration
int digits[count];
count is 0, which violates the constraints mentioned in spec. As per C11, chapter 6.7.5.2,
In addition to optional type qualifiers and the keyword static, the [ and ] may delimit an expression or *. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero. [....]
and
If the size is an expression that is not an integer constant expression: if it occurs in a declaration at function prototype scope, it is treated as if it were replaced by *; otherwise, each time it is evaluated it shall have a value greater than zero
So, this is not a valid code.
As already mentioned, what you are doing is plain wrong.
There is several ways to solve this issue. The easiest would be to allocate an array at the beginning of your program with enough space for all your usecases with something like :
#define MAX_DIGIT 50
int digits[MAX_DIGIT];
Then you just have to check you are not going over this array by checking that count < MAX_DIGIT.
Another way would be using dynamic memory allocation using an int pointer int *digits and malloc (I let you google that) once you know the size of the array you'll need. You'll have to change a bit your code to know the number of digits before starting to get the digits as you need to allocate the memory before starting to store digits.
You could use realloc to keep a code similar to what you already have, but I wouldn't advise it as it is not efficient to realloc memory for each value that you add.
Your logic is fine.
What went wrong is that you tried to increase the length of a fixed-length array while iterating which is not allowed.
You should never change the length of a fixed-length array anywhere in the program.
However if you want to change the length of an array during runtime you must use the malloc and realloc functions to do so.
Check out this example:
//declarations
int *storeNum;
storeNum = (int *)malloc(1 * sizeof(int));
//logic
while(num != 0) {
if(i > 0)
storeNum = realloc(storeNum, (i+1) * sizeof(int));
storeNum[i] = num % 10;
num = num/10;
++i;
}
Here first I declared the array size initially as one and later incremented it using realloc function.
You also have the array size stored in i which you can use later in your code in loops.
But keep in mind that the digits will be stored in your array in reverse order.
Also, you shouldn't declare an array within a loop.
Since you have "declared" the array, each time the compiler enters the loop while iterating it will consider the array-declaration as a new array. That is all.
I'm trying to convert a decimal value into a string. I use the STM32CubeIDE IDE but am getting an error like 'Invalid binary operator'. I'm able to set &n to the decimal value 3695. I need to convert that into a string. How would I do that?
void main()
{
uint8_t TxArr;
uint16_t Data;
int a[10];
int i;
while (1)
{
HAL_I2C_Master_Transmit(&hi2c1,0x16, &TxArr, 1, 1000);
HAL_I2C_Master_Receive(&hi2c1, 0x17, &Data, 2, 1000);
for(i=0;i<4;i++)
{
a[i]=Data%10+0x30; //value in Data is 3695.
Data=Data/10;
HAL_UART_Transmit(&huart3, a[i], 11, 100);
HAL_Delay(300);
}
}
The error is produced by:
n = n / 10;
What this would do if n was a pointer (int* n) is that it would repoint n to a location one tenth the original number. You will need to begin using normal array operators if you want your code to work properly.
The second problem you have is the following:
You declare n as a array of 10 integers of type and with int.
int n[10];
Then in your for loop you try to do this:
n > 0;
This is an invalid operation as n wil decay into a pointer and as such the address of your array is compared to 0. This will always evaluate as TRUE!
A good way to convert a integer to a string (char array) is this answer.
In your sitaution that would be
int yourToBeConvertedNumber;
char str[INT_MAX]; // or any other reasonable upper bound you have set for the input data.
snprintf(str, sizeof(str), "%d", yourToBeConvertedNumber);
Generally speaking, to convert an integer to a string, you can use the sprintf function. It should be available in newliband even newlib-nano standard C libraries.
However my guess here is that you have an array of integers where each element is a number between 0 and 9 ?
If this is true you have several issues: you seem to handle the variable n like an integer and not an address. Also your string should be one element longer and composed of chars.
You may do something like this:
char a[11];
for(i=0;i<10;i++)
{
a[i]=n[i]%10 +'0';
}
a[11]='\0';
Using a global variable like:
params_vector[100][100] = {};
Is it possible to 'reset' or 'clear' the values inside this array just to be equal as from when it's initialized? There are a lot of examples with char *arg[] (which arg[i] = NULL works) but none with a 'matrix' like this.
If this is a multidimensional array of char, you can "reset" it simply by calling
#include <string.h>
memset(params_vector, 0, sizeof params_vector);
If you just need to set the first byte of each string to 0, using a for loop could be more efficient.
Assuming this is a multidimensional array of char's, e.g.
char params_vector[N][M];
for some value of N and M - you don't need to memset() the entire thing to '\0'; it's enough to set the first character of each string to '\0':
for(size_t i = 0; i < N; i++) {
params_vector[i][0] = '\0';
}
However, if N is small, this optimization might not be worth it and a
memset(params_vector, '\0', M * N);
would be fine.
Use memset:
memset(params_vector, 0, sizeof(params_vector));
Note I'm using C not C++. I'm working on a program that will take a 2d-array and count the numbers of non-spaces in a subarray. Such as lines[0][i] <-- iterating over line[0][0] - line[0][n]. However, I'm having difficulty getting the function to accept the 2d-array.
Here is my code:
pScore[0]=letters(pLines, 0);
This is the actual function. pScore[] is another array, but a 1d one. pLines is a 4 by 200 2d-array.
int letters(char line[][], int row)
{
int i = 0;
int n = n;
int results = 0;
for( i = 0; i < (sizeof(line)/sizeof(line[0])); i++ )
{
if( !isspace(line[row][i]) )
results++;
}
return results;
}
When I do this it gives me "formal parameter number 1 is not complete". If I remove the second [] from it, the code runs but gives the worng number of non-space characters.
Taking from the comments above, and your function parameter list:
int letters(char line[][], int row)
You violate one primary tenant of passing a 2D array to a function. Specifically, you must always provide the number of columns contained in the array. e.g.
int letters(char line[][5], int row)
char line[][5] is an appropriate parameter. However, whenever you pass an array as a function parameter, the first level of indirection is converted to a pointer. (you will often here this referred to as "pointer-decay", though that is a bit of a misnomer). Therefore a proper declaration that makes this clear is:
int letters(char (*line)[5], int row)
line, after conversion, is a pointer-to-an-array of 5-int. While you can pass the array as line[][5], that is not nearly as informative as (*line)[5]. Let me know if you have any questions.
Numbers Instead of Characters
It is hard to tell what is going on without seeing the remainder of your code. However, I suspect that you are confusing the numerical value and the ASCII character value for the contents of your array. (e.g. character '0' = decimal 48 (0x30 (hex), '1' = 49, 'a' = 97, etc..). See ASCIItable.com
You you pass an array to a function it decays to a pointer. That means char line[][] should really by char (*line)[SIZE_OF_SECOND_ARRAY].
It also means the sizeof trick will not work, as doing sizeof on the pointer line will just return the size of the pointer and not what it points to, you need to explicitly pass the size as an argument to the function.
You need tell function the number of columns of 2d array. Here may help you.
I am not sure if the following statement works with you
for( i = 0; i < (sizeof(line)/sizeof(line[0])); i++ )
where sizeof(line) will be 4 or something like that depends on your platform because "line" is a pointer and you get the size of pointer itself.
Correct me if I am wrong.
In this case, you should pass column number as row's.