Welcome, Guest. Please login or register.

Author Topic: Executing c command in c  (Read 9226 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline foleyjoTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 608
    • Show only replies by foleyjo
Re: General C help
« Reply #29 on: May 19, 2017, 08:57:11 AM »
Well Olsen and Thomas thanks to your explanations about APTRs and BPTRs something clicked and I was able to work out how to get the string value from the mui_pop_string.

The talk of pointers, objects and strings made me realise that muia_popstring_string was returning a mui string object and not a string so I retrieved the value in 2 parts.

First I did a get() on the pop object to get the popstring_string object and then did another get on the returned object to get the strings content.

So now I think I understand everything I need to to get my first program completed without having to ask anymore questions.
There's still some stuff that I don't understand such as hooks but I think I'll be able to avoid creating any of my own.

So hopefully I won't be bothering anyone for help and advice till I have something to show.

You guys have helped point me in the right direction and understand so much more than all the guides and tutorials I spent weeks on and the reason why I always return to Amiga.org when I have an Amiga related question.

Cheers :D
 

Offline foleyjoTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 608
    • Show only replies by foleyjo
Re: General C help
« Reply #30 on: May 26, 2017, 09:02:15 AM »
Quote from: foleyjo;825982


So hopefully I won't be bothering anyone for help and advice till I have something to show.



Well it seems that I was wrong.
I have got through a lot and nearing first release. However I have hit a wall.

My code was getting too long and difficult to read so I decided to separate it into extra files.

I have created .h files and put includes to them in the .c files. I have got externs for when I want to share variables across pages and everything compiles fine.
Yet I keep getting crashes.
I have narrowed it down to if commands not working.

In the main file if I have
Code: [Select]

FILE * fp;
file = fopen("new_file","w");
if(fp){
  printf("file open");
  fclose(fp);
}
printf("file closed");


The output as you would expect is
-file_openfile closed

If the same code is placed in one of the sub files the output is
-file closed
and then when I close the program I get an error because the file wasn't closed.

Any ideas what I've missed ?
 

guest11527

  • Guest
Re: General C help
« Reply #31 on: May 26, 2017, 09:49:34 AM »
Quote from: foleyjo;826247
I have narrowed it down to if commands not working.

In the main file if I have
Code: [Select]
FILE * fp;
file = fopen("new_file","w");
if(fp){
  printf("file open");
  fclose(fp);
}
printf("file closed");

If the same code is placed in one of the sub files the output is
-file closed
Without seeing the full source, it is hard to tell. Probably the following: If you want to use the same object from two translation units, make sure that you define it only once, but declare it in every unit as an object with "external linkage".

That is, in one unit, you define outside of a function body an object with external linkage and program-long lifetime:
Code: [Select]
FILE *file; /* this is a definition, it creates the FILE * */
while, in a second unit, you access this very same object by only *declaring* it:
Code: [Select]
extern FILE *file; /* this is a declaration. The object is defined elsewhere */
The above line just tells the compiler "there is an object named 'file' somewhere else in the project, but not in the current translation unit".

This way, you ensure that the compiler generates code that accesses the identical object. Each object needs to be defined *once*, but can be *declared* multiple times.

I do not know whether this is your problem, it is just a guess from your observation.
 

Offline foleyjoTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 608
    • Show only replies by foleyjo
Re: Executing c command in c
« Reply #32 on: May 26, 2017, 10:25:03 AM »
With the extern command does it matter that I'm not declaring fp globally or passing it between functions?

so when I had the code in the sub function, in main I had a call to the subfunction with nothing else and then I just had the code from the example in the subfunction.

Everything else had been commented out.

It seems to be happening with all if/while statements where the result is expecting TRUE or FALSE and just taking the FALSE result.
The variables themselves are working without the if/whiles.
 

Offline olsen

Re: Executing c command in c
« Reply #33 on: May 26, 2017, 12:25:24 PM »
Quote from: foleyjo;826251
With the extern command does it matter that I'm not declaring fp globally or passing it between functions?
Hm... does "fp" have to be a global variable?

I am asking because there are several different ways to shoot yourself in the foot here.

It could be that you have a "FILE * fp;" defined inside a function (a local variable, as opposed to a global variable), which shares the same variable name with the globally defined "fp". This is the kind of thing which will inevitably make you miserable because everything seems to look right, yet the value of the variable seems to change. It does not change, the code is merely preferring the value stored in the local variable to the one in the global variable by the same name.

My advice would be to keep the names of local and global variables completely separate so that you know just by looking at what you code does that it's either a global or a local variable which is being used. If you don't yet have a good idea how to name your variables (this is one of the hard practical problems in computer science, I kid you not), you could start by changing the global "fp" variable name to "global_fp", for example and recompile your code. Does it compile? What needs to be changed to make it compile again?

I strongly recommend that you choose longer, more meaningful names for your variables. Introductions to the 'C' programming language tend to stick to the "no idle chatter" practice, keeping the names of functions and variables short. Variables are typically one letter each, maybe two, or even three if the author is generous.

When I started out writing 'C' code, I found that with short variables names, I had less to type, but more to remember. As a programmer, you already have a lot to remember to begin with, starting with how the individual parts of your program work together. Trying to remember all the names and respective purposes of variables does not help, it just makes your work harder. Worse: with similarly-named two-letter variables a mere typo can stress you out even more.

If you must use a global variable, make sure that you can know whether the contents of that variable are sound or not. If the fopen() function succeeds, it will return a special type of pointer ("FILE", as defined in the "stdio.h" header file) which is not NULL. If you store that pointer in a global variable and later close that file, make sure that you reset the global variable to NULL. That way you can more easily find improper use in your own code which references that global variable after the file has already been closed.
 

Offline foleyjoTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 608
    • Show only replies by foleyjo
Re: Executing c command in c
« Reply #34 on: May 26, 2017, 12:53:01 PM »
Think I've confused everyone with my explanation.

fp is declared locally. So I either have (just a quick example so ignore typos etc)

Example 1 = in 1 file
int main ()
{
  FILE *fp;
  fp =fopen("file","w");
  if(fp){do something}
  return 0;
}

Example 2 = in 2 files (with  .h files declaring the functions)
in file2.c
int function()
{
  FILE *fp;
  fp =fopen("file","w");
  if(fp){do something}
  return 0;
}

in file1.c

int main()
{
  function();
  return 0;
}


In Example 1 the if(fp) returns TRUE.
In Example 2 the if(fp) returns FALSE

Think I've confused everyone with my explanation.

fp is declared locally. So I either have (just a quick example so ignore typos etc)

Example 1 = in 1 file
int main ()
{
  FILE *fp;
  fp =fopen("file","w");
  if(fp){do something}
  return 0;
}

Example 2 = in 2 files (with  .h files declaring the functions)
in file2.c
int function()
{
  FILE *fp;
  fp =fopen("file","w");
  if(fp){do something}
  return 0;
}

in file1.c

int main()
{
  function();
  return 0;
}


In Example 1 the if(fp) returns TRUE.
In Example 2 the if(fp) returns FALSE

I haven't got fp declared globally. I try to avoid global variables as I've learned my lesson in the past from a global getting changed in a function when I didn't mean it to be changed.

The thing is, it all worked fine before I separated the code it into separate files. Anything in my main code file still works. It's only when I come to the other sections of code. If I put it back into 1 file it should work again but it's getting very long and hard to follow.
I suppose I could try adding comments to split the code up into sections

With variables I admit I don't name them the best but I do try to make them meaningful to me and usually use full words in my actual code. I use abbreviations for some things but only when the abbreviation is automatic to me. So when I see fp I'm actually reading it as File Pointer
« Last Edit: May 26, 2017, 01:11:42 PM by foleyjo »
 

Offline LiveForIt

Re: Executing c command in c
« Reply #35 on: May 26, 2017, 01:19:29 PM »
create a file called header.h

include header.h into the two files.

declare all the functions in header.h as extern
in the file header.h write

extern int function();

every file that header.h is included into, the compiler will know that there is a "int function()" somewhere, maybe not in this .cpp or .c file.

and try to not name your function "function", you might stumble onto keywords that compiler misinterprets.
« Last Edit: May 26, 2017, 01:24:05 PM by LiveForIt »
 

Offline olsen

Re: Executing c command in c
« Reply #36 on: May 26, 2017, 01:19:49 PM »
Quote from: foleyjo;826257
Think I've confused everyone with my explanation.

fp is declared locally. So I either have (just a quick example so ignore typos etc)

...

In Example 1 the if(fp) returns TRUE.
In Example 2 the if(fp) returns FALSE


If fopen() fails, there will be an error code set which explains why it did not work. That error code will be found in the global 'errno' variable (which is declared in the "stdio.h" header file), but you could use the perror() function (also declared in the "stdio.h" header file) to print an error message:

Code: [Select]

int
function_name(void)
{
    FILE * output_file;
    int success = FALSE;

    output_file = fopen("output","w");
    if(output_file != NULL)
    {
       ...

       fclose(output_file);

       success = TRUE;
    }
    else
    {
       perror("fopen failed");
    }

    return(success);
}


Opening a file for writing can only work out if that file is not currently being used, such as for reading or for writing. Protecting a file from deletion or writing can also prevent it from being opened for writing.

Also, if the name of the file you want to overwrite actually refers to a directory, you won't be able to open it for writing either.

If you succeed in opening a file for writing, make sure that you close that file when you no longer need it, or the next attempt to open it for writing may fail, even though your own program opened it.
 

Offline foleyjoTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 608
    • Show only replies by foleyjo
Re: Executing c command in c
« Reply #37 on: May 26, 2017, 01:46:23 PM »
LiveForIt - You might be onto something. (though I must point out my function isn't called function I just used that for the example. The one where I noticed the problem is actually called WriteNewDataToFile but I noticed the same issue across all functions not just with files).

I do have the header files and they are referenced in the c files.
What I haven't done is added the extern function lines in the main h file.
I have done it for variables that are passed between files.

Olsen - The file does seem to open. It creates an empty file in the correct folder with the correct name.
It doesn't close though as the if command doesn't work and my fclose is within the if.
 

Offline foleyjoTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 608
    • Show only replies by foleyjo
Re: Executing c command in c
« Reply #38 on: May 26, 2017, 01:55:58 PM »
Just thinking about what has been suggested already I'm just wondering,


if I have (again just examples not actual function names, headers all declared and bits missed out)


main.c
Code: [Select]

function1()
{
  FILE *fp
  fp =  fopen("thisfile","r");
  if(fp){
  do stuff....
  fclose(fp);}
}

main()
{
  function1();
  function2();


other.c
Code: [Select]
function2()
{
  FILE *fp
  fp =  fopen("thisfile","w");
  if(fp){
  do stuff....
  fclose(fp);}
}

because I have used fp in main.c would I need to set an extern File *fp in one of the headers to use it again in other.c ? Even though fp was declared locally in both function1 and function2 ?
My current way of thinking is that I wouldn't need to because the 2 fps are actually different because they are not declared globally.
However I'm starting to wonder if that is the case.
 

Offline LiveForIt

Re: Executing c command in c
« Reply #39 on: May 26, 2017, 03:17:02 PM »
Quote
I do have the header files and they are referenced in the c files.
What I haven't done is added the extern function lines in the main h file.
I have done it for variables that are passed between files.

Any function or variable that is not defined in the .cpp has to decaled with "extern", if you don't compiler will think the function is in the .c / .cpp file and fail.
Quote
function1()

If you have function like this one that does return a return value, you should declare it with void.

void function1() {
// do stuff
}

Quote
main()

should always be declared as "int main()", main should always return a value, or else you can get some strange messages in Shell.

Quote
because I have used fp in main.c would I need to set an extern File *fp in one of the headers to use it again in other.c ? Even though fp was declared locally in both function1 and function2 ?
My current way of thinking is that I wouldn't need to because the 2 fps are actually different because they are not declared globally.

You are correct

Quote
because I have used fp in main.c would I need to set an extern File *fp in one of the headers to use it again in other.c ?

As long as FILE *fp is declared inside the code block start { and }, its local variable, to that code block. Local variable are declared on the stack, sometime it might idea declare locals inside sub blocks inside function, saves the CPU from initialize variables that is not used.

You might have seen the typical

for (int I=0; I<10; I++) {
}

Counter "I", is only used once and declared only when it's needed.
« Last Edit: May 26, 2017, 03:27:47 PM by LiveForIt »
 

Offline foleyjoTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 608
    • Show only replies by foleyjo
Re: Executing c command in c
« Reply #40 on: May 26, 2017, 03:52:13 PM »
again in my real code the functions and declarations are declared properly and I've just been lazy in the examples.
So my real main lookslike

int main(int argc, char *argv[])
{
....
return 1;
}

I'll try adding externs for the functions and if it doesn't work I think I'll just go back to 1 file.
Everything was working as expected till I moved to separate files. In trying to locate the issue I ended up commenting out everything till all I had left was similar to the example I gave where if(fp) didn't work.
 

Offline LiveForIt

Re: Executing c command in c
« Reply #41 on: May 27, 2017, 12:12:17 AM »
You need to include the same files in all .c / .cpp files.
and you need to compile the .c/.cpp correct.

normally compile file2, file3 into a object, like

vbcc file2.c -o file2.o -c
vbcc file3.c -o file3.o -c

"-c" tells the compiler to make a object.

the you need to list all your file when compiling the main.c

vbcc main.c file2.o file3.o -o main.exe

some thing like that, I'm used to GCC, on AmigaOS4.1 :-), so you might need to look things up for vbcc.
« Last Edit: May 27, 2017, 12:14:55 AM by LiveForIt »
 

Offline foleyjoTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 608
    • Show only replies by foleyjo
Re: Executing c command in c
« Reply #42 on: May 30, 2017, 09:05:06 AM »
Well quite embarrassing but the issue was in another section of code where I hadn't put in a semi colon inside and else statement.

Only thing I'm struggling with is strings. I've been using malloc wrong and think I've made a mistake of not putting in a close character.

Need to put an integer into a structure string too. I've tried using sprintf(list_items->max_number"%d",total); but it just crashes
 

guest11527

  • Guest
Re: Executing c command in c
« Reply #43 on: May 30, 2017, 11:19:15 AM »
Quote from: foleyjo;826397
Need to put an integer into a structure string too. I've tried using sprintf(list_items->max_number"%d",total); but it just crashes
Note that sprintf requires a char * as first argument, and specifically, a buffer that is large enough to hold the largest possible output of the formatted print. With %d, the largest output could be 10 digits, so you would require a buffer of 11 characters at least.

One way or another, sprintf is probably not a very wise choice to use, especially for beginners. You do not know how large its output will become (unless you can compute an upper bound by yourself as in the example above), and if the buffer is too small, it will just overrun some random memory. Bad design decisions of legacy C.

If possible, avoid sprintf() and try to substitute with snprintf. While this may create truncated output, it will at least not trash memory in worst case.
 

Offline foleyjoTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 608
    • Show only replies by foleyjo
Re: Executing c command in c
« Reply #44 from previous page: May 30, 2017, 01:55:27 PM »
Had a typo there. List_items->max_number is my char *. Should have been a , after it.
I think it'll be easier to make it an int inside the structure. I had problems. Not sure why I did it as a char chat in the first place. Think I was getting a crash and changing it fixed things. Should have known it would come back to haunt me.
I'll check out snprintf too