I got stuck in a univ project as follows:
I was doing it before I knew the format of the input, so I started reading it with %s, and it was a char[32].
Then when the project was released, I realized I needed to read the input as int.
So now I started to read it as int and now I don't want to make again all other functions I made, and they are receiving the arguments as an array of chars (char[32]).
So I made a function to convert the int value to int*, because I can't return char[32]. Hence I did, on main, a simple for to pass the values in int* to char[32]. The problem is that, when I print it on main, I see exactly the same values, but when I pass this new char[32] to my functions, I get a bug now. I guess my problem is because of '\0' or something like this.
A simple demonstration is below:
int* convert_dec_to_bin(int n){
printf("\n");
int i, j, k;
int *bits;
bits = (char*)malloc(32*sizeof(int));
for(i = 31, j = 0; i >= 0; --i){
printf("%d", n & 1 << i ? 1 : 0);
if(n & 1 << i){
bits[j] = 1;
}else{
bits[j] = 0;
}
j++;
}
printf("\n");
return bits;
}
int main(){
int i, k, instructionNameInt;
char type;
int *bits;
char bitsC[32];
//char instructionBinary[32]; I was reading like this before, ignore this line
int instructionBinary; //Now I read like this
scanf("%d", &instructionBinary);
bits = convert_dec_to_bin(instructionBinary); //This is a function where I pass the int decimal input to 32 bits in binary as int*.
//Making probably the wrong conversion here, I tried to put '\0' in the end but somehow I failed
for(k = 0; k < 32; k++){
bitsC[k] = bits[k];
}
printf("\n");
type = determine_InstructionType(bitsC);
printf("TYPE: %c\n", type);
instructionNameInt = determine_InstructionName(bitsC, type);
And several other functions...
Can someone light me up how can I fix it? I spent several hours and still didn't achieve to pass this correctly to an array of chars.
Related
I want to pass a 2D array already filled with chars to a different method to do something with it.
Background: I am trying to implement GameOfLife. And I have already successfully implement the gameboard with a random amount of living cells. But now I want to pass the board(Array) to a different method to continue working with it. How to do so?
//wow das wird hurenshon
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
void spielStarten(int x, int amountOfLiving){
char feld[x][x];
for(int i = 0; i < x; i++){
for(int j = 0; j < x; j++){
feld[i][j] = 'o';
}
}
for(int i = 0; i < amountOfLiving; i++){
int a = (rand()%x);
int b = (rand()%x);
feld[a][b] = 'x';
}
printf("Gameboard: \n");
for(int i = 0; i < x; i++){
for(int j = 0; j < x; j++){
printf("%c ", feld[i][j]);
}
printf("\n");
}
spielRun(feld);
}
void spielRun(char feld[][]){
int neighbCount;
char feldNew[][] = feld[][];
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
checkForNeighbours(feld[x][y]);
// in progress
}
}
}
int main(int argc, char* argv[]){
srand(time(NULL));
int x = 16;
if(argc < 2 || argc > 3){
printf("2. Argument eine Zahl fuer Feldgroesse eingeben\n");
printf("1. Argument eine Zahl 0-10 fuer ungefähre prozentuale Belegung mit lebenden
Zellen eingeben \n");
return 0;
}
if(argv[2] != NULL){
x = atoi(argv[2]);
}
int i;
i = atoi(argv[1]);
i = (x^2)*(0,1*i);
spielStarten (x,i);
return 0;
}
In the last line of the Method "Spiel starten" i want to give the array to the next Method "spielRun".
Edit: thanks to an other user I found this struture:
void printarray( char (*array)[50], int SIZE )
But it doesn't work for me since I can´t hardcode the number, because the arraysize depends on a user input.
thanks!
The difficulty here is that the size of your array is not known statically (once upon a time, your code would even not compile for the same reason).
That, combined with the fact that 2D-arrays are not arrays of 1D arrays (contrarily to what happen when you malloc a int ** and then every int * in it), and so it doesn't make sense not to specify the size when passing it to a function.
When using arrays of arrays (technically, pointers to a bunch of pointers to ints), like this
void f(int **a){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int **t=malloc(10*sizeof(int *));
for(int i=0; i<10; i++) t[i]=malloc(20*sizeof(int));
f(t);
}
That code is useless, it prints only unitialized values. But point is, f understands what values it is supposed to print. Pointers arithmetics tells it what a[1] is, and then what a[1][0] is.
But if this 2D-array is not pointers to pointers, but real arrays, like this
void f(int a[][20]){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int t[10][20];
f(t);
}
Then, it is essential that the called function knows the size (or at least all sizes, but for the first dimension) of the array. Because it is not pointers to pointers. It is an area of 200 ints. The compiler needs to know the shape to deduce that t[5][3] is the 5×20+3=103th int at address t.
So, that is roughly what is (better) explained in the link that was given in comments: you need to specify the size.
Like I did here.
Now, in your case, it is more complicated, because you don't know (statically) the size.
So three methods. You could switch to pointers to pointers. You could cast your array into a char * and then do the index computation yourself (x*i+j). Or with modern enough C, you can just pass the size, and then use it, even in parameters, declaration
void f(int x, int a[][x]){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int t[10][20];
f(t);
}
Anyway, from an applicative point of view (or just to avoid segfault) you need to know the size. So you would have had to pass it. So why not pass it as first parameter (Note that the function in which you have this size problem, spielRun, does refers to a x, which it doesn't know. So, passing the size x would have been your next problem anyway)
So, spielRun could look like this (not commenting in other errors it contains)
void spielRun(int x, char feld[][x]){
int neighbCount;
char feldNew[][] = feld[][]; // Other error
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
checkForNeighbours(feld[i][j]); // Corrected one here
// in progress
}
}
}
And then calls to this spielRun could be
spielRun(x, feld);
Note that I address only the passing of array of size x here. There are plenty of other errors, and, anyway, it is obviously not a finished code. For example, you can't neither declare a double array char newFeld[][] = oldFeld[][]; nor affect it that way. You need to explicitly copy that yourself, and to specify size (which you can do, if you pass it).
I am also pretty sure that i = (x^2)*(0,1*i); does not remotely what you expect it to do.
Right now I have a u8 array that I successfully converted to a hexidecimal char array. Now, trying to change it back into a u8 array has been a doozy. I tried this code:
// DEMO:
char *message = "0f236a1f";
int i;
u8 final[4];
memset(final, 0, 4);
char* part = "00";
for (i = 0; i < 4; i++)
{
memcpy(part, &message[i*2], 2);
u8 num = 0;
sscanf(part, "%x", &num);
printf("%i", num);
final[i] = num;
}
I prepopulate everything with values to prevent stay memory values from messing up large portions of zeros I have in my actual data. Despite everything I have tried, occasionally the wrong values are assigned, and I can't find any other method online which does the same thing. Help me if you can, I hate C.
EDIT:
I revised my code, and am showing the real thing now, to see if it helps. The variable message is 464 zeros in a giant char * array. The console is still occasionally printing numbers besides zero, not sure why:
int i;
u8 final[232];
memset(final, 0, 232);
char part[3] = "00";
part[2] = 0;
for (i = 0; i < 232; i++)
{
memcpy(part, &message[i*2], 2);
unsigned int num = 0;
sscanf(part, "%x", &num);
printf("%i", num);
final[i] = (u8)num;
}
You are creating undefined behavior with these lines:
char* part = "00";
for (i = 0; i < 4; i++)
{
memcpy(part, &message[i*2], 2);
...
sscanf(part, "%x", &num);
part points to read only memory (this is why with strings like this we usually declare them as const char* to cause a compiler error when modification attempts occur) More info here.
You should allocate enough space for your string and null terminator with:
char part[3] = "00";
can someone please help me figure out what i'm doing wrong here? i'm getting inaccurate results here. I seem to be getting the first value in the array each time and i cant seem to figure out what i'm doing incorrectly
#include <stdio.h>
int getbillsum ( int price[] );
int main( void )
{
int itemprice [10];
int total = 0;
for (int c=0;c <10;c++ ) //Looping to get item prices
{
printf ("\nEnter the price of the item: ");
scanf (" %d", &itemprice[c]);
}
total = getbillsum (itemprice);
printf ("%d", total);
return 0;
}
int getbillsum (int price []) //function to sum the values in array
{
int sum = 0;
for (int i=0; i<sizeof(price); i++)
{
sum+=price[i];
}
return sum;
}
You can't pass arrays to functions in C (well, not as an array anyway). Arrays decay into pointers, the sizeof which is always the same (4 for 32 bit systems, 8 for 64 bits).
For more information see paragraph 2.3 here.
The easiest, most common and most reliable way of solving your issue is to pass the length of the array as a second argument:
int getbillsum (int *price, size_t len)
{
int sum = 0;
for (int i=0; i<len; ++i)
sum += price[i];
return sum;
}
//usage
int main ( void )
{
int price[10];
for(int i=0;i<10;++i)
scanf(" %d", &price[i]);
printf("Sum: %d\n", getbillsum(price, sizeof(price)/sizeof(*price)));
return 0;
}
You also had a problem in your code: you added the return statement inside of your loop.
Just a quick-tip: The sum of an array of ints is not unlikely to be too much for a single int to hold, so I'd change the return-type of getbillsum to long, too
I've also edited your question, addressing quite a lot of issues considering how short your code was:
int getbillsum ( price );//missing type, changed to
int getbillsum ( int price[] );//better would be int getbillsum ( int *price ); but considering your question, left it as array
scanf ("%d", &itemprice[c]);//unsafe, changed it to
scanf (" %d", &itemprice[c]);//add space
total = getbillsum (itemprice,9);//why the second param?
total = getbillsum (itemprice);//to match function prototype
return sum;//moved OUTSIDE of the loop...
sizeof(price) does not give you the length of the array, but the size of the pointer (int price[]), which is probably 4. Also, you immediately return in the first for run. Put return outside the for loop.
You do fix it by supplying the array size, but you never use it. Update your getbillsum function:
int getbillsum (int price [], int length) //function to sum the values in array
{
int sum = 0;
for (int i=0; i<length; i++)
{
sum+=price[i];
}
return sum;
}
In addition to posted answers, you can consider a technique suggested in this answer.
Edit Quoted from comment
it's non-standard, dangerous (think of overflow, forgetting to
dereference at the correct offset and the like), and you should not
try this
In your case it will be something like that :
void *p = calloc(sizeof(itemprice) + sizeof(unsigned long int),1));
*((unsigned long int*)p) = 10;
quote from linked answer
n is now stored at ((unsigned long int)p)
Your getbillsum will look like that now (did not compile it, consider it as pseudocode)
int getbillsum (void* p)
{
int* price = p+sizeof(unsigned long int);
unsigned long int size = *p;
int sum = 0;
for (int i=0; i<size; i++)
{
sum+=price[i];
}
return sum;
}
Let's say I have a temperature in celsius, int tC, and I want to convert that to binary form, with each of the bits in a integer array, arr[5]. I tried to use the remainder by two method to check if the number has a remainder. I tried using this function, but it always seems to mess up, even though in theory it does work. Any help is appreciated. Also, I could use pointers, but am not too sure how to use them in this particular case.
int main(void)
{
int arr[5];
int tC = 39;
int i;
for(i=0; i<5; i++)
{
if(tC%2==0)
arr[i] = 0;
else
arr[i] = 1;
tC/=2;
}
printf("\n%d\n", arr[5]);
}
Just a little change required:
#include<stdio.h>
int main(void)
{
int arr[5];
int tC = 39;
int i;
for(i=4; i>=0; i--)
{
if(tC%2==0)
arr[i] = 0;
else
arr[i] = 1;
tC/=2;
}
for(i=0; i<5; i++)
printf("%d", arr[i]);
}
Since you are storing the binary values in an array and looping from 0-4 (<5) - the values are getting saved in reverse order. You just need to loop from 4-0 (0 included). Also, in printf you were printing the individual bit value stored in the arr[5] which is UB since the last index is 4 - also, you were not looping to print all bit values in your array.
I'm working with strings in C as character arrays, and I'm trying to ensure that I can dynamically pass values into my for loops.
The following code works, no problem:
for (int i = -6; i < 11; i++) {
int test = OverlapStrength(fragments[1], fragments[2], i, 0);
printf("%d\n", test);
}
In fact, this code works, too:
for (int i = -strlen(fragments[2]) + 1; i < 11; i++) {
int test = OverlapStrength(fragments[1], fragments[2], i, 0);
printf("%d\n", test);
}
But for some reason, this code doesn't print ANYTHING:
for (int i = -strlen(fragments[2]) + 1; i < strlen(fragments[1]); i++) {
int test = OverlapStrength(fragments[1], fragments[2], i, 0);
printf("%d\n", test);
}
I have checked the values for both -strlen(fragments[2]) + 1 and strlen(fragments[1]) just before the loop and they check out to -6 and 11 respectively. Clearly the loop works when I place those values directly into their places, but when I replace the second one with the strlen calculations, it breaks and I can't figure out why for the life of me. Help?
Edit
OverlapStrength takes its arguments as constants so I can't change them, so I'm pretty sure I'm not changing the fragments as I go. Here's the method declaration:
int OverlapStrength(const char one[], const char two[], int startOne, int startTwo)
The contents of the fragments shouldn't be important, but they're simply strings that I'm trying to piece back together from overlapping fragments. I have already checked that my fragments are all coming out properly and that their lengths are computed properly when done outside of declaring this loop.
strlen returns value of type size_t, which is probably a typedef for unsigned int for your case. Then you are comparing a signed int (i) and unsigned int (strlen(...)). C decides then to cast your signed value to an unsigned type (because of default type promotions). -6 converted to unsigned int is 4294967290, therefore your comparison is false, so the loop ends.
To fix this, you can for example cast strlen to a signed value, e.g.:
i < (int) strlen(fragments[1])
In a for-loop, the codition (the i < strlen(fragments[1]) part) gets evaluated on every iteration. If OverlapStrength changes the value of fragments[1] to something less than i, the loop will abort.
To fix this, use a constant:
int loopUntil = strlen(fragments[1]);
for (int i = -strlen(fragments[2]) + 1; i < loopUntil; i++) {
int test = OverlapStrength(fragments[1], fragments[2], i, 0);
printf("%d\n", test);
}