I'm writing a parser for propositional logic (doesn't matter what that is, main point is I'm parsing a simple language) and initially started out with functions of the following form:
int formula() {
int store = step;
if(compound())
return TRUE;
else {
if(atom())
return TRUE;
else if(negation() && formula())
return TRUE;
else {
step = store;
return FALSE;
}
}
}
int compound() {
int store = step;
if(open() && formula() && binary_operator() && formula() && close())
return TRUE;
else {
step = store;
return FALSE;
}
}
The functions above not mentioned are base cases - these are the important parts. Formulas can have sub-formulas, and these sub-formulas in turn can be compound formulas, which contain sub-formulas, and so on.
Instead of ints though, I'm trying to return char sequences of 1s and 0s (true and false). If you return a sequence, it means that the input can generate a sequence (it must be valid). Otherwise, return null.
The issue is that every time I've tried the pointers keep getting lost - I understand this is to do with the stack(?) and the pointer sort of 'dies' when the function returns whatever. I've not tried arrays because I have been told that arrays work best statically, whereas the size of these arrays would be dynamic (size is determined by number of variables, which is only found at runtime).
Is there any way this approach can be done? I can't malloc anything because I won't be able to free it - the sequence of 1s and 0s needs to be returned before I'd be able to free it. Maybe pass structs with a sequence field, although I'm not sure if that suffers from the same issue.
Any help much appreciated. This is a program using C99. Any advice on clarifications welcome!
I'm not entirely following what you want to do, but there is not a clear reason why you couldn't use malloc. The pointer returned by malloc can be freed by another function later. Consider the following valid code:
char* foo(size_t* length)
{
*length = 3;
char* seq = malloc(*length);
seq[0] = 1;
seq[1] = 0;
seq[2] = 1;
return seq;
}
int main()
{
size_t length;
char* seq = foo(&length);
/* use seq */
free(seq);
}
You can also do it without malloc if you know an upper bound for your sequence. By passing a pointer to space you allocated on the stack from main(), you won't lose the data when the function exits:
void foo(char* seq, size_t total_size, size_t* used_size)
{
*used_size = 3;
seq[0] = 1;
seq[1] = 0;
seq[2] = 1;
}
int main()
{
size_t used_size;
char seq[100];
foo(seq, sizeof(seq), &used_size);
/* use seq */
}
Related
This probably has been asked already, but I'm unable to find anything on it.
I have a string array, where the numbers of strings in it is determined at runtime (the max string length is known, if that helps). Since I need global access to that array, I used a pointer and malloc'ed enough space to it when I actually know how much has to fit in there:
char *global_strings;
void some_func(int strings_nr, int strings_size)
{
global_strings = (char*) malloc(strings_nr* strings_size* sizeof(char));
}
What would be the correct way in C to use this pointer like a two-dimensional char array equivalent to
global_strings[strings_nr][strings_size] ?
As a global pointer to 2D data, whose N*M characteristics defined at run-time, I'd recommend a helper function to access the strings rather than directly use it. Make it inline or as a macro if desired.
char *global_strings = NULL;
size_t global_strings_nr = 0;
size_t global_strings_size = 0;
// Allocation -
// OK to call again, but prior data may not be organized well with a new string_size
// More code needed to handle that.
void some_func(int strings_nr, int strings_size) {
global_strings_nr = strings_nr; // save for later use
global_strings_size = strings_size; // save for later use
global_strings = realloc(global_strings,
sizeof *global_strings * strings_nr * strings_size);
if (global_strings == NULL) {
global_strings_nr = global_strings_size = 0;
}
}
// Access function
char *global_strings_get(size_t index) {
if (index >= global_strings_nr) {
return NULL;
}
return global_strings + index*global_strings_size;
}
#define GLOBAL_STRINGS_GET_WO_CHECK(index) \
(global_strings + (index)*global_strings_size)
Better to use size_t for array indexing and sizing than int.
Casts not needed.
Memory calculations should begin with a size_t rather than int * int * size_t.
I am writing two ASCII char arrays to an LCD screen perfectly fine. However I need an if-condition to compare these two values.
Originally I attempted to simply compare them like this:
if(currentTemp < triggTemp)
{
alarmTriggered = true;
}
As this didn't work, I am attempting to convert them to floats from their ASCII strings using atof().
However this doesn't seem to want to work either, am I missing something silly here? Necessary code below:
void main () {
char triggTemp;
int buttonBool = 0;
bool alarmTriggered = false;
char currentTemp;
double f_triggTemp = 0;
double f_currentTemp = 0;
TRISC = 0x00;
init();
Init_lcd();
while(1)
{
//char bufferString[4];
currentTemp = get_temp();
f_currentTemp = atof(currentTemp);
f_triggTemp = atof(triggTemp);
if(f_currentTemp < f_triggTemp)
{
alarmTriggered = true;
}
if(alarmTriggered == true)
{
soundBuzzer();
}
}
The values are being returned from functions in this form:
//some function
char bufferString[4];
sprintf(numberString, "%s.%s", itoa(bufferString,setTemp,10),
itoa(bufferStringDec,setTempDec,10));
return numberString;
In essence, I am trying to compare these char arrays of ASCII characters so I can use an if condition to trigger an alarm.
I tried to keep the code snippets short, I can clarify on request. Thanks for any help.
EDIT: I know I'm using atof into double variables; the prototype in my library is set up like that.
I think this is what you are doing:
char* some_function() {
char temporary_string_buffer[32]; // Or some other fixed size
snprintf(temporary_string_buffer, 32, "some format");
return temporary_string_buffer;
}
You can't do that. OK, you can do that -- you probably just did -- but it has Undefined Behaviour, because the lifetime of temporary_string_buffer ends with the return statement. In the caller, the function will be returning what's colloquially known as a "dangling pointer"; in other words, a pointer whose target no longer has any meaning. So by the time you get around to calling atof on that value, it may have been used for something completely different.
If you want to return a string to the caller, either:
Dynamically allocate the string with malloc and make sure the caller knows that they need to free it; or
Get the caller to give you the address of a buffer and its length (as arguments), and fill in the supplied buffer. You can use the return code for a success indicator, or (like sprintf) as a count of bytes, or whatever.
char currentTemp; ... atof(currentTemp); will not work. double atof(const char *nptr) expects a pointer to a string, not a char.
Create a function to do the compare for you. Here is a complete test program. You just compare the array element one by one.
int is_greater(char a[], char b[], int z, int z1) {
int i = 0;
for( i = 0; i < z; i++ ) {
if( a[i] > b[i] ) return 1;
}
return 0;
}
I am having a bunch of problems with pointers and dynamic arrays here.
I have a function that I call, that does a bunch a stuff, like removing an ellement from the dynamic array , which leads me to reallocating memory to one of those dynamic arrays. The problem is I call functions within functions, and I can't return all my values properly to the Main.
Since I can't return 2 values, how can I do this?
structure1* register(structure1 *registerArray,structure2 *waitingList, int counter){
//Bunch of code in here
registerArray = realloc(inspecao, (counter)+1);
waitingList = eliminate(waitingList, 5, counter); //Doesn't matter what it does really
return registerArray;
}
structure1* eliminate(structure1 *arrayToEliminateFrom, int positionToEliminate, int *counter){
//The code for this doesn't matter
//All I do is eliminate an ellement and reallocate it
arrayToEliminateFrom = realloc(arrayToEliminateFrom, (*counter-1)*sizeof(structure1))
return arrayToEliminateFrom;
}
As you can see , I don't know how to return the pointer to the waitingList dynamic array to the Main. How can I do this?
I have searched everywhere.
Help
Okay, here are two ways to do it.
The first is, based upon your comment, what you think your instructor would want:
void
xregister(structure1 **registerArray, int *arrayCount,
structure1 **waitingList, int *waitCount)
{
// Bunch of code in here
*arrayCount += 1;
*registerArray = realloc(inspecao, *arrayCount * sizeof(structure1));
// Doesn't matter what it does really
eliminate(waitingList, 5, waitCount)
}
void
eliminate(structure1 **arrayToEliminateFrom, int positionToEliminate,
int *count)
{
// The code for this doesn't matter
*count -= 1;
// All I do is eliminate an ellement and reallocate it
*arrayToEliminateFrom = realloc(*arrayToEliminateFrom,
*count * sizeof(structure1))
}
Here is what Roberto and I were suggesting. Actually, mine's a general variable length array approach that can be fully generalized with some slight field changes. In a way, since you're already using a struct, I can't see why your instructor would object to this as it's a standard way to do it. Less cumbersome and cleaner.
struct vector {
int vec_count;
structure1 *vec_base;
};
void
xregister(vector *registerArray,vector *waitingList)
{
// Bunch of code in here
registerArray->vec_count += 1;
registerArray->vec_base = realloc(registerArray->vec_base,
registerArray->vec_count * sizeof(structure1));
// Doesn't matter what it does really
eliminate(waitingList, 5)
}
void
eliminate(vector *arrayToEliminateFrom, int positionToEliminate)
{
// The code for this doesn't matter
arrayToEliminateFrom->vec_count -= 1;
// All I do is eliminate an ellement and reallocate it
arrayToEliminateFrom->vec_base = realloc(arrayToEliminateFrom->vec_base,
arrayToEliminateFrom->vec_count * sizeof(structure1))
}
Here's an even more compact way:
struct vector {
int vec_count;
structure1 *vec_base;
};
void
vecgrow(vector *vec,int inc)
{
vec->vec_count += inc;
vec->vec_base = realloc(vec->vec_base,vec->vec_count * sizeof(structure1));
}
void
xregister(vector *registerArray,vector *waitingList)
{
// Bunch of code in here
vecgrow(registerArray,1);
// Doesn't matter what it does really
eliminate(waitingList, 5)
}
void
eliminate(vector *arrayToEliminateFrom, int positionToEliminate)
{
// The code for this doesn't matter
vecgrow(arrayToEliminateFrom,-1);
}
you should try to do an higher structure that contains both pointers and pass and return that structure beetween your functions, because function can return only one object/structure, but your structure/object can contain more objects/structures
First off, I know this should have been answered somewhere on SO but I just can't seem to find the correct post. So if it is a duplicate please point me to the post that answers this question and I will delete this.
I have a function that copies a string:
static int read_ad_content(json_t * root, char* content)
{
[.. stuff happens]
const char* tmp = json_string_value(json_content);
unsigned int size = strlen(tmp);
content = (char*)malloc(size + 1);
memcpy(content, tmp, size);
content[size] = '\0'; // <= I checked and content is NOT null here!
return 0;
}
And I call it like this in my main function:
char *ad_content;
if (read_ad_content(ad_json, ad_content) != 0)
{
log_err(argv, "Failed to extract information");
}
if (ad_content == NULL)
{
// <= I always end up here
}
I know this should be easy but I just don't know how to solve this.
In C, parameters are passed by value. What you're doing isn't any different from:
void brokenMethod(int a){
a = 10;
}
int a = 0;
brokenMethod(a);
if(a == 0)
{
//always end up here!
}
Of course you'll always end up there. a was never modified! The value of a was passed to brokenMethod, which could've done anything it wanted but that's not going to affect the value of a in your outer scope.
If I want the method to fill in an int, I have to pass it a pointer to an int.
void fixedMethod(int* a)
{
*a = 10;
//Remember, you want to modify the thing being pointed at, not the thing doing the pointing!
//a = something; is going to have the exact same problem as the first example
}
int a = 0;
fixedMethod(&a);
if(a == 0)
{
//Better
}
The above example sticks a value into an int. In your case, if you want the method to fill in a pointer to an int then you'll have to pass it a pointer to a pointer to an int.
Sidebar:
You may also find that methods which return values via parameters are difficult to reason about and more likely to contain bugs. If you're trying to return an pointer to an int, just have a method that returns a pointer to an int.
int* HonestMethod()
{
return pointer to whatever.
}
Im trying to print out the part at the end of this program. I enter C17 and the part comes out as 0 when it should be 1. Why is this?
Kind Regards
Dennis
# include <stdio.h>
int Part;
int getPartType(int Part);
int calcPrice(int Part);
int main(int argc, char * argv[]){
getPartType(Part);
calcPrice(Part);
return 0;
}
// Part1: Asks for input from user for part type
int getPartType(int Part) {
int nvr;
char character_one;
char character_two;
int number;
printf("Enter the part type (C17, F25, DN3, GG7 or MV4): ");
nvr = scanf("%c%c%d",&character_one,&character_two,&number);
if (number==7 && character_two=='1') {
Part=1;
}else if (number==5 && character_two=='2') {
Part=2;
}else if (number==3 && character_two=='N') {
Part=3;
}else if (number==7 && character_two=='G') {
Part=4;
}else if (number==4 && character_two=='V') {
Part=5;
}else{
printf("Wrong Part Type\n");
Part=0;
}
return Part;
}
int calcPrice(int Part) {
printf("%d\n",Part);
return 0;
}
getPartType(Part); returns an int, and doesn't assign to the original Part. So you must change this line:
getPartType(Part);
to
Part = getPartType(Part);
If you want to change the original value of Part you must use pointers. You can read more about this in any decent C book (I recommend K&R). For example:
// takes pointer to integer and sets it to 5
void settofive(int *someInteger) {
*someInteger = 5; // dereference someInteger and set to 5
}
int main(int argc, char *argv[]) {
int test = 0;
int *ptrTotest = &test; // take address of test and store in ptrTotest
printf("%d\n", test); // prints out zero
settofive(ptrTotest);
printf("%d\n", test); // prints out five
return 0;
}
You have a little misunderstanding of function argument passing.
When you call a function like
getPartType(Part);
C will create a copy of Part on the stack and all computations within the function will be made on this copy. Therefore you will not change the variable Part. This is called Call-by-value.
To change this problem, there are two ways. You can either just use:
Part = getPartType(Part);
This will create a copy of Part, the function will work on this copy, and then return something. This something will then get stored in the original Part. In your case you can actually just use int getPartType(void) as the function declaration, because you don't work an Part.
The other way would be to pass a pointer:
getPartType(&Part);
This passes a pointer to the original Part, so you can manipulate the original part (using the *-operator). This would mean that your declaration shoudl like like void getPartType(int *). But I would say the first method is preferable if you are dealing with just one basic variable
C is call by value. This means that the function can't change the value of a variable in the caller's context, unless the caller passes the address of that value.
Since your function doesn't really need an input argument, it should be removed. All you need is the return value.
Also, you could consider using multiple return statements, changing the if-ladder to look like so:
if (number==7 && character_two=='1') {
return 1;
}else if (number==5 && character_two=='2') {
return 2;
and so on.
Further, the use of "magical" numerical constants is generally a bad idea. It would be better to introduce an enumeration before main(), like this:
enum Part { PART_C17 = 1, PART_F25, PART_DN3, PART_GG7, PART_MV4 };
Then change the function to return a value of this new type:
enum Part getPartType(void)
{
/* ... */
}
and update the code in the if-ladder accordingly:
if (number==7 && character_two=='1') {
return PART_C17;
}else if (number==5 && character_two=='2') {
return PART_F25;
and so on.