Re: Simple console input / output framework for teaching beginners
On Sun, 25 May 2014 16:48:52 -0700 (PDT), "K. Frank"
<kfrank29.c@gmail.com> wrote:
Hello Group!
Could people suggest a simple program that illustrates using
console input with basic error handling that would be suitable
for rank beginners?
i had the same think but with the C language....
so i wrote one library for include the right functions
and so the exercise program can be link with library function
free for use
i not know if they are right
_____________________________________________
/*
libreria.dll
per costruire la .dll e la .lib usare
usare:
bcc32 -v -WD libreria.c
implib libreria.lib libreria.dll
*/
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <windows.h>
// ritorna un puntatore da liberarsi tramite free()
// 0 per errore
char* __export GetLine(char* testo)
{unsigned s, i, vMax=UINT_MAX-1032; // 1024+4+1 [+ 3]=1032
int c;
char *p,*t;
s=1024; p=malloc(s+4);
if(p==0) return 0;
if(testo!=0 && printf("%s", testo)<0)
{la: free(p); return 0;}
if(fflush(stdout)!=0)
goto la;
for(i=0; (c=getchar())!=EOF ; )
{if(i>=s)
{if(s>=vMax)
goto la;
s=s+1024;
t=realloc(p, s+4);
if(t==0)
goto la;
p=t;
}
p[i]=c; ++i;
if(c=='\n')
break;
}
if(ferror(stdin))
goto la;
p[i]=0;
return p;
}
// fa apparire il testo nello schermo e prende una stringa
// da stdin
// ritorna un puntatore a una *stringa* da liberare con free().
// ritorna 0 per errore.
char* __export GetLineI(char* testo)
{unsigned s, i;
int c, r;
char *p,*t;
s=1024; p=malloc(s+4); if(p==0) return 0;
r=printf("%s", testo); if(r< 0) goto li;
r=fflush(stdout); if(r==EOF) goto li;
for(i=0; (c=getchar())!=EOF ; )
{if(i>=s)
{s=s+1024;
if(s+4>(unsigned) INT_MAX )
goto li;
t=realloc(p, s+4);
if(t==0)
{li: free(p); return 0;}
p=t;
}
p[i]=c; ++i;
if(c=='\n') break;
}
p[i]=0;
if(ferror(stdin))
goto li;
return p;
}
// par: res: pointer to string of input
// testo: string to write to the screen
// return
// (unsigned)-1 for error
// or if ok return the len of string in res
unsigned __export GetLineII(char** res, char* testo)
{unsigned s, i;
int c, r;
char *p,*t;
if(res==0) return -1;
s=1024; p=malloc(s+4); if(p==0) return -1;
r=printf("%s", testo); if(r < 0) goto li;
r=fflush(stdout); if(r==EOF) goto li;
for(i=0; (c=getchar())!=EOF ; )
{if(i>=s)
{s=s+1024;
if(s+4>(unsigned) INT_MAX )
goto li;
t=realloc(p, s+4);
if(t==0)
{li: free(p); return -1;}
p=t;
}
p[i]=c; ++i;
if(c=='\n') break;
}
p[i]= 0;
*res= p;
if(ferror(stdin))
return -1;
return i;
}
// ritorna INT_MIN per errore
int __export GetInt(char* testo)
{int i,c;
long v;
char arr[1028], *p=0;
printf("%s", testo); fflush(stdout);
for(i=0; i<1024; ++i)
{c=getchar();
if(c==EOF||c=='\n')
break;
arr[i]=(char)c;
}
arr[i]=0;
if(i==1024) // elimina la linea fino a '\n'
{while((c=getchar())!=EOF)
if(c=='\n') break;
return INT_MIN;
}
v=strtol(arr, &p, 10);
if(v<INT_MIN||v>INT_MAX||p==arr)
return INT_MIN;
return (int) v;
}
// ritorna UINT_MAX per errore
unsigned __export GetUns(char* testo)
{int i,c;
unsigned long v;
char arr[1028], *p=0;
printf("%s", testo); fflush(stdout);
for(i=0; i<1024; ++i)
{c=getchar();
if(c==EOF||c=='\n')
break;
arr[i]=(char)c;
}
arr[i]=0;
if(i==1024) // elimina la linea fino a '\n'
{while((c=getchar())!=EOF)
if(c=='\n') break;
return UINT_MAX;
}
v=strtoul(arr, &p, 10);
if(v>UINT_MAX||p==arr)
return UINT_MAX;
return (unsigned) v;
}
// ritorna DBL_MIN per errore
double __export GetDouble(char* testo)
{int i,c;
double v;
char arr[1028], *p=0;
printf("%s", testo); fflush(stdout);
for(i=0; i<1024; ++i)
{c=getchar();
if(c==EOF||c=='\n')
break;
arr[i]=(char)c;
}
arr[i]=0;
if(i==1024) // elimina la linea fino a '\n'
{while((c=getchar())!=EOF)
if(c=='\n') break;
return DBL_MIN;
}
v=strtod(arr, &p);
if(v==HUGE_VAL||p==arr)
return DBL_MIN;
return v;
}
void __export err(char* i)
{printf("Errore: ");
if(i) printf("%s", i);
printf("\nEsco\n");
exit(0);
}
int WINAPI
DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*
lpReserved)
{(void) hinst; (void) lpReserved;
if(reason == DLL_PROCESS_ATTACH){}
else if(reason == DLL_PROCESS_DETACH){}
return 1;
}
-----------------
libreria.h
#include <float.h>
#include <limits.h>
char* __import GetLineI (char* testo);
int __import GetInt (char* testo);
unsigned __import GetUns (char* testo);
double __import GetDouble(char* testo);
void __import err(char* i);
-------------------
use as
double b;
b=GetDouble("insert a double: ");
if(b==DBL_MIN) error123();
etc
Some context and more detail:
The question comes up from time to time as to whether it makes sense
to use C++ to teach programming to new programmers. (I think the
answer is yes, but this particular issue is not really my question.)
If you want to do so, you need to teach them basic programming
concepts, good programming habits, and good C++ programming
habits before you teach them all, or most, a lot, or even some
of the intricacies of C++.
Imagine that you are teaching a beginning programming class that
uses C++, and that the students have written their "hello world"
program, have a text editor or ide, and have made their peace with
whatever compile / build process they are using. Now you want them
to start writing simple programs that perform various simple tasks
on input data, and you want them to be able to read in data from the
console (cin), and write the results to the console (cout). (For the
sake of argument, let's stick to using cin rather than argc / argv
for input.)
But you want your students to be able to input their data in some
reasonably convenient way, and not have their program exit (or crash)
every time they mis-type some input data on the console (and you also
want your students to start facing the reality that the outside world
is not so accommodating as to make programming trivial, and you need to
have some kind of validation and error checking for input data, and,
ideally, need to give your users some support with thier data input).
So "cin >> var1 >> var2 >> var3; do_computation (var1, var2, var2);"
is out.
One approach might be to write a message to cout such as "enter var1,
var2, and var3", enter a loop in which you read in the data, verify,
and either print out a "try-again" message or accept it. You might do
this a couple of times if there were a couple of different chunks of
data you needed to read in. (But maybe there are other good approaches.)
What sample program would you suggest to give your students a basic
framework for this kind of simple data input? They wouldn't necessarily
be able to use the code unchanged from program to program, but it should
be suitable for use in similar, but distinct applications, if only through
copy-paste-modify.
Ideally, you should be able to walk the students through the sample in
one class period, and they should be able to understand the code and the
basic logic, even if they don't understand all of the nuances.
(For example, you would probably use std:string. If so, the students
presumably won't know (yet) that std::string is a specialized template,
or even that std::string is a library class, rather than a primitive type.
But they should know -- after you tell them -- that std::string is a type
that holds the value of a string, and is a good first choice for working
with strings.)
The idea is to give the students something that -- within the context of
being one of the earliest programs they encounter, and subsequently write
on their own -- starts them on the path of using modern C++ idioms (specifically
C++11), and good C++ habits.
There is clearly a trade-off between truly good code and code simple enough
for rank beginners. But within the constraint of the necessary simplicity
we want to start illustrating good programming habits.
Any comments and suggestions would be very welcome.
K. Frank