REPL (Read–eval–print loop) with Mathlink (Wolfram Mathematica) - wolfram-mathematica

I'm new to Mathlink, and before integrating it in my code I tried to write a small REPL to get accustomed to it. The code is as follows (irrelevent parts omitted, and sorry for the horrible blend of C and C++):
int main(int argc,char **argv)
{
init_and_openlink(argc,argv);
while(!feof(stdin))
{
int pkt;
char buf[1024];
if(!fgets(buf,1024,stdin))
continue;
MLPutFunction(lp,"EnterTextPacket",1);
MLPutString(lp,buf);
MLEndPacket(lp);
while(((pkt=MLNextPacket(lp),pkt))&&(pkt!=RETURNPKT))
{
MLNewPacket(lp);
if(MLError(lp))
return 1;
}
const char *result;
MLGetString(lp,&result);
printf("%s\n",result);
MLReleaseString(lp,result);
}
return 0;
}
but it doesn't seem to work at all. I've tried replacing the while loop with a single MLNextPacket instruction but to no avail; I spent hours searching Mathlink documentation, but that one is a big mess! Where I'm doing it wrong?

The EnterTextPacket MathLink packet will make the kernel return the result wrapped in a ReturnTextPacket MathLink packet. Try changing the condition in your while loop to:
while(((pkt=MLNextPacket(lp),pkt))&&(pkt!=RETURNTEXTPKT))

Related

I am having a problem passing arguments to execvp using sleep and fork

I asked a really terrible question last time so I will try and do better here. I have the following code:
int main(int argc, char* argv[])
{
int forkChild;
char* argList[] = {"10","20","30"};
forkChild = fork();
if(forkChild == 0)
{
execvp("sleep",argList);
exit(0);
}
else
{
wait(NULL);
}
}
I am having trouble getting the execvp line to work. It will not sleep at all. It seems that the trouble might be because the argList array is passing strings and not integers to execvp. If I plug an integer directly into sleep it seems to work fine.
Eventually my program should be able to pass any parameter to execvp, so I am not sure why there is a problem with argument types. Is there something to this that I am not seeing?
Thanks

Accepting and printing a string

Can we accept and print a string like this in c++?
This code is not working properly.
#include<iostream>
#include<string>
using namespace std;
main()
{
string a;char ch;
for(int i=0;i<5;i++)
{cin>>ch;
a[i]=ch;
}
a[5]='\0';
cout<<a;
}
I am able to print individual elements like a[1],a[2],etc but unable to print the entire string.Why?
If you want to take a string, you could do the following.
#include <iostream>
int main() {
std::string str;
std::getline(std::cin, str);
std::cout << str;
}
Also, C++ automatically null terminates any string literal you use.
Well it's not really anywhere near best-practices but to fix your immediate issue you need to actually resize the string.
#include<iostream>
#include<string>
main()
{
std::string a;char ch;
a.resize(5); // <--- reserves memory
for(int i=0;i<5;i++)
{
std::cin>>ch;
a[i]=ch;
}
a[5]='\0'; //<-- unnecessary
st::cout<<a;
}
alternatively you can append the characters
#include<iostream>
#include<string>
main()
{
std::string a;char ch;
for(int i=0;i<5;i++)
{
std::cin>>ch;
a+=ch;
}
std::cout<<a;
}
The real problem here is not that you can't read or can't print the string, is that you are writing to unallocated memory. operator[], which is what you are using when you do something like a[i]=ch, does not do any kind of boundary checking and thus you are causing undefined behavior. In my machine, nothing is printed, for instance.
In short, you need to make sure that you have space to write your characters. If you are certain that you are going to read 5 characters (and adding a \0 at the end, making it 6 in length), you could do something like this:
std::string a(6, '\0')
If you are uncertain of how many characters you are going to read, std::string is ready to allocate space as need, but you need to use std::push_back to give it a chance to do so. Your loop contents would be something like:
cin >> ch;
a.push_back(ch);
If you are uncertain where the std::string object is coming from (as in, this is library code that accepts a std::string as an argument, you could use at(i) (e.g, a.at(i) = ch instead of a[i] = ch), which throws an exception if it is out of range.
You can print the string like this
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a;char ch;
for(int i=0;i<5;i++)
{
cin>>ch;
a.push_back(ch);
}
a.push_back('\0');
cout << a;
return 0;
}

getch() returns \377! instead of reading character

I am using Xcode and using the C language trying to understand how to use the Getch function to start a project. I copied some code someone had written as an example that should work, however instead of the code waiting for me to enter a character, it returns one for me:
#include <midi_lib.h> <---------- this needs to be here for later
#include <curses.h>
int main() {
keypad(stdscr, TRUE); /* I dont know if this is needed*/
char c;
puts("Enter a character\n");
c = getch();
printf("You just typed a %c! \n", c);
getch();
}
This is the output:
Enter a character
You just typed a \377!
It works if i use Getchar(), but i dont want to have to press enter.
I'm really new to coding so it maybe something simple, but i have no idea....
LT
Well, you didn't even initialize the Ncurses library with initscr().
There really are a lot of things you are missing, so I recommend you to read the Ncurses howto that explains you everything from initializing (e.g. what that keypad(stdscr, true) is) to input and a lot more.
Here's an example that works:
#include <ncurses.h>
int main()
{
int ch;
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
ch = getch();
endwin();
printf("The key pressed is %d\n", ch);
}
Try this to get you started
#include <midi_lib.h> <---------- this needs to be here for later
#include <curses.h>
int main()
{
char c;
keypad(stdscr, TRUE); /* I dont know if this is needed*/
puts("Enter a character\n");
do {
c = getch();
} while (c == (char)-1);
printf("You just typed a %c! \n",c);
}
Note that getch() is constantly polling the keyboard for input, when there is
none, it will get -1 and retry until there is some in which case it will fall out of the while loop and continue.
This probably isn't how you should be coding this, but it does answer your question. The computer will act busy while it is constantly polling the keyboard.

Dereferencing void* warnings on Xcode

I'm aware of this SO question and this SO question. The element
of novelty in this one is in its focus on Xcode, and in its use of
square brackets to dereference a pointer to void.
The following program compiles with no warning in Xcode 4.5.2, compiles
with a warning on GCC 4.2 and, even though I don't have Visual Studio
right now, I remember that it would consider this a compiler
error, and MSDN and Internet agree.
#include <stdio.h>
int main(int argc, const char * argv[])
{
int x = 24;
void *xPtr = &x;
int *xPtr2 = (int *)&xPtr[1];
printf("%p %p\n", xPtr, xPtr2);
}
If I change the third line of the body of main to:
int *xPtr2 = (int *)(xPtr + 1);
It compiles with no warnings on both GCC and Xcode.
I would like to know how can I turn this silence into warnings or errors, on
GDB and especially Xcode/LLVM, including the fact that function main is int but
does not explicitly return any value (By the way I think -Wall does
the trick on GDB).
that isnt wrong at all...
the compiler doesnt know how big the pointer is ... a void[] ~~ void*
thats why char* used as strings need to be \0-terminated
you cannot turn on a warning for that as it isnt possible to determine a 'size of memory pointer to by a pointer' at compile time
void *v = nil;
*v[1] = 0 //invalid
void *v = malloc(sizeof(int)*2);
*v[1] = 0 //valid
*note typed inline on SO -- sorry for any non-working code

gcc and lccwin32:different result

i try to compile this code:
#include <stdio.h>
void print(FILE *a)
{
int main();
int count=20;
int c;
int stop=0;
char answer;
while(!stop){
while((c=getc(a))!=EOF){
fprintf(stdout,"%c",c);
if(c=='\n'){
count--;
if(!count){
printf("do you want continue:y=for continue/q=for quit");
fflush(stdin);
answer=getchar();
if(answer=='y' || answer=='Y')
count=20;
else if(answer=='Q' || answer=='q'){
printf("you quit this program,press any key and hit the enter to close");
stop=1;
break;
}
else{
printf("argument is unacceptable,rolling back action");
main();
}
}
}
}
if(c==EOF)
stop=1;
}
}
void halt()/*do nothing just for halt and waiting for input*/
{
int a;
scanf("%d",&a);
}
int main()
{
FILE *in,*fopen();
char name1[25];
int a;
printf("enter the name of the file you want to show:");
scanf("%24s",name1);
in=fopen(name1,"r");
if(in==NULL){
printf("the files doesnt exist or it is in another directory, try to enter again\n");
main();
}
else
print(in);
fclose(in);
halt();
return 0;
}
the purpose of the program is to show 20 line content of a file. i compiled it in windows xp with lccwin32 and it works as expected. but problem arise when i change my os to linux (Ubuntu:pricise pangolin 12.04 LTS Desktop) and compile it with gcc.first it seems works fine but until the 20th line and prompt is out, when i put the argument (y for continue , q for quit)and hit the enter, but nothings happen. it just slipped away to elsepart which is starting again the program.so is it the gcc i have buggy or my code doesnt suit with gcc or may be i missed something?
I hate scanf. I would suggest replacing the scanf("%24s",name1) with fgets(s,24,stdin);
(And then unfortunately doing if (s[strlen(s)-1] == '\n') s[strlen(s)-1] = '\0' to get rid of the \n at the end.
I would also suggest:
Not use recursion on main
Use int main(int argc, char *argv[]) and then passing the name of your file as an argument (so you would check that argc > 1 and then use argv[1] as the filename, and then when running the program do ./programname filename)
Still not using scanf
In addition to the issues reported by #Foon you also have those problems :
fflush(stdin) is not working as you think it does.
scanf() leaves the newline character in the input buffer.
Your problem is that there is still a newline (\n) in the input buffer when you call getchar(), so your y/q answer is not even read.
Replacing fflush(stdin) with a solution from 1., or replacing fflush()+getchar() with scanf("\n%c",&answer); should solve that particular issue.

Resources