Several basic C questions - c

I am a person who is trying to learn C, but I got stuck at a few points while doing my projects:
1) How exactly can I implement random integer generation? I have Googled and found the code for 0 to x generation with the code below, yet how about between 2 integers that I decide (like between X and Y)?
int random;
random = random(100);
2) How can I set a variable to NULL in the beginning (like in Java) and manipulate it if it is NULL? For instance I want to achieve the following:
int a = null;
if (a == null){
a = 3;
}

1)
int r = random(Y - X) + X;
2)
Integers can't be null in either C or Java. In C only pointers can be null, represented by pointing them to zero. However, I suggest you don't get into the whole pointer mess before getting the basics down.

1- How exactly can I implement a random integer generation [...]
See FAQ 13.15 and FAQ 13.16 -- the latter explicitly answers this question.
2- How can I set a variable null in the begining
For floats and integral types you assign them to the magic value 0. For pointers you can assign them to 0 (again) or the macro NULL.

To get the range you want (y-x) multiply each random numberby (y-x). To make them start at x and end at y add x to each number (already multiplied by (y-z)). Assume that y > x.
int i;
for (i = 0; i < NrOfNumers; i++)
{
randomNumberSequence[i] = randomNumberSequence[i]*(y-x) + x;
}

In C you often see the following:
int x = -1;
if (x == -1) { x = 3; } else { /* do nothing */ }
This assumes that the value type is actually unsigned or at least that -1 is not a valid value. You also can do:
#define UNINITIALIZED ((int8_t) -128) /* -128 has no inverse with 8-bit */
...
int8_t x = UNINITIALIZED;
if (x == UNINITIALIZED) { x = 3; } else { /* do nothing */ }

Related

How to sort strings without string.h library in C [duplicate]

This question already has answers here:
How to sort array of strings in ascending order in C
(6 answers)
Closed 2 months ago.
#include <stdio.h>
int main()
{
char * str[ ]={"C program", "Basic", "Foxbase+", "Fortran", "Pascal"};
int i,j;
char * temp;
int k;
for(i=0;i<4;i++)
{
k=i;
for(j=i+1;j<5;j++)
if(str[i] < str[j]) k=j;
temp=str[i]; str[i] = str[k]; str[k] = temp;
}
for(i=0;i<5;i++)
printf("%s\n",str[i]);
return 0;
}
I wanna sort the strings given above by the order of letter(ASCII), but I just couldn't do it, I already know that the wrong part of this code is the
if(str[i] < str[j]) k=j;
And I tried to fix it many times, just doesn't work out.
I already tried:
*str[i] < *str[j] (didn't work, which I think is reasonable?)
Btw, using string.h is not allowed, how can I make everything right here?
EDIT: sorry I posted this question that is silly, I didn't know that even if I couldn't use string.h, I can also use stdlib.h to use strcmp function, I was confused at that time but now everything is clear. Thanks for you guys spending time here, I appreciate it, and sorry again for asking this silly question.
As arising from the comments to the question you are not allowed to use any library functions – thus you need to compare those strings manually (note that you cannot just compare the pointers, these might be arbitrary addresses, you need to compare what the strings point to!) – and as you even don't seem to be allowed to write a separate function you need to inline this code as well.
In general string comparison might look as follows (here still as a function):
int cmp(char const* x, char const* y)
{
for(; *x && *y; ++x, ++y)
{
if(*x != *y)
// first position where the strings differ:
// x < y lexicographically if *x < *y, thus *x - *y < 0
// x > y analogously, so:
return *x - *y;
// this gives you the equivalence: x # y <=> cmp(x, y) # 0
// with # being any comparison operator
}
#if 0
if(*x)
return 1; // x is longer, thus x > y
if(*y)
return -1; // y is longer, thus x < y
return 0; // both equal
#else
// actually, as the null terminator is smaller than any other character
// anyway, we still can simply:
return *x - *y;
#endif
}
Edit: An even simpler solution (thanks #Lundin for the hint) just iterates as long as the strings yet can be equal:
while(*x && *x == *y) // covers *y being 0, too!
{
++x; ++y;
}
return *x - *y;
Side note: There's an issue with the comparison if your strings include values in the upper half of the character range (from 128 up to 255 inclusive; not an issue with your example): It is unspecified if raw char is signed or unsigned – which makes a difference on comparing characters not residing in the same half of the range of char (200 - 100 = 100 > 0 <-> -56 - 100 = -156 < 0). You can achieve more consistent behaviour over different platforms if you cast to unsigned char at any difference or comparison (above and below):
return static_cast<unsigned char>(*x) - static_cast<unsigned char>(*y);
Using such a function is, in general, the solution to prefer. Maybe you ask once more if you are allowed to write a new function after all!
Otherwise in your case you could reduce the code for testing on being smaller only, so:
char const* cur = str[j];
char const* min = str[k];
while(*cur && *cur == *min)
{
++cur; ++min;
}
if(*cur < *min)
{
// cur is lexicographically smaller or shorter than min!
// -> found a new minimum
k = j;
}
Rather than compare pointers with
if(str[i] < str[j]) // Compare pointers
code need to compare the strings refenced by those pointers.
if (strcmp(str[i], str[j])) // Compare strings
As OP is obliged to not use strcmp(), make your own by comparing the strings, one character at a time (as unsigned char) for equality (and not a null character). Report zero when the same or a negative or positive corresponding to the sign of the difference.
// Use const to allow for pointers to const strings.
int my_strcmp(const char *x, const char *y) {
// Convert to unsigned char * as `strcmp()` compares "as if"
// the characters were all unsigned.
const unsigned char *ux = (const unsigned char*) x;
const unsigned char *uy = (const unsigned char*) y;
// Test for equality and null character.
// I like to place the more likely to fail one first.
while ((*ux == *uy) && *ux) {
ux++;
uy++;
}
// On rare machines, using `return *ux - *uy` may overflow.
// To avoid overflow, use 2 tests.
// Good compilers see this idiom and emit efferent code.
return (*ux > *uy) - (*ux < *uy);
}

Division of two values from array always return 0

I have this function that is suppouse to return a number that should be or 1 or 2 or 4, but when the division happens, the variable duracion always get the value 0 as result. I have tried a lot of changes but no one was the solution.
// Converts a fraction formatted as X/Y to eighths
int duration(char* fraction)
{
// TODO
if (strlen(fraction) == 3)
{
// Asignacion de los caracteres de la fraccion a un array para
convertirlos en numeros despues.
int a = atoi(&fraction[0]);
int b = atoi(&fraction[2]);
// Busqueda de errores ---------------------------------------
if ((fraction[0] != '1') && (fraction[0] != '3'))
{
fprintf(stderr, "octave most be formated as X/Y, where X
can't be greater than 8\n");
return 1;
}
else if (fraction[1] != '/')
{
fprintf(stderr, "octave most be formated as X/Y\n");
return 1;
}
else if ((fraction[2] % 2 != 0) || (fraction[2] < 0))
{
fprintf(stderr, "octave most be formated as X/Y, where Y
most be a positive pair number\n");
return 1;
}
// Fin de busqueda de errores -------------------------------
float duracion = (a / b) * 8;
return duracion;
}
else
{
fprintf(stderr, "Note lenght most be formated as X/Y\n");
return 1;
}
}
While there are several problems with this code, I'll first answer your immediate question.
Your problem lies in the line
float duracion = (a / b) * 8;
From your code I can see that you assume a < b. This means that: a / b < 1.
Since a and b are ints, you are performing an integer division, and this means that the integer result of your division is always truncated to zero.
Here is one possible solution (not sure this is what you actually want, though):
return (8.0 * a / b);
Here is another (maybe this is what your actually need?):
return b / a;
Now some general remarks (assuming your using C99).
Your question title states "Division of two values from array always return 0" when, in fact, these are values from a string.
But this is irrelevant since if you would just say "Division of two integer values always return 0" then you would have Google find the answer for you.
If you assume that both parts of the fraction are always a single ASCII character, you could just write:
int a = fraction[0] - '0';
int b = fraction[2] - '0';
If this is not the assumption then using "sscanf" is preferred, since it will handle most your use cases, even fractions like "-16/8".
int a,b;
int ret = sscanf(fraction,"%d / %d", &a, &b);
Also note that this line is just wrong and will not work the way you want:
else if ((fraction[2] % 2 != 0) || (fraction[2] < 0))
In general, you should perform all check on the values "a" and "b" and not on the string.
Also it is customary to try and accept any input that looks valid and not restricting your user to some over-specified pattern. So you should not limit the length of the string to 3, and you should allow spaces between the elements.
In addition, unless this is your intent, and that should be clearly marked, you should not return a valid reply, "1" in your case, when an error was detected.
Select a number like "-1" or, better yet, define an enumeration of negative values and return the specific error, instead of printing it inside the function.
P.S.
A note duration more than the base is perfectly legal in music. So things like 16/8 are usually OK. But this is a musical theory and not a programming question.
The isssue is that both a and b are int. So it is performing int division.
Try casting to float as (float)a/b * 8
Or you can use atof instead of atoi and declare a and b as float
Just this:
float duracion = (a / b) * 8;
Modify:
float duracion = (a * 1.0 / b) * 8;
Try it

Why this value is changing?

I've just started learning C language. so I was doing some exercises and I had a problem with this one.
The code:
#include <stdio.h>
#include <math.h>
main()
{
double l[2];
double s, v, d;
int i;
for (i = 0; i < 3 && l[i] >= 0; i++)
{
scanf("%lf", &l[i]);
if ( l[i] < 0)
{
printf("Please type a positive value\n");
l[i+1]=-1;
}
}
if (l[0] >= 0 && l[1] >= 0 && l[2] >= 0)
{
s = 2 * ((l[0] * l[1]) + (l[0] * l[2]) + (l[1] * l[2]));
v = l[0] * l[1] * l[2];
d = sqrt(pow(l[0],2)+pow(l[1],2)+pow(l[2],2));
printf("%.2f\n%.2f\n%.2f\n", s, v, d);
}
}
The output gives right value for "s", but it changes l[2] value after "s" is stored, consequently it gives me wrong values for "v" and "d". I dont understand why l[2] is changing, anyone could help?
The definition
double l[2];
defines an array with space for 2 values of type double.
The array elements can be accessed with l[0] and l[1]. Accessing l[2] (as you are doing) is an error.
Accessing l[2] results in undefined behavior. Arrays in C are 0-indexed and l only contains two elements, i.e., l[0] and l[1]. Your loop should be:
for (i = 0; i < 2 && l[i] >= 0; i++)
And you should probably just store the size in a constant.
Your program invokes undefined behavior;
1. You are reading/writing to an unallocated memory location.
2. In your for loop you are reading uninitialized variable.
Yeah, the answer for why the value is changing would be that since the memory location at l[2] is not allocated to your program, it is probably allocated to some other program, which is changing it's value. Even when you are reading some stuff into it, some other program is trying to change it again.
Again, there is still a fair chance that the code would work fine if you are not running many processes. This is because, if the memory block containing l[2] is empty, it doesn't change over time.
However, accessing variables out of your scope is a bad practice and would give you errors in other compilers.
error is in accessing l[2]
if (l[0] >= 0 && l[1] >= 0 && l[2] >= 0)

Checking whether two pointers are in the same block of memory

This is a homework question that I am confused on how to approach. There are restrictions as well were I cannot use /, %, or any loops. Given a method, it accepts two pointers of type int. Taking these two pointer I need to find whether they are in the same block of memory or in different block of memory. If case one I return 1 for them being in the same block if and 0 otherwise. So my thinking is that if two pointers are in the same block of memory that must mean they point to the same integer? Im not sure if this is correct any hint in the right direction would be greatly appreciated.
Thank you
Floris basically gave you the idea; here's my actual implementation for POSIX:
uintptr_t pagesz = getpagesize();
uintptr_t addr_one = (uintptr_t)ptr1;
uintptr_t addr_two = (uintptr_t)ptr2;
bool in_same_page = (addr_one & ~(pagesz - 1)) == (addr_two & ~(pagesz - 1));
Assuming that you know how large the blocks of memory are (I assume 1k (2^10)) you can subtract the smaller address from the larger and see if the difference is less than the block size -1.
int same_block(int x, int y){
int difference;
if(x > y){
difference = x - y;
} else {
difference = y - x;
}
if(difference < 1024){
return 1;
}
return 0;
}

Passing 2d arrays and then not getting a value

I am having an issue with some code that I am writing.
I use this site often as I have found many people who have already asked the same questions I am wondering. With that I want to thank the community on here for all of the previous insight into my programming conundrums.
(And before we get too far, no this is not a 'school project' or 'school homework', I am simply trying to solve the 'Travelling Salesman Problem' and better my C skills.
This is the portion of code I have been stuck on:
void printAndFlip(int arrayone[][20], int citytotal, int arrayCities[])
{
////Finds cost:
int x, y, z;
int totalCost
int singleTrip;
int cheepestTrip;
int nCity = citytotal + 1; //nCity is the number of Cities //Adding one to accomadate going back to the first city
int gCounter;
int gCounterTrue = 1;
int cheepestTrip[20];
int totalCost = 0;
int lCounter;
int i;
int n = citytotal;
////Sets up for a default case to set cheepestTrip:
for(gCounter = 1; gCounter <= nCity; gCounter++)
{
while(gCounterTrue == 1)
{
if(gCounter == arrayCities[gCounter])
{
gCounterTrue = 1;
}
else
{
gCounterTrue = 0;
gCounter = 50; //Stopping the larger for loop with 50 (the nCity can't be larger than 20) so that it will hopefully be faster
}
if(gCounter == nCity)
{
if(arrayCities[1] == arrayCities[nCity])
{
!!!!! cheepestTrip = totalCost;
}
}
}
}
for(x = 1; x < nCity; x++)
{
y = arrayCities[x];
z = arrayCities[x+1];
singleTrip = arrayone[y][z]; //finding individual cost of each trip...will be added to 'totalCost' below
totalCost = singleTrip + totalCost;
}
!!!!!!!! if(totalCost <= cheepestTrip)
{
for(lCounter = 1; lCounter <= nCity; lCounter++)
{
cheepestTrip[lCounter] = arrayCities[lCounter];
}
}
To make it easier to show where my compile errors are at I put exclamation points on the lines.
Please tell me if I am wrong, but I am passing an array of pointers with an array when I send 'arrayone' to printANDFlip right?
I know the compile errors are relating to the pointers but I am just uncertain of where they should be placed.
Any and all help will be appreciated.
Much thanks,
Alex
To make explicit what some of the other replies are saying: You have two variables with the same name but different types:
int cheepestTrip; /* This is an single integer... */
and
int cheepestTrip[20]; /* ...but this is an array of integers. */
This should be triggering a warning at compile time (probably something about redeclaring an existing variable).
Here you are comparing an array pointer with a int value
if(totalCost <= cheepestTrip)
For example you should compare it to an element of that array
if(totalCost <= cheepestTrip[0])
cheepestTrip is the name of the array, which is equivalent to a pointer to the first element. totalCost is an int. Just remove the [20] from your declaration at the top part of the code.
you are comparing a pointer to an int, which your particular compiler might not be allowing (though I though with C you could). but cheapestTrip is essentially a pointer to the first element in your array of ints, while totalcost is simply an int primative

Resources