K
Keith Thompson
W. eWatson said:Rats. I missed it in the index. It's a lame description.
What book are you using?
W. eWatson said:Rats. I missed it in the index. It's a lame description.
Correct, but I found the mistake.^[...] Here's what I have:
while(fgets(str,70,p)!=NULL){
n=sscanf(str,"%5f", &value);
printf("value = %5.1f %d\n", value,n);
one decimal place^^}
value is float. str is char str[70];
Here's what the program produces:
value = 0.00 0
two decimal places
The code you've shown isn't the code you're running.
Comprehensive C.What book are you using?
The columns are fixed, so I would expect
20.3
1.45
to appear as they are.
Interesting about %5f. It appears that a specifier with a decimal, e.g.,
%10.3, is only available when a printf (or similar cmd) is used.
Correct.
I decided to catch the output of sscanf. Here's what I have:
while(fgets(str,70,p)!=NULL){
n=sscanf(str,"%5f", &value);
printf("value = %5.1f %d\n", value,n);
}
value is float. str is char str[70];
Here's what the program produces:
value = 0.00 0
[...]
value = 0.00 -1
About 39 lines!!!
n goes negative?
I was right when I mentioned the above post as "Maybe the culprit is
that I'm using a data file that was produced in Win7? End of line
incompatibility?"
Now my problem is to read an entire line. [...]
The real data I ultimately need is from a fortran name list. Here's a
bit of it. For array xa:
8927.0000 , 8415.4004 , 8037.0000 , 7579.0000 , 7133.7998 ,
6680.7998 , 6229.2002 , 5784.6001 , 5291.7998 , 4819.7998 , 4328.3999 ,
3854.3999 , 3361.0000 , 2840.6001 , 2332.0000 , 1814.0000 , 1290.0000 ,
For array xb:
Just like the above but with different numbers. There are about 80
numbers in each column of the arrays.
Columns are fixed, and occasionally one encounters no data in the last
column. Actually, it's always the first row.
Off to pondering that issue.
.... You might be right. I've written the some code using jEdit using itPossible, but not likely. Feed a line ending with \r\n to a
POSIX text stream, and it will understand the \r as a data character,
not as part of the line-ending protocol. But the "%f" specifier
skips white space, and \r is a white space character -- it should
behave just like a trailing blank for the purposes of your code.
I strongly suspect something else was going on.
I printed James's comments from above. As it turns out my old C bookI'll point you toward James Kuyper's suggestion: Use the
strtod() function (or strtof(), if you prefer). It will skip
leading white space, convert a number, and tell you where it
stopped. You can restart from that spot, check for and/or
ignore the comma, and repeat until you've eaten the whole line.
I'll also put in a plug for the strtok() function. It's
got its drawbacks, but takes more flak than it deserves -- and
for the input you have, it'll work just fine. The outline:
Read a whole line, use strtok() to divide it into stretches that
contain no spaces, commas, \t, \r, or \n, and use strtod() to
convert what you find in those stretches:
char buffer[WHATEVER];
// read a line into buffer[]
for (char *p = buffer;
(p = strtok(p, " ,\t\r\n")) != NULL;
p = NULL)
{
// p points to a stretch of "important" characters
char *q;
double value = strtod(p, &q);
if (q == '\0') {
// converted the whole stretch; use value
} else {
// conversion stopped early; bad input
}
}
I was right when I mentioned the above post as "Maybe the culprit is
that I'm using a data file that was produced in Win7? End of line
incompatibility?"
I created a new dat file with vi, and the results were as expected.
Output was correct.
I'm using gcc under MinGW, and it's been 10 years since I used vi. My
wife is familiar with it, and give me a little help. I'm now brushing up
on it.
$ cat tst_array.dat
123.1 42.1 1.23
321.0 2.44 8,9
value = 123.10 1
value = 321.00 1
Now my problem is to read an entire line. The current code is:
while(fgets(str,70,p)!=NULL){
n=sscanf(str,"%5f", &value);
printf("value = %5.2f %d\n", value,n);
}
The real data I ultimately need is from a fortran name list. Here's a
bit of it. For array xa:
8927.0000 , 8415.4004 , 8037.0000 , 7579.0000 , 7133.7998 ,
6680.7998 , 6229.2002 , 5784.6001 , 5291.7998 , 4819.7998 , 4328.3999 ,
3854.3999 , 3361.0000 , 2840.6001 , 2332.0000 , 1814.0000 , 1290.0000 ,
For array xb:
Just like the above but with different numbers. There are about 80
numbers in each column of the arrays.
Columns are fixed, and occasionally one encounters no data in the last
column. Actually, it's always the first row.
W. eWatson said:Comprehensive C.
I merged your code into mine. It appears I muffed something in line 31.
gcc NL_pxm-array.c
_pxm-array.c: In function 'main':
_pxm-array.c:31:5: error: 'for' loop initial declarations are only
allowed in C99 mode
_pxm-array.c:31:5: note: use option -std=c99 or -std=gnu99 to compile
your code
_pxm-array.c:32:13: warning: assignment makes pointer from integer
without a cast [enabled by default]
Ah, missed the "instructions". C90, C99? What are they? Modes?? I usedI merged your code into mine. It appears I muffed something in line 31.
gcc NL_pxm-array.c
_pxm-array.c: In function 'main':
_pxm-array.c:31:5: error: 'for' loop initial declarations are only
allowed in C99 mode
_pxm-array.c:31:5: note: use option -std=c99 or -std=gnu99 to compile
your code
So - follow the instructions. Add the option -std=c99 to your compiler
command line.
_pxm-array.c:32:13: warning: assignment makes pointer from integer
without a cast [enabled by default]
This implies that the compiler thinks that the call to strtok() returns
an integer, which is not the case. Why would it think that? Because
strtok() is declared in <string.h>, and your code doesn't include that
header. In C90, if you used an undeclared identifier as if it were the
name of a function, it get implicitly declared as a function returning
'int'. C99 has more reasonable behavior: it's a constraint violation to
attempt calling an undeclared function.
#include<stdio.h>
#include<stdlib.h> ...
for (char *p = buffer; <- line 31
(p = strtok(p, " ,\t\r\n")) != NULL;
As it turns out, the comma is the end of the array, but the very nextFrom what you've said, I don't know how your program should figure out
when it's reached the end of array xa. The following suggestion may need
modification, based upon the answer to that question.
In order to use sscanf() for this purpose, you need a format string with
sscanf that includes the comma after each number and the following
comma: "%f ,".
scanf() directives normally take the form of conversion specifications
that start with a % character, but every character in a format string
that is not part of a conversion specification counts as one of two
possible kinds of directives. If it is white space character, the
directive "is executed by reading input up to the first non-white-space
character (which remains unread), or until no more characters can be
read. The directive nev er fails." That is what the space character in
"%f ," is for. All other characters that are not part of a conversion
specification must match the input file exactly, or there is a
conversion failure - that is what the comma is for.
Depending upon what you're doing with this data, it may be inappropriate
to have sscanf() fail just because something other than a comma appears
in that location. In that case, reach the character using a %c
conversion specifier, and figure out what you want your code to do if
it's not a comma.
BTW, I asked my colleague who wrote "the program A", what language heStrange. I changed the name of the file, and the program ran. Now I need
to sit back and think how I'm going to set this up for pgrmA that I
mentioned as post or two or above.
Thanks to all for the help.
It could not open pxm_array-test.dat, but it looks like it clearly in
the same folder.
Unable to open file pxm_array-test.dat
Wayne@solarblast1 /home/wayne/MeteorProject/SampleCode
$ cat pxm_data-test.dat
Ah, missed the "instructions". C90, C99? What are they? Modes?? I used_pxm-array.c:32:13: warning: assignment makes pointer from integer
without a cast [enabled by default]
This implies that the compiler thinks that the call to strtok() returns
an integer, which is not the case. Why would it think that? Because
strtok() is declared in <string.h>, and your code doesn't include that
header. In C90, if you used an undeclared identifier as if it were the
name of a function, it get implicitly declared as a function returning
'int'. C99 has more reasonable behavior: it's a constraint violation to
attempt calling an undeclared function.
#include<stdio.h>
#include<stdlib.h> ...
for (char *p = buffer; <- line 31
(p = strtok(p, " ,\t\r\n")) != NULL;
c99 amd added #include <string>, and it compiled successfully.
As it turns out, the comma is the end of the array, but the very next
line contains the name of another variable. I should be able to detect
that.
&INSTRUMENT
BN= 2*6.1999998 ,
FL= 2*3.2000000 ,
PXM=
8927.0000 , 8415.4004 , 8037.0000 , 7579.0000 , 7133.7998 ,
6680.7998 , 6229.2002 , 5784.6001 , 5291.7998 , 4819.7998 , 4328.3999 ,
3854.3999 , 3361.0000 , 2840.6001 , 2332.0000 , 1814.0000 , 1290.0000 ,
741.00000 , 213.20000 , -340.39999 , -931.40002 , -1494.8000 ,
...
-21194.600 , -22386.801 , -23614.600 , 41*0.0000000 , <- note 41
PXQ= -1800.0000 , -2500.0000 ,
PYM=
In it's default mode, gcc compiles a language called GnuC, a language
closely related to C, but having many non-conforming extensions to it.
It's possible for an extension to be fully conforming, but many of
GnuC's extensions are not. The -ansi option is equivalent to -std=c99.
The combination -std=c90 -pedantic puts gcc into a mode where it fully
conforms to C90. With -std=C99, it conforms pretty well, but not
completely, with C99. The option for C2011 -std=C1X, because it wasn't
clear at the time that they added that option exactly when the new
standard would be approved.
...
Correction: -ansi is equivalent to -std=c90 (that was probably just
a typo).
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.