Hello there and thank you for stopping by.
The solution has been found by making use of proprietary code. See bottom for used code.
Thanks everybody for input and help!
I'm fairly new to C programming (meaning I coded some very basic stuff). At the moment, I'm writing a script in C language. I've tried searching the site, but no examples seem applicable to my case, or simply do not work.
What it does is basically opening a file (or a batch of multiple files), telling the master program to plot a graph of selected string (the open_curve() is a program specific function).
Now my problem is that one of the strings (lets say string2 in the code below) is not always present. When it's missing, the script produces an error and quits. How to stop this happening? VBA has an option many people loathe, but I regard it to be quite useful in this situation: On Error resume next. I know it might be missing and it is not of importance in this case. When it's there I need it. When it's not, too bad... so if no errors pop up and the value is missing, that is perfectly fine.
Question is, how can I get a similar functionality in C?
#define NMAX 10 // max. Anzahl Dateien
string n[NMAX]; // Global wegen Stack!
void main(void)
{
string *q;
int i,nmax=NMAX;
nmax=GetOpenFileName(n, nmax, "Daten-Dateien (*.DAT)", "*.DAT");
for (i=0, q=n; i<nmax; i++,q++)
{
ql.open_file(.file=*q);
close_curve();
open_curve(.name="\"String1\"");
open_curve(.name="\"String2\"");
open_curve(.name="\"String3\"");
printf("File %2d: %s\n",i,*q);
}
getch();
}
The prototype:
int [ql.]open_curve(.name = string[, .no = int,
.color = int, .lthick = int,
.linetype = int,
.marker = int, .drawall = int,
.markersize = float,
.bars = int, .ynull = float,
.ymin = float, .ymax = float,
.xmin = float, .xmax = float,
.yaxis = int, .xaxis = int,
.axis = int, .colsrc = int,
.xsignal = string, .csignal = string,
.index = string,
.xfrom = float, .xuntil = float,
.usemarker = int]);
The Code, with my problem solved:
Now returns empty when not found.
for (i=0, q=n; i<nmax; i++,q++)
{
ql.open_file(.file=*q);
close_curve();
open_curve(.name="\"String1\"");
Warninglevel = 2;
Errorlevel3 = 3; // Fehler nicht melden, weitermachen
err = open_curve(.name="\"String2\"");
Errorlevel3 = 0;
Warninglevel = 0;
open_curve(.name="\"String3\"");
printf("File %2d: %s\n",i,*q);
}
getch();
}
with the warning and error levels explained as following:
extern int Warninglevel - Warnings will...
0 - Produce an Error box
1 - be ignored
2 - be ignored
extern int Errorlevel1 - Errors will...
0 - Produce an Error box (popup) and cancel script
1 - Produce an Error box and continue script 2 - ignored and cancel script.
There is nothing in C that corresponds to On Error Resume Next.
It is possible to catch errors using signal handling, but it is not the preferred way to do error checking in C.
Instead, best practice is to code defensively. Any variable that is allowed to be NULL should be checked before it is used.
In your case the code could look like this:
char *name; // In reality
name = get_graph_name(); // Generate a name somehow, or null.
if (name != NULL) { // Only open the curve if we have a name.
open_curve(name);
}
Related
I'm trying to use realloc function in C, to dynamically operate on a char array of strings (char**).
I usually get a realloc():invalid old size error after 41st cicle of the for loop and I really can't understand why.
So, thanks to everyone who will help me ^-^
[EDIT] I'm trying to make the post more clear and following your advices, as a "new active member" of this community, so thank you all!
typedef struct _WordsOfInterest { // this is in an header file containing just
char **saved; // the struct and libraries
int index;
} wordsOfInterest;
int main() {
char *token1, *token2, *save1 = NULL, file[LEN], *temp, *word, **tokenArr;
int n=0, ch,ch2, flag=0, size, init=0,position,currEdit,init2=0,tempEdit,size_arr=LEN,
oldIndex=0,totalIndex=0,*editArr,counterTok=0;
wordsOfInterest toPrint;
char **final;
toPrint.index = 0;
toPrint.saved = malloc(sizeof(char*)*LEN);
editArr = malloc(sizeof(int)*LEN);
tokenArr = malloc(sizeof(char*)*LEN);
final = malloc(sizeof(char*)*1);
// external for loop
for(...) {
tokenArr[counterTok] = token1;
// internal while loop
while(...) {
// some code here surely not involved in the issue
} else {
if(init2 == 0) {
currEdit = config(token1,token2);
toPrint.saved[toPrint.index] = token2;
toPrint.index++;
init2 = 1;
} else {
if((abs((int)strlen(token1)-(int)strlen(token2)))<=currEdit) {
if((tempEdit = config(token1,token2)) == currEdit) {
toPrint.saved[toPrint.index] = token2;
toPrint.index++;
if(toPrint.index == size_arr-1) {
size_arr = size_arr*2;
toPrint.saved = realloc(toPrint.saved, size_arr);
}
} else if((tempEdit = config(token1,token2))<currEdit) {
freeArr(toPrint, size_arr);
toPrint.saved[toPrint.index] = token2;
toPrint.index++;
currEdit = tempEdit;
}
}
}
flag = 0;
word = NULL;
temp = NULL;
freeArr(toPrint, size_arr);
}
}
editArr[counterTok] = currEdit;
init2 = 0;
totalIndex = totalIndex + toPrint.index + 1;
final = realloc(final, (sizeof(char*)*totalIndex));
uniteArr(toPrint, final, oldIndex);
oldIndex = toPrint.index;
freeArr(toPrint,size_arr);
fseek(fp2,0,SEEK_SET);
counterTok++;
}
You start with final uninitialized.
char **final;
change it to:
char **final = NULL;
Even if you are starting with no allocation, it needs a valid value (e.g. NULL) because if you don't initialize a local variable to NULL, it gets garbage, and realloc() will think it is reallocating a valid chunk of memory and will fail into Undefined Behaviour. This is probably your problem, but as you have eliminated a lot of code in between the declaration and the first usage of realloc, whe cannot guess what is happening here.
Anyway, if you have indeed initialized it, I cannot say, as you have hidden part of the code, unlistening the recommendation of How to create a Minimal, Reproducible Example
.
There are several reasons (mostly explained there) to provide a full but m inimal, out of the box, failing code. This allows us to test that code without having to provide (and probably solving, all or part) the neccesary code to make it run. If you only post a concept, you cannot expect from us complete, full running, and tested code, degrading strongly the quality of SO answers.
This means you have work to do before posting, not just eliminating what you think is not worth mentioning.
You need to build a sample that, with minimum code, shows the actual behaviour you see (a nonworking complete program) This means eliminating everything that is not related to the problem.
You need (and this is by far more important) to, before sending the code, to test it at your site, and see that it behaves as you see at home. There are many examples that, when eliminated the unrelated code, don't show the commented behaviour.
...and then, without touching anymore the code, send it as is. Many times we see code that has been touched before sending, and the problem dissapeared.
If we need to build a program, we will probably do it with many other mistakes, but not yours, and this desvirtuates the purpose of this forum.
Finally, sorry for the flame.... but it is necessary to make people read the rules.
I am trying to make a c-program that will will a string, but I want it only to read a very small part of it.
The NMEA-telegram that I try to read is $WIXDR, and do receive the necessary strings.
Here's 2 examples of strings that I get into the CPU:
$WIXDR,C,1.9,C,0,H,83.2,P,0,P,1023.9,H,0*46
$WIXDR,V,0.01,M,0,Z,10,s,0,R,0.8,M,0,V,0.0,M,1,Z,0,s,1,R,0.0,M,1,R,89.9,M,2,R,0.0,M,3*60
If it were only 1 string (not both C and V), this would not be a problem for me.
The problem here is that it's 2 seperate strings. One with the temperature, and one with rain-info.
The only thing that I'm interested in is the value "1.9" from
$WIXDR,C,1.9,C,0......
Here's what I have so far:
void ProcessXDR(char* buffPtr)
{
char valueBuff[10];
int result, x;
float OutSideTemp;
USHORT uOutSideTemp;
// char charTemperature, charRain
IODBerr eCode;
//Outside Temperature
result = ReadAsciiVariable(buffPtr, &valueBuff[0], &buffPtr, sizeof(valueBuff));
sscanf(&valueBuff[0],"%f",&OutSideTemp);
OutSideTemp *= 10;
uOutSideTemp = (USHORT)OutSideTemp;
eCode = IODBWrite(ANALOG_IN,REG_COM_XDR,1,&uOutSideTemp,NULL);
}
// XDR ...
if(!strcmp(&nmeaHeader[0],"$WIXDR"))
{
if(PrintoutEnable)printf("XDR\n");
ProcessXDR(buffPtr);
Timer[TIMER_XDR] = 1200; // Update every minute
ComStateXDR = 1;
eCode = IODBWrite(DISCRETE_IN,REG_COM_STATE_XDR,1,&ComStateXDR,NULL);
}
There's more, but this is the main part that I have.
I have found the answer to my own question. The code that would do as I intented is as follows:
What my little code does, is to look for the letter C, and if the C is found, it will take the value after it and put it into "OutSideTemp". The reason I had to look for C is that there is also a similar string received with the letter V (Rain).
If someone have any input in a way it could be better, I don't mind, but this little piece here does what I need it to do.
Here's to example telegrams I receive (I wanted the value 3.0 to be put into "OutSideTemp"):
$WIXDR,C,3.0,C,0,H,59.2,P,0,P,1026.9,H,04F
$WIXDR,V,0.00,M,0,Z,0,s,0,R,0.0,M,0,V,0.0,M,1,Z,0,s,1,R,0.0,M,1,R,89.9,M,2,R,0.0,M,358
void ProcessXDR(char* buffPtr)
{
char valueBuff[10];
int result, x;
float OutSideTemp;
USHORT uOutSideTemp;
// char charTemperature, charRain
IODBerr eCode;
// Look for "C"
result = ReadAsciiVariable(buffPtr, &valueBuff[0], &buffPtr, sizeof(valueBuff));
// sscanf(&valueBuff[0],"%f",&charTemperature);
if (valueBuff[0] == 'C')
//Outside Temperature
result = ReadAsciiVariable(buffPtr, &valueBuff[0], &buffPtr, sizeof(valueBuff));
sscanf(&valueBuff[0],"%f",&OutSideTemp);
OutSideTemp *= 10;
uOutSideTemp = (USHORT)OutSideTemp;
eCode = IODBWrite(ANALOG_IN,REG_COM_XDR,1,&uOutSideTemp,NULL);
}
Today I finished the music project, or at least I think I've finished it.
On helper.c when I run make it makes both notes and synthesizer files and with no errors. But when I want to run ./notes it gives me segmentation fault error. Even when I ran the program with check50 it gave me this error:
failed to execute program due to segmentation fault
I personally think it might be because of turning string to int or the way I got the notes from the string. First I introduced one string for taking the note and one int for taking the ovtav of the note.
The string note is something like D4 or C#4
So I will just copy this part, to check with you if I've done it correctly.
string noteletter="";
int noteoctav;
if (strlen(note) == 3)
{
noteletter[0] = note[0];
noteletter[1] = note[1];
noteoctav = note[2] - '0';
}
if (strlen(note)== 2)
{
noteletter[0] = note[0];
noteoctav = note[1] - '0';
}
Update
Here I've added the full code so you can see what I am trying to do.
Two problems I can see (assuming string is a typedef of char*)
if noteletter has a length of 0 (value = "") then what do you think noteletter[1] is doing?
Even if noteletter was set to something bigger (e.g. noteletter = "ABC";) - writing to a literal string is undefined behavior.
Try char noteletter[3] = { 0 }; to get something that (at a quick glance) looks big enough.
Another possible issue: if note is NULL or invalid then strlen(note) is not safe.
(Posted answer on behalf of the question author)
My problem was that I defined noteletter as string. I changed that part to
char noteletter[4];
int noteoctav;
if (strlen(note) == 3)
{
noteletter[0] = note[0];
noteletter[1] = note[1];
noteletter[2] = '\0';
noteoctav = note[2] - '0';
}
if (strlen(note)== 2)
{
noteletter[0] = note[0];
noteletter[1] = '\0';
noteoctav = note[1] - '0';
}
and now it works :)
I am having some issues with lb_getcursel and what it returns (if it does even return anything)
heres my message handler...
case IDT_TESTLIST1:
if(HIWORD(wParam) == LBN_DBLCLK) {
int ret = 0;
double TimeOut = 60.0;
int Lng = 1;
unsigned char Param[255] = {0};
unsigned char Port1 = port1;
int iCurSel = SendDlgItemMessage(hwnd,IDT_TESTLIST1,LB_GETCURSEL,0.0);
ret = PSB30_Open(Port1,16);
ret = PSB30_SendOrder(Port1,test1[iCurSel].testNumber, &Param[0],&Lng,&TimeOut);
ret = PSB30_Close(Port1);
}
break;
I am using Visual Studio 2010 and whenever i run the program iCurSel doesn't look like it even gets assigned a value, defaults to 0, when i step into the case statement, not all variables are visible in the autos section, when i add a watch to iCurSel i get a CXX0017: Error message.
hwnd is the handle to my main window and is correct
any help would be appreciated
Cheers
i find it funny that none of my variables in the message are showing anything by hovering over them
That's because they don't exist. Your program cannot compile, it has an error. SendDlgItemMessage() takes 5 arguments, you pass 4. The last one got morphed into a floating point value by a typo.
Clearly you'll need to pay attention to compile error messages. And change a setting so this cannot happen again. Tools + Options, Projects and Solution, Build and Run. Change the "On Run, when build or deployment error occurs" setting to "Do not launch".
I am programming a robot in C, and I have run into a problem I can't seem to figure out.
The only way to solve this problem would be to use a lot of goto statements.
I am trying to figure out a way to save myself writing over 100 goto points and statements and if statements, etc. and am wondering if there is a way to goto the value of a string. for example-
string Next = "beginning";
goto Next;
beginning:
Is there any way to goto the value of Next, or to substitute in the value of Next into the goto statement?
If there is a way to do this, then I will be able to just change the value of Next for each driving command, and then goto whatever the value of the string Next is.
In other words, just converting the string to a goto identifier, or substituting it in place of one.
Thanks for the help!
-EDIT-
A lot of you guys are suggesting the use of switch statements. I am not sure this would work because of how i have it programmed. The structure of the program is here--
by the way this code only includes a little of what i actually have, my real code is over 500 lines so far. Also, the driving commands are majorly simplified. but the basic concept is here, easier to understand than what i wouldve had.
task main()
{
//integer list
int forwardDrivingSelector = 0;
int backwardDrivingSelector = 0;
int rightRotatingSelector = 0;
string nextCommand;
int waitTime = 0;
int countup = 0;
//driving commands
driveForward:
while(forwardDrivingSelector == 1)
{
motor[leftMotor] = 127;
motor[rightMotor] = 127;
countup++;
wait1Msec(1);
if(countup == waitTime)
{
countup = 0;
goto nextCommand;
}
}
driveBackward:
while(backwardDrivingSelector == 1)
{
motor[leftMotor] = -127;
motor[rightMotor] = 127;
countup++;
wait1Msec(1);
if(countup == waitTime)
{
countup = 0;
goto nextCommand;
}
}
rightRotate:
while(rightRotatingSelector == 1)
{
motor[leftMotor] = 127;
motor[rightMotor] = -127;
countup++;
wait1Msec(1);
if(countup == waitTime)
{
countup = 0;
goto nextCommand;
}
}
//autonomous driving code
//first command, drive forward for 1000 milliseconds
forwardDrivingSelector = 1;
nextCommand = "secondCommand";
waitTime = 1000;
goto driveForward;
secondCommand:
forwardDrivingSelector = 0;
//second command, rotate right for 600 milliseconds
rightRotatingSelector = 1;
nextCommand = "thirdCommand";
waitTime = 600;
goto rightRotate;
thirdCommand:
rightRotatingSelector = 0;
//third command, drive backwards for 750 milliseconds
backwardDrivingSelector = 1;
nextCommand = "end";
waitTime = 750;
goto driveBackward;
end:
backwardDrivingSelector = 0;
}
so. how this works.
i have a list of integers, including driving command selectors, the countup and waitTime integers, and the string that i was talking about, nextCommand.
next comes the driving commands. in my real code, i have about 30 commands, and they are all hooked up to a remote control and its over 400 lines for just the driving commands.
next comes the autonomous code. the reason i set it up like this is so that the autonomous code part would be, short, simple, and to the point. pretty much to add a command to the driving code, you turn on the selector, tell the nextCommand string what the next command is, set the waitTime (which is how long it does the command, in milliseconds), then you make the code goto the driving command which you are putting in. the driving command drives for the amount of time you put in, then does goto nextCommand;
This would all theoretically work if there was a way to make the goto statement 'interpret' the string as an identifier so it can be changed.
There are about 4 simple ways i can think of right now that could get past this easily, but they would make the code really really long and cluttered.
Now that you have a better understanding of my question, any more input? :)
btw - i am using a program called robotC, and i am programming a vex robot. so i HAVE to use plain, basic, C, and i cant use any addons or anything... which is another reason this is complicated because i cant have multiple classes and stuff like that...
As an extension to the C language, GCC provides a feature called computed gotos, which allow you to goto a label computed at runtime. However, I strongly recommend you reconsider your design.
Instead of using gotos with over a hundred labels (which will easily lead to unmaintainable spaghetti code), consider instead using function pointers. The code will be much more structured and maintainable.
Instead of goto's, I'd call one of 100 functions. While C won't handle the conversion from string to function for you, it's pretty easy to use a sorted array of structs:
struct fn {
char name[whatever];
void (*func)(void);
};
Then do (for example) a binary search through the array to find the function that matches a string.
Also note that many real systems provide things like GetProcAddress (Windows) or dlsym (Unix/Linux) to handle some of the work for you.
You're thinking about this the wrong way. Each of the actions you need to call should be a function, then you can choose which function should be called next by inspecting a "next" variable.
This could be a string as you've mentioned, but you might be best using a enumerated type to make readable, but more efficient code.
The alternative, though probably overkill, would be to ensure your functions all use the same parameters and return types, and then use a function pointer to track which piece of code should be executed next.
Small tip: If you ever think you need more than 1 goto statement to achieve a certain goal you're probably not looking at the best solution.
You need to step back and consider other solutions for the problem you are trying to solve. One of them might look like this:
void DoSomething() {
printf("Something\n");
}
void DoSomethingElse() {
printf("Something else\n");
}
void (*nextStep)(void) = NULL;
nextStep = DoSomething;
nextStep();
nextStep = DoSomethingElse;
nextStep();
See it in action.
How about a switch? Either use an int/enum/whatever or inspect the value of the string (loop over it and strcmp, for instance) to figure out the destination.
const char *dsts[n_dsts] = {"beginning","middle",...};
...
int i;
for(i = 0; i < n_dsts; i++) if(strcmp(dsts[i]) == 0) break;
switch(i) {
case 0: // whatever
case 1: // whatever
...
break;
default: // Error, dest not found
}
Firstly, let me preface this by agreeing with everyone else: this is probably not the right way to go about what you're trying to do. In particular, I think you probably want a finite-state machine, and I recommend this article for guidelines on how to do that.
That said . . . you can more or less do this by using a switch statement. For example:
Next = BEGINNING;
HelperLabel:
switch(Next)
{
case BEGINNING:
.
.
.
Next = CONTINUING;
goto HelperLabel;
case ENDING:
.
.
.
break;
case CONTINUING:
.
.
.
Next = ENDING;
goto HelperLabel;
}
(Note that a switch statement requires integers or integer-like values rather than strings, but you can use an enum to create those integers in a straightforward way.)
See http://en.wikipedia.org/wiki/Duff's_device for the original, canonical example of using switch/case as a goto.
#define GOTO_HELPER(str, label) \
if (strcmp(str, #label) == 0) goto label;
#define GOTO(str) do { \
GOTO_HELPER(str, beginning) \
GOTO_HELPER(str, end) \
} while (0)
int main (int argc, char ** argv) {
GOTO("end");
beginning:
return 1;
end:
return 0;
}