program stuck when reading file on.get function - c++

I'm creating a program on win32, the program stops responding on .get function, I don't know what to do else, I think the problem is with std::ifstream inFile; but I need it outside of the main program, so I can use it in everywhere, for example here I use inFile in WM_CREATE and also in WM_KEYDOWN and close the file when the window closes. is it posible to do?
char Map[10][10], c[256];
std::ifstream inFile;
//windProc
case WM_CREATE: {
inFile.open ("Map.txt");
if (!inFile) {
::MessageBox(hwnd, "Failed to open file", "Error", MB_OK);
}
int i,j;
do { //loop for skipping comments
Map[j][i] = inFile.get(); //<---stuck here
if (Map[j][i] ==';') inFile.getline(c, 256);
} while (Map[j][i] ==';');
while (Map[j][i] !=';') { //loop for painting
switch (Map[j][i]) {
//
//paint based on char
//
}
i++;
Map[j][i] = inFile.get();
if (i==10) {j++; i=0;}
}
}
case WM_KEYDOWN: {
//...
inFile.getline(c, 256); // continue reading from file
int j=0; int i=0;
Map[j][i] = inFile.get();
while (Map[j][i] !=';') {
switch (Map[j][i]) {
//
//paint based on char
//
}
i++;
Map[j][i] = inFile.get();
if (i==10) {j++; i=0;}
}
break; }
case WM_DESTROY:
inFile.close();
PostQuitMessage (0);
break;

If the steam enters error/eof state in your while loop, Map[j][i] won't ever be set to ';' resulting in an endless loop:
do { //loop for skipping comments
Map[j][i] = inFile.get(); //<---stuck here
if (Map[j][i] ==';') inFile.getline(c, 256);
} while (inFile.good() && Map[j][i] ==';');

Your problem is that you're not initializing i and j. Try initializing them to 0. Also, you presumably want to update them in your loop so you don't continuously store the character in the same element.
Then you need to reinitialize i and j to 0 before the painting loop. However, painting is usually done in WM_PAINT (I'm not even sure it'll work in WM_CREATE.)

Related

Making program to close automatically after clicking on NO on a MessageBox (C++)

I'm learning C++ programming at school and by myself as well. Now I'm trying to make some upgrades on the visual experience and on the user interface. My question is that can I close the program after a simple click on a MessageBox's "NO" button. I whant to skip "Press any key to contiue" after the program ran. Here is the code:
`
#include<iostream>
#include<windows.h>
#include<stdlib.h>
using namespace std;
int main()
{
MessageBox ( NULL, "7. Adott az a(i), i=1,n szamsor. Hozzuk létre a b szamsort", "Feladat szovege", MB_OK);
float a[111], b[111], n;
cout<<"n= ?\b";
MessageBox ( HWND_DESKTOP, "Kerlek irj be egy szamot, hogy hany ertek van a sorozatban!", "10_tombok/07", MB_OK);
cin>>n;
cout<<"\n";
for(int i=1; i<=n; i++)
{
cout<<"a"<<i<<"= ?\b";
cin>>a[i];
}
for(int i=1; i<=n; i++)
{
if (a[i]>=0)
{
b[i]=2*a[i];
}
else
{
b[i]=-a[i]/2;
}
}
cout<<"\nA 'b' szamsor: ";
for(int i=1; i<=n; i++)
{
if (i!=n)
cout<<b[i]<<", ";
else
cout<<b[i]<<"\n";
}
int mbID= MessageBox (NULL, "Szeretned ujra futtatni a programot?", "Program end", MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2);
switch (mbID)
{
case IDYES:
{
return main();
break;
}
case IDNO:
{
//here i need something
return 0;
break;
}
}
`
To address the question, if running from within Visual Studio you will get the "Press any key to continue." prompt. Try running the executable directly.
For the question in your comment, use a loop. At the very least something like this:
int main()
{
int done = 0;
while(!done)
{
// skipping all the other program code above...
switch (mbID)
{
case IDYES:
break;
case IDNO:
done = 1;
break;
}
}
return 0;
}
It is actually undefined behavior to call main() from within your C++ program.
If you are really interested in Windows UI programming, have a look at some Win32 or MFC tutorials. It is a bit different from building console applications.

C++ how do I terminate my programm using ESC button

Here is my main function i use visual studio 2012 express and the code works fine. My question is how will i terminate this loop when the user Presses the ESC button instead of -1. Although i would prefer a solution that works both in unix and windows, if it is not possible i am most interested in it working for windows.
int _tmain(int argc, _TCHAR* argv[])
{
list mylist;
int value;
cout<<"Give the numbers you want to insert to the list, press -1 to stop\n";
do
{
cin>>value;
mylist.insertf(value);
mylist.sort_list();
mylist.print();
}while(value!=-1);
}
Here are solution for Windows
First solution:
Esc will not be handled when user starts to type till pressing enter.
While idle Esc will be handled
#include <Windows.h>
#include <iostream>
#include <conio.h>
#include <vector>
int main(int argc, char **argv)
{
int value=0;
std::vector<int> mylist;
do
{
//check if any input.
if (_kbhit()){
//probable user started to type
//block to read till the user press Enter. If you want to handle Esc here .
//then you should manually do input reading . I will write that solution later
std::cin>>value;
//if success
if(std::cin.good()){
mylist.push_back(value);
}else{
//firstly, clear error flag
std::cin.clear();
//ignore
std::cin.ignore(10000,'\n');
}
//print list
std::cout<<"new list: { " ;
for(int i=0;i< mylist.size();i++){
std::cout<<mylist[i]<<'\t';
}
std::cout<<" }"<<std::endl;
}
//check if Esc Pressed
}while(GetAsyncKeyState(VK_ESCAPE)==0);
return 0;
}
Second Solution:
Esc will be handled always in another thread. Immediate exit can be undesirable on some cases
DWORD WINAPI CheckEscape( LPVOID lpParam ) {
while(GetAsyncKeyState(VK_ESCAPE)==0){
//sleep
Sleep(10);
}
exit(0);
}
int main(int argc, char **argv)
{
int value=0;
std::vector<int> mylist;
//create thread for handling ESC key
CreateThread( NULL, 0, CheckEscape,NULL , 0, NULL);
//loop infinitely
while(true)
{
std::cin>>value;
//if success
if(std::cin.good()){
mylist.push_back(value);
}else{
//firstly, clear error flag
std::cin.clear();
//ignore
std::cin.ignore(10000,'\n');
}
//print list
std::cout<<"new list: { " ;
for(int i=0;i< mylist.size();i++){
std::cout<<mylist[i]<<'\t';
}
std::cout<<" }"<<std::endl;
}
return 0;
}
Third Solution and the Best one .Do everything manually
Handling keypress manually.
Exit will be called when Esc is Pressed. You can change it to handle more right way
bool keypress( char &key){
INPUT_RECORD IR[1];
DWORD read;
static HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
while(PeekConsoleInputA(h,IR,1,&read)){
if(read!=0){
//check if it was Key Event
if(IR[0].EventType==KEY_EVENT){
key=IR[0].Event.KeyEvent.uChar.AsciiChar;
ReadConsoleInputA(h,IR,1,&read);
FlushConsoleInputBuffer(h);
return true;
}
if(ReadConsoleInputA(h,IR,1,&read)){
continue;
}
}else{
return false;
}
}
}
//getnumber
int cinnumb( ){
char buffer[32];
buffer[0]='\0';
int count=0;
DWORD key=-1;
while(true){
Sleep(100);
do{
//here I make it nonblockin keypress
//but actually we do not need it
//we can use blocking ReadConsoleInputA(h,IR,1,&read);
//this way we not even need sleep() and
//our keypress function will be simple
//anyway im posting nonblocking one
//nonblocking keypress
char key=0;
bool isOk=keypress(key );
if(!isOk ){
Sleep(20);
continue;
}
if(key>='0' && key<='9'){
buffer[count]=key;
std::cout<<key;
++count;
if( count==31)break;
}
// check Enter key and enough symbol
if( key==13 && count>0 ){
std::cout<<std::endl;
break;
}
//for windows
//check if Esc pressed
if(key==27) exit(0);
}while(true);
buffer[count]='\0';
int value=atoi(buffer);
return value;
}
}
int main(int argc, _TCHAR* argv[])
{
std::vector<int> mylist;
int value;
char buffer[100];
//infinite loop
while(true)
{
//get number
value=cinnumb();
mylist.push_back(value);
//print list
std::cout<<"new list: { " ;
for(int i=0;i< mylist.size();i++){
std::cout<<mylist[i]<<'\t';
}
std::cout<<" }"<<std::endl;
//sleep a little
Sleep(10);
} ;
return 0;
}

Wait for input for a certain time

Is there any function that can wait for input until a certain time is reached? I'm making kind of Snake game.
My platform is Windows.
For terminal based games you should take a look at ncurses.
int ch;
nodelay(stdscr, TRUE);
for (;;) {
if ((ch = getch()) == ERR) {
/* user hasn't responded
...
*/
}
else {
/* user has pressed a key ch
...
*/
}
}
Edit:
See also Is ncurses available for windows?
I found a solution using kbhit() function of conio.h as follows :-
int waitSecond =10; /// number of second to wait for user input.
while(1)
{
if(kbhit())
{
char c=getch();
break;
}
sleep(1000); sleep for 1 sec ;
--waitSecond;
if(waitSecond==0) // wait complete.
break;
}
Try with bioskey(), this is an example for that:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <bios.h>
#include <ctype.h>
#define F1_Key 0x3b00
#define F2_Key 0x3c00
int handle_keyevents(){
int key = bioskey(0);
if (isalnum(key & 0xFF)){
printf("'%c' key pressed\n", key);
return 0;
}
switch(key){
case F1_Key:
printf("F1 Key Pressed");
break;
case F2_Key:
printf("F2 Key Pressed");
break;
default:
printf("%#02x\n", key);
break;
}
printf("\n");
return 0;
}
void main(){
int key;
printf("Press F10 key to Quit\n");
while(1){
key = bioskey(1);
if(key > 0){
if(handle_keyevents() < 0)
break;
}
}
}
Based on #birubisht answer I made a function which is a bit cleaner and uses NON-deprecated versions of kbhit() and getch() - ISO C++'s _kbhit() and _getch().
Function takes: number of seconds to wait for user input
Function returns: _ when user does not put any char, otherwise it returns the inputed char.
/**
* Gets: number of seconds to wait for user input
* Returns: '_' if there was no input, otherwise returns the char inputed
**/
char waitForCharInput( int seconds ){
char c = '_'; //default return
while( seconds != 0 ) {
if( _kbhit() ) { //if there is a key in keyboard buffer
c = _getch(); //get the char
break; //we got char! No need to wait anymore...
}
Sleep(1000); //one second sleep
--seconds; //countdown a second
}
return c;
}

C++ processes and pipes

I working my way through a C++ and Operating Systems book and I've come upon an assignment that requires creation, writing, and reading from pipes. However my program stalls on reading from the second pipe. My program is to accept input and parse out a space delimited string into tokens and classifying those tokens accordingly. My code is bellow with my problem area marked. Any help is as always very appreciated.
edit: This is supposed to have two children. One for processing the space delimited tokens and the other for determining the type of delimited tokens. As far as debugging goes I only have access to cout as a debugger. So I inserted a cout before the read and after the one before the read appeared but the one after did not.
#include <iostream>
#include <fstream>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
using namespace std;
//declaring the pipes
int pipeOne[2];
int pipeTwo[2];
struct inputStruct {
char str[256]; /* one extra spot for \n */
int len; /* length of str */
int flag; /* 0 for normal input, 1 to indicate “done” */
};
struct tokenStruct {
char token[256]; /* tokens can be 255 max */
int flag; /* same as inputStruct */
int tokenType; /* a code value */
};
void dataProcess(){
//new input struct to contain the the input from the parent
inputStruct input;
//the intial read from the pipe to populate the input stuct
read( pipeOne[0], (char*)&input, sizeof(inputStruct));
//set the flag
int flag = input.flag;
while (flag != 1){
int size = 0;
//get the size of the array up until the null character
while (input.str[size] != '\0'){
size++;
}
//Here's the parsing of each token
for (int i=0; i<size; i++) {
int tokenLength;
tokenStruct token;
//while the char isn't white space or null increment through it
while (input.str[i] != ' ' && input.str[i] != '\0') {
//a is the index of the string token
int a = 0;
//write the parsed string
token.token[a] = input.str[i];
a++;
i++;
}
//write to process 2
write(pipeTwo[1], (char*)&token, sizeof(tokenStruct));
}
//read again and store the results
read(pipeOne[0], (char*)&input, sizeof(inputStruct));
flag = input.flag;
}
tokenStruct token;
token.flag = flag;
//final write to the second child to tell it to commit suicide
write(pipeTwo[1], (char*)&token, sizeof(tokenStruct));
exit(0);
}
void tokenClassifer(){
tokenStruct token;
//Problem area is here on ****************************************************
//the initial read
read(pipeTwo[0], (char*)&token, sizeof(tokenStruct));
while (token.flag != 1){
int size = 0;
//get the size of the array up until the null character
while (token.token[size] != '\0'){
size++;
}
if (size == 1) {
//check for the one char things first
switch (token.token[0])
{
case '(':
token.tokenType = 0;
break;
case ')':
token.tokenType = 0;
break;
case ';':
token.tokenType = 0;
break;
case '+':
token.tokenType = 1;
break;
case '-':
token.tokenType = 1;
break;
case '/':
token.tokenType = 1;
break;
case '*':
token.tokenType = 1;
break;
default:
if (isdigit(token.token[0])) {
token.tokenType = 2;
} else {
token.tokenType = 3;
}
break;
}
} else {
bool isStr;
int i = 0;
//check for the more than one character
while (token.token[i] != '\0'){
//check if it's a string or digits
if (isdigit(token.token[0])) {
isStr=false;
} else{
//set up the bools to show it is a string
isStr=true;
break;
}
}
//if it is a string token type 3
if (isStr) {
token.tokenType = 3;
} else {
//if not then it's digits and token type 2
token.tokenType = 2;
}
}
//print out the token and token type
cout << "Token type is: " << token.tokenType << "Token value is: " << token.token << "\n";
//read the pipe again and start the process all over
read(pipeTwo[0], (char*)&token, sizeof(tokenStruct));
}
exit(0);
}
int main()
{
//create the pipes for reading and writing between processes
pipe(pipeOne);
pipe(pipeTwo);
//fork off both processes
int value = fork();
int value2 = fork();
//do the process for the first fork
if(value == 0){
//fork one
dataProcess();
} else {
wait(0);
}
//do the process for the second fork
if (value2 == 0) {
//fork two
//the token classifer function for the second fork
tokenClassifer();
} else {
cout << "Type some tokens (or just press enter to quit) \n";
//this is all of the parent functions
for (string line; getline(cin, line); )
{
inputStruct input;
if (line.empty())
{
// if the line is empty, that means the user didn't
// press anything before hitting the enter key
input.flag = 1;
write( pipeOne[1], (char*)&input, sizeof(inputStruct));
break;
} else {
//else copy the string into an array
strcpy(input.str, line.c_str());
//set the flag to zero to show everthing is ok
input.flag = 0;
}
//write the stuct to the pipe
write( pipeOne[1], (char*)&input, sizeof(inputStruct));
cout << "Type some tokens (or just press enter to quit) \n";
}
wait(0);
}
}
One problem that is evident:
//fork off both processes
int value = fork();
int value2 = fork();
This will fork 3 new processes. The initial fork will leave you with two processes, each of which go on to fork a new process.
EDIT:
Proper forking:
int value = fork();
if (value == 0) {
// do child stuff
exit(0);
} else if (value == -1) {
//fork failed
}
int value2 = fork();
if (value2 == 0) {
//do child stuff
exit(0);
} else if (value2 == -1) {
//fork failed
}
I'm actually not quite clear about how data goes through your program, so I'll leave it to you to add the waits. I'd actually change the names of value and value2, but that's just me. Also, I'm only addressing the forking issue here so there may be other problems with your code (which I kind of suspect since you have two pipes).
EDIT 2:
Another issue that I see is that you're not closing the ends of the pipes that you don't use. If you never close the write end of a pipe, your reads will block until the pipe has data (or there are no more writers to the pipe, that is, the write end is not open). This means that the write end of the pipe should be closed in all processes when you are not using it or are finished with it.

string manipulating in C?

I want to print an array of characters, these characters are underscores first.
Then the user can write characters on these underscores.I used gotoxy() but it doesn't work properly.
That is what i wrote:
int main(void)
{
char arr[20];
int i;
char ch;
clrscr();
for(i=0;i<=20;i++)
{
textattr(0x07);
cprintf("_");
}
do
{
for(i=0;i<=20;i++)
{
//gotoxy(i,0);
//ch = getche();
if( isprint(ch) == 1)
{
arr[i] = ch;
gotoxy(i,0);
//printf("%c",ch);
}
}
} while(i == 20);
getch();
return 0;
}
The first thing is this: You probably don't want to have all those calls to gotoxy, textattr and cprintf in your main function, since that is not what the main function is supposed to do.
It is much more likely that the main function's purpose is "to read some text from the user, presented nicely in an input field". So you should make this a function:
static int
nice_input_field(char *buf, size_t bufsize, int x, int y) {
int i, ch;
gotoxy(x, y);
for (i = 0; i < bufsize - 1; i++) {
cprintf("_");
}
i = 0;
gotoxy(x, y);
while ((ch = readkey()) != EOF) {
switch (ch) {
case '...': /* ... */
break;
case '\b': /* backspace */
cprintf("_");
i--;
gotoxy(x + i, y);
break;
case '\t': /* tabulator */
case '\n': /* enter, return */
buf[i] = '\0';
return 0; /* ok */
default: /* some hopefully printable character */
if (i == bufsize - 1) {
cprintf("\a"); /* beep */
} else {
buf[i++] = ch;
gotoxy(x + i, y);
cprintf("%c", buf[i]);
}
}
}
/* TODO: null-terminate the buffer */
return 0;
}
Printing an array of characters is fairly easy:
char* str = your_array;
while(*str) {
putc(*str++);
}
From memory that should print a string out to the screen.
Your code is very DOS-specific. There is not a good general solution to the problem of reading immediate input in a portable way. It does get asked quite often, so I think the C FAQ broke down and included an answer which you might want to seek out.
That said, I think your bug is that gotoxy(1, 1) is the upper corner of the screen, not 0,0. So you want gotoxy(i, 1)