From bug-octave-request at bevo dot che dot wisc dot edu Fri Sep 10 00:10:16 1999 Subject: scanf wierdness From: "John W. Eaton" To: bug-octave at bevo dot che dot wisc dot edu Cc: Alex Stark Date: Fri, 10 Sep 1999 00:10:15 -0500 (CDT) On 9-Sep-1999, Alex Stark wrote: | Help! | | I just don't understand this: | | octave:79> sscanf('L02282 GGGAACTAGA ACGATTCGCA GTTAATCCTG | CCCTGTTAGA AACATCAGAA','%1s',1) | ans = L | | octave:80> sscanf('L02282 GGGAACTAGA ACGATTCGCA GTTAATCCTG | CCCTGTTAGA AACATCAGAA','%2s',1) | ans = L | | octave:81> sscanf('L02282 GGGAACTAGA ACGATTCGCA GTTAATCCTG | CCCTGTTAGA AACATCAGAA','%3s',1) | ans = L02282GGGAACTAGA ACGATTCGCAGTTAATCCTG CCCTGTTAGAAACATCAGAA5S | | octave:82> sscanf('L02282 GGGAACTAGA ACGATTCGCA GTTAATCCTG | CCCTGTTAGA AACATCAGAA','%4s',1) | ans = L | | octave:83> sscanf('L02282 GGGAACTAGA ACGATTCGCA GTTAATCCTG | CCCTGTTAGA AACATCAGAA','%5s',1) | ans = L02282 GGGAACTAGAACGATTCGCAGTTAATCCTGCCCTGTTAGAAACATCAGAA | | octave:84> sscanf('L02282 GGGAACTAGA ACGATTCGCA GTTAATCCTG | CCCTGTTAGA AACATCAGAA','%6s',1) | ans = L02282GGGAACTAGA ACGATTCGCA GTTAATCCTG CCCTGTTAGA AACATCAGAA | | octave:86> sscanf('L02282 GGGAACTAGA ACGATTCGCA GTTAATCCTG | CCCTGTTAGA AACATCAGAA','%7s',1) | ans = L02282 GGGAACTAGA ACGATTCGCAGTTAATCCTG CCCTGTTAGAAACATCAGAA at È | t | | octave:87> sscanf('L02282 GGGAACTAGA ACGATTCGCA GTTAATCCTG | CCCTGTTAGA AACATCAGAA','%8s',1) | ans = L | | octave:88> version | ans = 2.0.14 | | Any ideas? | | (Linux with Redhat rpm: | Name : octave Relocations: /usr | Version : 2.0.14 Vendor: Red Hat Software | Release : 1 Build Date: Fri May 7 | 22:11:00 1999 | Install date: Mon Jul 26 12:54:14 1999 Build Host: | porky.devel.redhat.com | Group : Applications/Engineering Source RPM: | octave-2.0.14-1.src.rpm | ) It looks like a bug to me. Here is a patch to try. I think this should make Octave's scanf more compatible with Matlab's. Please try it and report any problems you find. Thanks, jwe Thu Sep 9 17:09:23 1999 John W. Eaton * oct-stream.cc (get_size): Allow zero values. (get_size) New arg, one_elt_size_spec. (do_scanf_conv): New arg, `conv_count'. Change instantiation requests and all callers. (octave_base_stream::do_scanf): Improve scanning of strings. (octave_base_stream::do_oscanf): Remove size limit on %s conversions. *** src/oct-stream.cc~ Fri Sep 10 00:01:16 1999 --- src/oct-stream.cc Fri Sep 10 00:02:26 1999 *************** *** 24,29 **** --- 24,30 ---- #include #endif + #include #include #include *************** *** 88,94 **** { if (! xisinf (d)) { ! if (d > 0.0) retval = NINT (d); else ::error ("%s: negative value invalid as size specification", --- 89,95 ---- { if (! xisinf (d)) { ! if (d >= 0.0) retval = NINT (d); else ::error ("%s: negative value invalid as size specification", *************** *** 104,114 **** } static void ! get_size (const Matrix& size, int& nr, int& nc, const char *warn_for) { nr = -1; nc = -1; double dnr = -1.0; double dnc = -1.0; --- 105,118 ---- } static void ! get_size (const Matrix& size, int& nr, int& nc, int& one_elt_size_spec, ! const char *warn_for) { nr = -1; nc = -1; + one_elt_size_spec = 0; + double dnr = -1.0; double dnc = -1.0; *************** *** 117,122 **** --- 121,128 ---- if (sz_nr == 1 && sz_nc == 1) { + one_elt_size_spec = 1; + dnr = size (0, 0); dnc = 1.0; } *************** *** 145,151 **** { nr = get_size (dnr, warn_for); ! if (! error_state && dnc > 0.0) nc = get_size (dnc, warn_for); } } --- 151,157 ---- { nr = get_size (dnr, warn_for); ! if (! error_state && dnc >= 0.0) nc = get_size (dnc, warn_for); } } *************** *** 879,885 **** int nr = -1; int nc = -1; ! get_size (size, nr, nc, "fread"); if (! error_state) { --- 885,893 ---- int nr = -1; int nc = -1; ! int ignore; ! ! get_size (size, nr, nc, ignore, "fread"); if (! error_state) { *************** *** 903,910 **** template void do_scanf_conv (istream& is, const char *fmt, T valptr, Matrix& mval, ! double *data, int& idx, int nr, int max_size, ! bool discard) { is.scan (fmt, valptr); --- 911,918 ---- template void do_scanf_conv (istream& is, const char *fmt, T valptr, Matrix& mval, ! double *data, int& idx, int& conv_count, int nr, ! int max_size, bool discard) { is.scan (fmt, valptr); *************** *** 923,963 **** } if (! discard) ! data[idx++] = *(valptr); } } template void do_scanf_conv (istream&, const char*, int*, Matrix&, double*, int&, ! int, int, bool); template void do_scanf_conv (istream&, const char*, long int*, Matrix&, double*, int&, ! int, int, bool); template void do_scanf_conv (istream&, const char*, short int*, Matrix&, double*, int&, ! int, int, bool); #if 0 template void do_scanf_conv (istream&, const char*, float*, Matrix&, double*, int&, ! int, int, bool); #endif template void do_scanf_conv (istream&, const char*, double*, Matrix&, double*, int&, ! int, int, bool); octave_value octave_base_stream::do_scanf (scanf_format_list& fmt_list, ! int nr, int nc, int& count) { ! count = 0; octave_value retval = Matrix (); istream *isp = input_stream (); bool all_char_conv = fmt_list.all_character_conversions (); --- 931,985 ---- } if (! discard) ! { ! conv_count++; ! data[idx++] = *(valptr); ! } } } template void do_scanf_conv (istream&, const char*, int*, Matrix&, double*, int&, ! int&, int, int, bool); template void do_scanf_conv (istream&, const char*, long int*, Matrix&, double*, int&, ! int&, int, int, bool); template void do_scanf_conv (istream&, const char*, short int*, Matrix&, double*, int&, ! int&, int, int, bool); #if 0 template void do_scanf_conv (istream&, const char*, float*, Matrix&, double*, int&, ! int&, int, int, bool); #endif template void do_scanf_conv (istream&, const char*, double*, Matrix&, double*, int&, ! int&, int, int, bool); octave_value octave_base_stream::do_scanf (scanf_format_list& fmt_list, ! int nr, int nc, int one_elt_size_spec, ! int& conversion_count) { ! conversion_count = 0; ! ! int data_index = 0; octave_value retval = Matrix (); + if (nr == 0 || nc == 0) + { + if (one_elt_size_spec) + nc = 0; + + return Matrix (nr, nc, 0.0); + } + istream *isp = input_stream (); bool all_char_conv = fmt_list.all_character_conversions (); *************** *** 965,981 **** Matrix mval; double *data = 0; int max_size = 0; int final_nr = 0; int final_nc = 0; ! if (nr > 0) { if (nc > 0) { mval.resize (nr, nc, 0.0); data = mval.fortran_vec (); max_size = nr * nc; } else { --- 987,1026 ---- Matrix mval; double *data = 0; int max_size = 0; + int max_conv = 0; int final_nr = 0; int final_nc = 0; ! if (all_char_conv) ! { ! if (one_elt_size_spec) ! { ! mval.resize (1, 512, 0.0); ! data = mval.fortran_vec (); ! max_size = 512; ! ! if (nr > 0) ! max_conv = nr; ! } ! else if (nr > 0 && nc > 0) ! { ! mval.resize (nr, 32, 0.0); ! data = mval.fortran_vec (); ! max_size = nr * 32; ! ! max_conv = nr * nc; ! } ! } ! else if (nr > 0) { if (nc > 0) { mval.resize (nr, nc, 0.0); data = mval.fortran_vec (); max_size = nr * nc; + + max_conv = max_size; } else { *************** *** 1003,1029 **** { if (elt) { ! if (count == max_size) { ! if (nr > 0) { ! if (nc > 0) ! { ! final_nr = nr; ! final_nc = nc; ! break; ! } ! else ! { ! max_size *= 2; ! mval.resize (nr, max_size / nr, 0.0); ! data = mval.fortran_vec (); ! } } else { ! max_size *=2; mval.resize (max_size, 1, 0.0); data = mval.fortran_vec (); } --- 1048,1079 ---- { if (elt) { ! if (max_conv > 0 && conversion_count == max_conv) { ! if (all_char_conv && one_elt_size_spec) { ! final_nr = 1; ! final_nc = data_index; ! } ! else ! { ! final_nr = nr; ! final_nc = (data_index - 1) / nr + 1; ! } ! break; ! } ! else if (data_index == max_size) ! { ! if (nr > 0) ! { ! max_size *= 2; ! mval.resize (nr, max_size / nr, 0.0); ! data = mval.fortran_vec (); } else { ! max_size *= 2; mval.resize (max_size, 1, 0.0); data = mval.fortran_vec (); } *************** *** 1050,1056 **** case 'h': { short int tmp; ! do_scanf_conv (is, fmt, &tmp, mval, data, count, nr, max_size, discard); } break; --- 1100,1107 ---- case 'h': { short int tmp; ! do_scanf_conv (is, fmt, &tmp, mval, data, ! data_index, conversion_count, nr, max_size, discard); } break; *************** *** 1058,1064 **** case 'l': { long int tmp; ! do_scanf_conv (is, fmt, &tmp, mval, data, count, nr, max_size, discard); } break; --- 1109,1116 ---- case 'l': { long int tmp; ! do_scanf_conv (is, fmt, &tmp, mval, data, ! data_index, conversion_count, nr, max_size, discard); } break; *************** *** 1066,1072 **** default: { int tmp; ! do_scanf_conv (is, fmt, &tmp, mval, data, count, nr, max_size, discard); } break; --- 1118,1125 ---- default: { int tmp; ! do_scanf_conv (is, fmt, &tmp, mval, data, ! data_index, conversion_count, nr, max_size, discard); } break; *************** *** 1078,1084 **** { double tmp; ! do_scanf_conv (is, fmt, &tmp, mval, data, count, nr, max_size, discard); } break; --- 1131,1138 ---- { double tmp; ! do_scanf_conv (is, fmt, &tmp, mval, data, ! data_index, conversion_count, nr, max_size, discard); } break; *************** *** 1089,1109 **** case 's': { ! int len = strlen (fmt); ! char *tmp_fmt = new char [len+1]; ! strcpy (tmp_fmt, fmt); ! if (tmp_fmt[len-1] == 's') ! tmp_fmt[len-1] = 'c'; ! int width = elt->width ? elt->width : 1; ! char *tmp = new char [width+1]; ! is.scan (tmp_fmt, tmp); ! delete [] tmp_fmt; ! tmp[width] = '\0'; if (is) { --- 1143,1188 ---- case 's': { ! int width = elt->width; ! if (elt->type == 'c' && width == 0) ! width = 1; ! char *tmp = 0; ! if (width) ! { ! tmp = new char [width+1]; ! is.scan (fmt, tmp); ! tmp[width] = '\0'; ! } ! else ! { ! // We're looking at a `%s' format. We have to ! // skip initial whitespace and then read until ! // the next whitespace character. ! ! ostrstream buf; ! ! int c = EOF; ! ! while (is && (c = is.get ()) != EOF && isspace (c)) ! /* skip leading whitespace */; ! ! if (is && c != EOF) ! buf << (char) c; ! ! while (is && (c = is.get ()) != EOF && ! isspace (c)) ! buf << (char) c; ! ! buf << ends; ! ! tmp = buf.str (); ! } ! ! width = strlen (tmp); if (is) { *************** *** 1111,1119 **** if (! discard) { while (i < width && tmp[i] != '\0') { ! if (count == max_size) { max_size *= 2; --- 1190,1200 ---- if (! discard) { + conversion_count++; + while (i < width && tmp[i] != '\0') { ! if (data_index == max_size) { max_size *= 2; *************** *** 1125,1131 **** data = mval.fortran_vec (); } ! data[count++] = tmp[i++]; } } } --- 1206,1212 ---- data = mval.fortran_vec (); } ! data[data_index++] = tmp[i++]; } } } *************** *** 1151,1172 **** } else if (! is) { ! if (nr > 0) { ! if (count > nr) { final_nr = nr; ! final_nc = (count - 1) / nr + 1; } else { ! final_nr = count; final_nc = 1; } } else { ! final_nr = count; final_nc = 1; } --- 1232,1271 ---- } else if (! is) { ! if (all_char_conv) { ! if (one_elt_size_spec) ! { ! final_nr = 1; ! final_nc = data_index; ! } ! else if (data_index > nr) { final_nr = nr; ! final_nc = (data_index - 1) / nr + 1; } else { ! final_nr = data_index; ! final_nc = 1; ! } ! } ! else if (nr > 0) ! { ! if (data_index > nr) ! { ! final_nr = nr; ! final_nc = (data_index - 1) / nr + 1; ! } ! else ! { ! final_nr = data_index; final_nc = 1; } } else { ! final_nr = data_index; final_nc = 1; } *************** *** 1199,1215 **** { mval.resize (final_nr, final_nc, 0.0); ! if (all_char_conv) ! { ! if (nr < 0) ! mval = mval.transpose (); ! ! retval = mval; ! retval = retval.convert_to_str (); ! } ! else ! retval = mval; } return retval; --- 1298,1307 ---- { mval.resize (final_nr, final_nc, 0.0); ! retval = mval; ! if (all_char_conv) ! retval = retval.convert_to_str (); } return retval; *************** *** 1272,1281 **** int nr = -1; int nc = -1; ! get_size (size, nr, nc, "fscanf"); if (! error_state) ! retval = do_scanf (fmt_list, nr, nc, count); } break; } --- 1364,1375 ---- int nr = -1; int nc = -1; ! int one_elt_size_spec; ! ! get_size (size, nr, nc, one_elt_size_spec, "fscanf"); if (! error_state) ! retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec, count); } break; } *************** *** 1372,1394 **** case 's': { ! // XXX FIXME XXX -- this must be fixed! ! int width = elt->width ? elt->width : 65535; ! char *tmp = new char [width+1]; ! if (is.scan (fmt, tmp)) { ! if (! discard) ! { ! tmp[width] = '\0'; ! retval = tmp; ! } } else ! quit = true; delete [] tmp; } break; --- 1466,1514 ---- case 's': { ! int width = elt->width; ! char *tmp = 0; ! if (width) { ! tmp = new char [width+1]; ! ! is.scan (fmt, tmp); ! ! tmp[width] = '\0'; } else ! { ! // We're looking at a `%s' format. We have to ! // skip initial whitespace and then read until ! // the next whitespace character. ! ! ostrstream buf; ! ! int c = EOF; ! ! while (is && (c = is.get ()) != EOF && isspace (c)) ! /* skip leading whitespace */; ! ! if (is && c != EOF) ! buf << (char) c; ! ! while (is && (c = is.get ()) != EOF && ! isspace (c)) ! buf << (char) c; ! ! buf << ends; ! ! tmp = buf.str (); ! ! if (! discard) ! retval = tmp; ! } delete [] tmp; + + if (! is) + quit = true; } break; *** oct-stream.h~ Fri Feb 6 10:48:03 1998 --- oct-stream.h Fri Sep 10 00:04:25 1999 *************** *** 315,321 **** int nr, int nc, int& count); octave_value do_scanf (scanf_format_list& fmt_list, int nr, int nc, ! int& count); octave_value scanf (const string& fmt, const Matrix& size, int& count); --- 315,321 ---- int nr, int nc, int& count); octave_value do_scanf (scanf_format_list& fmt_list, int nr, int nc, ! int one_elt_size_spec, int& count); octave_value scanf (const string& fmt, const Matrix& size, int& count); --------------------------------------------------------------------- Octave is freely available under the terms of the GNU GPL. To ensure that development continues, see www.che.wisc.edu/octave/giftform.html Instructions for unsubscribing: www.che.wisc.edu/octave/archive.html ---------------------------------------------------------------------