// minimized analog of sscanf #include #include #include "escanf.h" #include #include int escanf ( char* string, char* format, ...) { va_list argptr; // 2 variables for reading arguments char *fmtptr; static struct readstr strings[64]; // addresses of structures with strings struct readstr thestr; // address of the current structure char *begin, *end; // beginning and end of read string double *dnum; // read number, if float float *fnum; int *inum; // read number, if int char *outstr = (char*) malloc (512); // read string/char, if %s/%c int c; // loop variable int nread; // number of variables read // finding which string is dealt with or marking a new string for (c = 0; c < 64; c++ ) { // is a string already read? if ( strings[c].first == string ) { if (strcmp (strings[c].first, strings[c].old) != 0) //string changed { strings[c].curr = strings[c].first; strcpy (strings[c].old, strings[c].first); } break; } } if (c < 64) thestr = strings[c]; // string was already read else { // there were no such a string in for (c = 0; c < 64; c++ ) // strings[] if (strings[c].isused == 0 ) break; if (c < 64) { thestr = strings[c]; thestr.isused = 1; thestr.curr = thestr.first = string; thestr.old = (char*) malloc (512); strcpy (thestr.old, thestr.first); } else { printf ( "Attempt to open more than 64 strings in escanf\n" ); exit (1); } } // } // reading a format line and va_start (argptr, format); // argptr points at the first unnamed argument begin = thestr.curr; nread = 0; for (fmtptr = format; *fmtptr; fmtptr++) { while (*begin == ' ') begin++; while (*fmtptr == ' ') fmtptr++; if (*fmtptr != '%') { if (*begin != *fmtptr) { printf ("Umatched format in escanf\n"); exit (1); } else { begin++; fmtptr++; continue; } } if ( (*begin == '\0' || *begin == '\n') && *(fmtptr+1) != 'r' && *(fmtptr+1) != 'l' ) { thestr.isused = 0; thestr.first = NULL; free (thestr.old); strings[c] = thestr; free (outstr); if (nread) return (-1); else return (0); } if (end = (char*) strstr (begin, " ")) *end++ = '\0' ; switch (*++fmtptr) { // read format string case 'i': case 'd': // %i, %d - integer inum = va_arg (argptr, int*); *inum = atoi (begin); nread++; break; case 'f': // %f - float fnum = va_arg (argptr, float*); *fnum = atof (begin); nread++; break; case 'g': // %g - double dnum = va_arg (argptr, double*); *fnum = atof (begin); nread++; break; case 'c': // %c - usual char - not checked yet outstr = va_arg (argptr, char *); *outstr = *begin; nread++; break; case 's': // %s - string - not checked yet outstr = va_arg (argptr, char *); outstr = begin; nread++; break; case 'r': // read string from the beginning if (end) *(end-1) = ' '; // returning erased space thestr.curr = thestr.first; strings[c] = thestr; free (outstr); return (1); case 'l': thestr.isused = 0; thestr.first = NULL; free (thestr.old); strings[c] = thestr; free (outstr); return (1); } if (end) *(end-1) = ' '; // returning erased space begin = end; } va_end (argptr); thestr.curr = begin; // updating structures' strings[c] = thestr; free (outstr); return (1); }