I write a small console program in objective-c. It need to use the scanf method to receive the number.When I enter a character, it will make a mistake.So I try to solve it,but it has entered a cycle of death! See the following code, to help me solve it, thank you very much!
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
int num1 = 0;
NSLog(#"Please input number:");
while (!scanf("%d", &num1)) {
fflush(stdin);
NSLog(#"Input error,just input number:");
}
}
return 0;
}
The documentation for fflush states:
The function fflush() forces a write of all buffered data for the given output or update stream via the
stream's underlying write function. The open status of the stream is unaffected.
and you are trying to flush input. Try fpurge:
The function fpurge() erases any input or output buffered in the given stream.
Also do not write !scanf(...). Check the documentation, this function returns an integer, not a boolean, and the value could be positive or negative (look up the definition of EOF). A negative value indicates an error, but the ! operator will yield false and your code would not ask for new input.
If successful scanf returns the number of items successfully parsed, check for that.
The documentation for all these functions is available via Xcode or the man command.
HTH
Related
I want to create a program that draws some objects to scene using OpenGL, where I am continually changing the position of those object manually. To achieve this, I need to run some kind of loop where on each loop, it changes the position of the objects, and then draws to the screen, before repeating.
Given that glutMainLoop() is a non-returning function, and is also compulsory to run an OpenGL program, I need to run my loop with some sort of timer.
Now my solution which works is similar to the following:
void Render()
{
// Draw some objects using OpenGL
// ......
// ......
}
void Loop
{
// Update the positions of the objects
// ......
// ......
glutPostRedisplay();
glutTimerFunc(1, Loop, 0);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
GlutCreateWindow("Test");
glutDisplayFunc(Render);
glutMainLoop();
glutTimerFunc(1, Loop, 0);
}
However, I am not sure I understand why there is the need for the glutTimerFunc() call in main(). Why can I not just replace it with a direct call to Loop()?
For example:
int main(int argc, char** argv)
{
glutInit(&argc, argv);
GlutCreateWindow("Test");
glutDisplayFunc(Render);
glutMainLoop();
Loop();
}
This does not work. The objects do not move on the screen as expected, and furthermore, then OpenGL window is totally unresponsive; I cannot even close it by clocking the cross on the title bar.
Surely glutTimerFunc(1, Loop, 0); just calls Loop() in the same way I have done in the second example, so why does this not work...?
Basically, the glutTimerFunc waits for a number of milliseconds to pass before calling the callback (in your case, Loop()). In this way it acts like a refresh operation.
Check out →GLUT API for more detail
void glutTimerFunc(unsigned int numMilliseconds, functionCallback, value);
So, that means you can pass in something like this:
glutTimerFunc(1000 / SCREEN_FPS, Loop, 0);
For extra info on main loops
deWitter's Gameloop
However, as your project gets more complex, you might find that you want the objects in your scenes rendering at constant speed. In addition to the glutTmerFunc, you can make you animations work with elapsed time - found by calculating the difference between the current time and previously current time.
Hope this helps!
Here's a really simple glutTimerFunc() example from a real program.
I wanted to hi-jack the title bar for command input. When you typed stuff, it appeared in the title bar and when you pressed return, it executed the command. I wanted a blinking cursor.
char title[80]; // This is where our keystrokes go.
char * cursor = NULL; // This points to the cursor character.
void cursorBlink(int id) {
if (cursor) {
*cursor = (*cursor == ' ') ? '_' : ' ';
glutSetWindowTitle(title);
glutTimerFunc(1000.0, cursorBlink, 0);
}
}
This isn't quite the whole thing. The ESC key gets us into command line entry mode. This sets up the title string and the cursor pointer, and it also has to make the first call to cursorBlink() to get the loop started. When command entry is done, the cursor point gets set back to NULL, and the loop shuts itself down.
The cursorBlink argument is not used. This is common with simple animations. Don't worry about it.
My code is as follows:
boost::asio::streambuf b1;
boost::asio::async_read_until(upstream_socket_, b1, '#',
boost::bind(&bridge::handle_upstream_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
void handle_upstream1_read(const boost::system::error_code& error,
const size_t& bytes_transferred)
{
if (!error)
{
async_write(downstream_socket_,
b2,
boost::bind(&bridge::handle_downstream_write,
shared_from_this(),
boost::asio::placeholders::error));
}
else
close();
}
According to the documentation of async_read_until, http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/async_read_until/overload1.html,
After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter. An application will typically leave that data in the streambuf for a subsequent async_read_until operation to examine.
I know that the streambuf may contain additional data beyond the delimiter, but, in my case, will it write those additional data (the data beyond the char'#') to the downstream_socket_ inside the async_write operation? Or will async_write function be smart enough not to write those additional data until the next time the handle_upstream1_read function is being called?
According to the approaches in the documentation, the data in streambuf are stored in the istream first ( std::istream response_stream(&streambuf); )
and then put it into a string by using std::getline() funciton.
Do I really need to store the streambuf in istream first and then convert it into a string and then convert it back to char arrary (so that I can send the char array to the downstream_socket_ ) instead of just using the async_write to write the data( up to but not including the delimter, '#' ) to the downstream_socket_ ?
I prefer the second approach so that I don't need to make several conversion on the data. However, it seems that something is wrong when I tried the second approach.
My ideal case is that:
upstream_socket_ received xxxx#yyyy by using async_read_until
xxxx# is written to the downstream_socket_
upstream_socket_ received zzzz#kkkk by using async_read_until
yyyyzzzz# is written to the downstream_socket_
It seems that async_write operation still writes the data beyond the delimiter to the downstream_socket_. (but I am not 100% sure about this)
I appreciate if anyone can provide a little help !
The async_write() overload being used is considered complete when all of the streambuf's data, its input sequence, has been written to the WriteStream (socket). It is equivalent to calling:
boost::asio::async_write(stream, streambuf,
boost::asio::transfer_all(), handler);
One can limit the amount of bytes written and consumed from the streambuf object by calling this async_write() overload with the boost::asio::transfer_exactly completion condition:
boost::asio::async_write(stream, streambuf,
boost::asio::transfer_exactly(n), handler);
Alternatively, one can write directly from the streambuf's input sequence. However, one will need to explicitly consume from the streambuf.
boost::asio::async_write(stream,
boost::asio::buffer(streambuf.data(), n), handler);
// Within the completion handler...
streambuf.consume(n);
Note that when the async_read_until() operation completes, the completion handler's bytes_transferred argument contains the number of bytes in the streambuf's input sequence up to and including the delimiter, or 0 if an error occurred.
Here is a complete example demonstrating using both approaches. The example is written using synchronous operations in an attempt to simplify the flow:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
// This example is not interested in the handlers, so provide a noop function
// that will be passed to bind to meet the handler concept requirements.
void noop() {}
/// #brief Helper function that extracts a string from a streambuf.
std::string make_string(
boost::asio::streambuf& streambuf,
std::size_t n)
{
return std::string(
boost::asio::buffers_begin(streambuf.data()),
boost::asio::buffers_begin(streambuf.data()) + n);
}
int main()
{
using boost::asio::ip::tcp;
boost::asio::io_service io_service;
// Create all I/O objects.
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0));
tcp::socket server_socket(io_service);
tcp::socket client_socket(io_service);
// Connect client and server sockets.
acceptor.async_accept(server_socket, boost::bind(&noop));
client_socket.async_connect(acceptor.local_endpoint(), boost::bind(&noop));
io_service.run();
// Mockup write_buffer as if it read "xxxx#yyyy" with read_until()
// using '#' as a delimiter.
boost::asio::streambuf write_buffer;
std::ostream output(&write_buffer);
output << "xxxx#yyyy";
assert(write_buffer.size() == 9);
auto bytes_transferred = 5;
// Write to server.
boost::asio::write(server_socket, write_buffer,
boost::asio::transfer_exactly(bytes_transferred));
// Verify write operation consumed part of the input sequence.
assert(write_buffer.size() == 4);
// Read from client.
boost::asio::streambuf read_buffer;
bytes_transferred = boost::asio::read(
client_socket, read_buffer.prepare(bytes_transferred));
read_buffer.commit(bytes_transferred);
// Copy from the read buffers input sequence.
std::cout << "Read: " <<
make_string(read_buffer, bytes_transferred) << std::endl;
read_buffer.consume(bytes_transferred);
// Mockup write_buffer as if it read "zzzz#kkkk" with read_until()
// using '#' as a delimiter.
output << "zzzz#kkkk";
assert(write_buffer.size() == 13);
bytes_transferred = 9; // yyyyzzzz#
// Write to server.
boost::asio::write(server_socket, buffer(write_buffer.data(),
bytes_transferred));
// Verify write operation did not consume the input sequence.
assert(write_buffer.size() == 13);
write_buffer.consume(bytes_transferred);
// Read from client.
bytes_transferred = boost::asio::read(
client_socket, read_buffer.prepare(bytes_transferred));
read_buffer.commit(bytes_transferred);
// Copy from the read buffers input sequence.
std::cout << "Read: " <<
make_string(read_buffer, bytes_transferred) << std::endl;
read_buffer.consume(bytes_transferred);
}
Output:
Read: xxxx#
Read: yyyyzzzz#
A few other notes:
The streambuf owns the memory, and std::istream and std::ostream use the memory. Using streams may be a good idea when one needs to extract formatted input or insert formatted output. For instance, when one wishes to read the string "123" as an integer 123.
One can directly access the streambuf's input sequence and iterate over it. In the example above, I use boost::asio::buffers_begin() to help construct a std::string by iterating over a streambuf's input sequence.
std::string(
boost::asio::buffers_begin(streambuf.data()),
boost::asio::buffers_begin(streambuf.data()) + n);
A stream-based transport protocol is being used, so handle incoming data as a stream. Be aware that even if the intermediary server reframes messages and sends "xxxx#" in one write operation and "yyyyzzzz#" in a subsequent write operation, the downstream may read "xxxx#yyyy" in a single read operation.
I should use Objective-C to read some slowly growing file (under Mac OS X).
"Slowly" means that I read to EOF before it grows bigger.
In means of POSIX code in plain syncronous C I can do it as following:
while(1)
{
res = select(fd+1,&fdset,NULL,&fdset,some_timeout);
if(res > 0)
{
len = read(fd,buf,sizeof(buf));
if (len>0)
{
printf("Could read %u bytes. Continue.\n", len);
}
else
{
sleep(some_timeout_in_sec);
}
}
}
Now I want to re-write this in some asynchronous manner, using NSInputSource or some other async Objective-C technique.
The problem with NSInputSource: If I use scheduleInRunLoop: method then once I get NSStreamEventEndEncountered event, I stop receiving any events.
Can I still use NSInputSource or should I pass to using NSFileHandle somehow or what would you recommend ?
I see a few problems.
1) some_Timeout, for select() needs to be a struct timeval *.
2) for sleep() some_timeout needs to be an integer number of seconds.
3) the value in some_timeout is decremented via select() (which is why the last parameter is a pointer to the struct timeval*. And that struct needs to be re-initialized before each call to select().
4) the parameters to select() are highest fd of interest+1, then three separate struct fd_set * objects. The first is for input files, the second is for output files, the third is for exceptions, however, the posted code is using the same struct fd_set for both the inputs and the exceptions, This probably will not be what is needed.
When the above problems are corrected, the code should work.
I'm learning Objective-C and I'm having problems with this snippet of code: (scanf)
int main (int argc, const char * argv[])
{
#autoreleasepool {
double xnumber;
scanf("%1f",&xnumber);
printf("%f",xnumber);
}
return 0;
}
When I run this simple program, I cannot set the value of xnumber to anything. It alway returns zero no matter what I typed. This basic program it is just an input needed for many exercises... Can someone help me?
Use the "l" modifier to indicate you're reading a double
scanf("%lf", &xnumber);
scanf("%1f",&xnumber); you read a double,so change %1f to %lf.
you can read this http://www.dgp.toronto.edu/~ajr/209/notes/printf.html
I am trying to write some code that interacts with an USB device in Objective C, and I got stuck on setting the callback function for incoming reports. In my case it's an IOKIT function but I think the problem is more general as I (apparently) don't know how to correctly set a C callback function in Objective-C. I've got a Class "USBController" that handles the io functions
USBController.m:
#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h>
#include <IOKit/hid/IOHIDLib.h>
#import "USBController.h"
static void Handle_IOHIDDeviceIOHIDReportCallback(
void * inContext, // context from IOHIDDeviceRegisterInputReportCallback
IOReturn inResult, // completion result for the input report operation
void * inSender, // IOHIDDeviceRef of the device this report is from
IOHIDReportType inType, // the report type
uint32_t inReportID, // the report ID
uint8_t * inReport, // pointer to the report data
CFIndex InReportLength) // the actual size of the input report
{
printf("hello"); //just to see if the function is called
}
#implementation USBController
- (void)ConnectToDevice {
...
IOHIDDeviceRegisterInputReportCallback(tIOHIDDeviceRefs[0], report, reportSize,
Handle_IOHIDDeviceIOHIDReportCallback,(void*)self);
...
}
...
#end
All the functions are also declared in the header file.
I think I did pretty much the same as what I've found here, but it doesn't work. The project compiles nicely and everything works up till the moment there is input and the callback function is to be called. Then I get an "EXC_BAD_ACCESS" error. The first three arguments of the function are correct. I'm not so sure about the context..
What did I do wrong?
I am not sure at all that your EXEC_BAD_ACCESS depends on your callback. Indeed, if you say that it is called (I suppose you see the log) and since it only logs a message, there should be no problem with this.
EXEC_BAD_ACCESS is caused by an attempt to access an already deallocated object. You can get more information in two ways:
execute the program in debug mode, so when it crashes you will be able to see the stack content;
activate NSZombies or run the program using the performance tool Zombies; this will tell you exactly which object was accessed after its deallocation.
I know how to fix this. When calling this:
IOHIDDeviceRegisterInputReportCallback(tIOHIDDeviceRefs[0], report, reportSize,
Handle_IOHIDDeviceIOHIDReportCallback,(void*)self);
You don't include the code for the creation/type of the value called report. However the method name "Handle_IOHIDDeviceIOHIDReportCallback" comes from an Apple document where there is an error in the creation of the report value. https://developer.apple.com/library/archive/technotes/tn2187/_index.html
CFIndex reportSize = 64;
uint8_t report = malloc( reportSize ); // <---- WRONG
IOHIDDeviceRegisterInputReportCallback( deviceRef,
report,
reportSize,
Handle_IOHIDDeviceIOHIDReportCallback,
context );
Instead do this:
uint8_t *report = (uint8_t *)malloc(reportSize);