something fishy here with stripnl()

G

grinder

i am writing a prog that reads mulitple lines from a txt file in
succession into code that takes these lines as an input file that would
be opened and from which data would be manipulated. As the in the
following:

#include <stdio.h>
#include<stdlib.h>
#include<math.h>
#define MAX 150
#define PI 3.14159265

void stripnl(char *str) {
while(strlen(str) && ( (str[strlen(str) - 1] == 13) ||
( str[strlen(str) - 1] == 10 ))) {
str[strlen(str) - 1] = 0;
}

}

int main() {
char fname[40];
char line[20];
double x[MAX],y[MAX];
double mm,mxy,my,mx,mx2;
double resul;
double a[2][2],b[2][2],c[2][2];
double w;
int q,counter,v,lcount;
int ifail;
int m,n,k;
FILE *input,*result,*infile;

// Read in the filename //
printf("Enter the name of data file: ");
fgets(fname, sizeof(fname), stdin);

// get rid of the newline char //
stripnl(fname);
strtok(fname," ");

// Open the file//
if((infile = fopen(fname, "rt")) == NULL) {
printf("Error Opening File.\n");
exit(1);
}
while( fgets(line, sizeof(line), infile) != NULL ) {
// Get each line from the infile //
lcount++;
// print the line number and data //
printf("Line %d: %s",lcount,line);
printf("%s",line);

<><>><><><><><><><><><><><><><><><><><>

if ((input = fopen(line,"rt")) == NULL )
{
printf("\ndata file not found\n\n");
exit(0);
}
<><><><><><><><><><><><><><><><><><><><><><

counter=0;
while(!feof(input))
{
if(counter==MAX-1)
{
printf("\n too many points ,taking the first %d points
\n",counter); break;
}
counter++;
fscanf(input,"%lf %lf\n",&x[counter],&y[counter]);
printf("%lf %lf\n",&x[counter],&y[counter]);
}
v=counter;
result=fopen("st_line.dat","w");
for(q=1,mm=0,mx=0,mxy=0,my=0,mx2=0;q<=v;q++)
{
//summing values and naming as variable//
{
resul=cos(x[q]*PI/180);
printf(" %lf %lf \n",resul,x[q]);
}
mm=q;
mxy=mxy+resul*y[q];
my=my+y[q];
mx=mx+resul;
mx2=mx2+resul*resul;
}
a[0][0]= mm;
a[0][1]= mx;
a[1][0]= mx;
a[1][1]= mx2;

b[0][0]=my;
b[1][0]=mxy;
b[0][1]=0;
b[1][1]=0;

printf("\n\n %lf %lf \n %lf %lf
\n",a[0][0],a[0][1],a[1][0],a[1][1]);
printf("\n\n %lf %lf \n %lf %lf
\n",b[0][0],b[0][1],b[1][0],b[1][1]);

printf("\n\n %lf %lf \n %lf %lf
\n\n",a[0][0],a[0][1],a[1][0],a[1][1]);

fclose(input);
fclose(result);
}

#undef MAX
fclose(infile);
}

---------------------------------------------------------------------------------

When it gets to the "if" statement between the "<><><><><><" i receive
the "data file not found", but yet in the fopen line that contains
"fname" works perfectly if the "stripnl()" line is present. This is my
first time working with char strings in this fasion and i am not
familiar with the procedures. i assumed that it is because fopen does
not know where the end of the string is and is getting confused, and if
that is the case, then i am not versed well enough in C to tell it
otherwise.
 
B

Ben Pfaff

grinder said:
void stripnl(char *str) {
while(strlen(str) && ( (str[strlen(str) - 1] == 13) ||
( str[strlen(str) - 1] == 10 ))) {
str[strlen(str) - 1] = 0;
}

}

You should use '\r' and '\n' in place of 13 and 10. In fact, the
'\r' should not be necessary, because you're reading a text
stream, and lines in text streams end in just a new-line ('\n').

The name of the function should not be stripnl, because names
that begin with str followed by a letter are reserved.

It's likely to be really inefficient to call strlen so many
times. You should only need to call it once per function
invocation.

The excessive use of parentheses above makes it hard to actual
read out the operator precedence. I'd suggest dropping the
parentheses around the equality expressions as a start.

I'm not sure what the real problem is, because I only read that
much of your code, but those should get you started.
 
R

Richard

grinder said:
i am writing a prog that reads mulitple lines from a txt file in
succession into code that takes these lines as an input file that would
be opened and from which data would be manipulated. As the in the
following:

#include <stdio.h>
#include<stdlib.h>
#include<math.h>
#define MAX 150
#define PI 3.14159265

void stripnl(char *str) {
while(strlen(str) && ( (str[strlen(str) - 1] == 13) ||
( str[strlen(str) - 1] == 10 ))) {
str[strlen(str) - 1] = 0;
}

Possibly inefficient. Something like this is probably quicker and easier
to read/debug. Not tested - you get the idea. Youre assuming the
possibility of multiple blank lines I guess?

size_t l = strlen(str);
while(l && (str[l-1]=='\n'))
str[l--] = '\0';


As for the rest : did you use a debugger/printf to examine the "line" variable?
Does it have \n on the end? Does it work if you call stripnl?

More importantly, are you sure the files its trying to open are there? :-;

Good luck!

}

int main() {
char fname[40];
char line[20];
double x[MAX],y[MAX];
double mm,mxy,my,mx,mx2;
double resul;
double a[2][2],b[2][2],c[2][2];
double w;
int q,counter,v,lcount;
int ifail;
int m,n,k;
FILE *input,*result,*infile;

// Read in the filename //
printf("Enter the name of data file: ");
fgets(fname, sizeof(fname), stdin);

// get rid of the newline char //
stripnl(fname);
strtok(fname," ");

// Open the file//
if((infile = fopen(fname, "rt")) == NULL) {
printf("Error Opening File.\n");
exit(1);
}
while( fgets(line, sizeof(line), infile) != NULL ) {
// Get each line from the infile //
lcount++;
// print the line number and data //
printf("Line %d: %s",lcount,line);
printf("%s",line);

<><>><><><><><><><><><><><><><><><><><>

if ((input = fopen(line,"rt")) == NULL )
{
printf("\ndata file not found\n\n");
exit(0);
}
<><><><><><><><><><><><><><><><><><><><><><

counter=0;
while(!feof(input))
{
if(counter==MAX-1)
{
printf("\n too many points ,taking the first %d points
\n",counter); break;
}
counter++;
fscanf(input,"%lf %lf\n",&x[counter],&y[counter]);
printf("%lf %lf\n",&x[counter],&y[counter]);
}
v=counter;
result=fopen("st_line.dat","w");
for(q=1,mm=0,mx=0,mxy=0,my=0,mx2=0;q<=v;q++)
{
//summing values and naming as variable//
{
resul=cos(x[q]*PI/180);
printf(" %lf %lf \n",resul,x[q]);
}
mm=q;
mxy=mxy+resul*y[q];
my=my+y[q];
mx=mx+resul;
mx2=mx2+resul*resul;
}
a[0][0]= mm;
a[0][1]= mx;
a[1][0]= mx;
a[1][1]= mx2;

b[0][0]=my;
b[1][0]=mxy;
b[0][1]=0;
b[1][1]=0;

printf("\n\n %lf %lf \n %lf %lf
\n",a[0][0],a[0][1],a[1][0],a[1][1]);
printf("\n\n %lf %lf \n %lf %lf
\n",b[0][0],b[0][1],b[1][0],b[1][1]);

printf("\n\n %lf %lf \n %lf %lf
\n\n",a[0][0],a[0][1],a[1][0],a[1][1]);

fclose(input);
fclose(result);
}

#undef MAX
fclose(infile);
}

---------------------------------------------------------------------------------

When it gets to the "if" statement between the "<><><><><><" i receive
the "data file not found", but yet in the fopen line that contains
"fname" works perfectly if the "stripnl()" line is present. This is my
first time working with char strings in this fasion and i am not
familiar with the procedures. i assumed that it is because fopen does
not know where the end of the string is and is getting confused, and if
that is the case, then i am not versed well enough in C to tell it
otherwise.
 
S

Simon Biber

Ben said:
grinder said:
void stripnl(char *str) {
while(strlen(str) && ( (str[strlen(str) - 1] == 13) ||
( str[strlen(str) - 1] == 10 ))) {
str[strlen(str) - 1] = 0;
}

}

You should use '\r' and '\n' in place of 13 and 10. In fact, the
'\r' should not be necessary, because you're reading a text
stream, and lines in text streams end in just a new-line ('\n').

In the real world, one does often encounter MS-DOS text files on Unix or
Unix-like (eg. Cygwin) systems. Text streams there will not strip out
the '\r' for you.

In many cases it's good practise to write code that will work properly
whether it encounters Unix ("\n"), Mac ("\r") or MS-DOS ("\r\n") text
files, or even a mixture within one file.
 
P

Philip Potter

Simon Biber said:
In the real world, one does often encounter MS-DOS text files on Unix or
Unix-like (eg. Cygwin) systems. Text streams there will not strip out
the '\r' for you.

In many cases it's good practise to write code that will work properly
whether it encounters Unix ("\n"), Mac ("\r") or MS-DOS ("\r\n") text
files, or even a mixture within one file.

Uhm, don't the C library functions do all that for you? In text-mode output
to streams, '\n' is converted to the local newline expression, whatever that
may be. This doesn't necessarily apply if you are using
implementation-specific I/O calls.

Philip
 
A

Ancient_Hacker

When it gets to the "if" statement between the "<><><><><><" i receive
the "data file not found", but yet in the fopen line that contains
"fname" works perfectly if the "stripnl()" line is present.

?? That comment makes no sense to me. There's an "exit()" after the
error message, so you can't have seen the code work after getting the
error message.


This is my
first time working with char strings in this fasion and i am not
familiar with the procedures. i assumed that it is because fopen does
not know where the end of the string is and is getting confused, and if
that is the case, then i am not versed well enough in C to tell it
otherwise.

So what is the problem? If the code is working, what would you like it
to do differently?

A few general suggestions:

Don't use a file name array of length 20! File names can be a whole
lot longer, especially if paths are involved. Memory is cheap these
days, go for at least 500.

The man page for gets() says it DOES NOT return the \n character at the
end, unlike fgets() which DOES, so the mystery deepens.

How about you print out the line in ascii and decimal so we can see
exactly what is there?:

for( i=0; i <strlen(line);i++ ) printf( "Char %3d is '%c' '%3d'\n",
i+1, line, line );

Also, why are you doing a strtok() on the file name? strtok is a bit
dangerous as it modifies the input string, which often leads to major
confusion.

You may not have a problem at all if you take out the trimming code and
the strtok().
 
P

Philip Potter

Philip Potter said:
Uhm, don't the C library functions do all that for you? In text-mode output
to streams, '\n' is converted to the local newline expression, whatever that
may be.

*slaps forehead*
I will read posts before replying.
I will read posts before replying.
I will read posts before replying.

Philip
 
P

Philip Guenther

grinder wrote:
....
#include<stdlib.h> ....
void stripnl(char *str) {

It's a relatively minor point, but since no one else has mentioned it:
the external symbol stripnl() is in the namespace reserved to the
implemention when <stdlib.h> or <string.h> is included. While it's
unlikely to actually conflict, you should consider changing the name to
not start with "str".

Philip Guenther
 
K

Keith Thompson

Philip Guenther said:
grinder wrote:
...

It's a relatively minor point, but since no one else has mentioned it:
the external symbol stripnl() is in the namespace reserved to the
implemention when <stdlib.h> or <string.h> is included. While it's
unlikely to actually conflict, you should consider changing the name to
not start with "str".

Only identifiers starting with "str" and a lowercase letter are
reserved. "str_ipnl" would be ok.
 
S

Simon Biber

Philip said:
grinder wrote:
....

It's a relatively minor point, but since no one else has mentioned it:
the external symbol stripnl() is in the namespace reserved to the
implemention when <stdlib.h> or <string.h> is included. While it's
unlikely to actually conflict, you should consider changing the name to
not start with "str".

It's not true that no-one else mentioned it. The very first reply by Ben
Pfaff mentioned it:
 
G

grinder

i have tried some of the suggestions, but yet to no avail. so i have
taken the advice of ancient_hacker and have supplied the output below:

<><><><><><><><><><><><><><><><><><><><><><><>
Enter the name of data file: lin_file.dat
Line 1: points.dat
points.dat
Char 1 is 'p' '112'
Char 2 is 'o' '111'
Char 3 is 'i' '105'
Char 4 is 'n' '110'
Char 5 is 't' '116'
Char 6 is 's' '115'
Char 7 is '.' ' 46'
Char 8 is 'd' '100'
Char 9 is 'a' ' 97'
Char 10 is 't' '116'
Char 11 is '
' ' 10'

data file not found

Segmentation fault

<><><><><>><><><><><><><><><><><><><><


i have removed the "exit()" and the "strtok()" and still get this
output. Also, i am positive that the file is there because i have used
it in other facets of the larger code, and every time i
ls -a it is in the directory. Though, it does seem that there is a
space after the 't',i.e., a blank for char 11.
 
A

Ancient_Hacker

grinder said:
i have tried some of the suggestions, but yet to no avail. so i have
taken the advice of ancient_hacker and have supplied the output below:

<><><><><><><><><><><><><><><><><><><><><><><>
Enter the name of data file: lin_file.dat
Line 1: points.dat
points.dat
Char 1 is 'p' '112'
Char 2 is 'o' '111'
Char 3 is 'i' '105'
Char 4 is 'n' '110'
Char 5 is 't' '116'
Char 6 is 's' '115'
Char 7 is '.' ' 46'
Char 8 is 'd' '100'
Char 9 is 'a' ' 97'
Char 10 is 't' '116'
Char 11 is '
' ' 10'

data file not found

Segmentation fault

<><><><><>><><><><><><><><><><><><><><

okay, all is clear now. you are using fgets() to read from the
keybaord, which DOES pass thru the ending "\n". The numeric value of
\n is 10. You need to strip off that last character. The easiest way
is to just do a:

len = strlen( Line );

if( len > 0 ) Line[ len - 1 ] = '\0';

That will zap the \n and then the file name should be acceptable to
fopen().
 
K

Keith Thompson

grinder said:
i have tried some of the suggestions, but yet to no avail. so i have
taken the advice of ancient_hacker and have supplied the output below:

<><><><><><><><><><><><><><><><><><><><><><><>
Enter the name of data file: lin_file.dat
Line 1: points.dat
points.dat
Char 1 is 'p' '112'
Char 2 is 'o' '111'
Char 3 is 'i' '105'
Char 4 is 'n' '110'
Char 5 is 't' '116'
Char 6 is 's' '115'
Char 7 is '.' ' 46'
Char 8 is 'd' '100'
Char 9 is 'a' ' 97'
Char 10 is 't' '116'
Char 11 is '
' ' 10'

data file not found

Segmentation fault

<><><><><>><><><><><><><><><><><><><><


i have removed the "exit()" and the "strtok()" and still get this
output. Also, i am positive that the file is there because i have used
it in other facets of the larger code, and every time i
ls -a it is in the directory. Though, it does seem that there is a
space after the 't',i.e., a blank for char 11.

If you're on an ASCII-based system, a blank is not character 10, it's
character 32. Character 10 is an ASCII LF, also known (in most
implementations) as '\n'.

Figure out why you have a '\n' character in your string. Does the
actual file name have a '\n'? If not, figure out how to get rid of
the '\n' character.
 
K

Keith Thompson

Ancient_Hacker said:
grinder said:
i have tried some of the suggestions, but yet to no avail. so i have
taken the advice of ancient_hacker and have supplied the output below:

<><><><><><><><><><><><><><><><><><><><><><><>
Enter the name of data file: lin_file.dat
Line 1: points.dat
points.dat
Char 1 is 'p' '112'
Char 2 is 'o' '111'
Char 3 is 'i' '105'
Char 4 is 'n' '110'
Char 5 is 't' '116'
Char 6 is 's' '115'
Char 7 is '.' ' 46'
Char 8 is 'd' '100'
Char 9 is 'a' ' 97'
Char 10 is 't' '116'
Char 11 is '
' ' 10'

data file not found

Segmentation fault

<><><><><>><><><><><><><><><><><><><><

okay, all is clear now. you are using fgets() to read from the
keybaord, which DOES pass thru the ending "\n". The numeric value of
\n is 10. You need to strip off that last character. The easiest way
is to just do a:

len = strlen( Line );

if( len > 0 ) Line[ len - 1 ] = '\0';

That will zap the \n and then the file name should be acceptable to
fopen().

I'd first confirm that the character really is a '\n':

if (len > 0 && Line[len-1] == '\n') {
Line[len-1] = '\0';
}

fgets() can give you a string with no trailing newline if the input
line is longer than the buffer you provided. (But in that case, you
probably don't want to use the partial line as a file name anyway; it
might make more sense to print an error message instead.)
 
R

Richard

Keith Thompson said:
Only identifiers starting with "str" and a lowercase letter are
reserved. "str_ipnl" would be ok.

Without trying it, do compilers warn about things like that?
 
I

Ian Collins

Richard said:
Without trying it, do compilers warn about things like that?

Not until a clashing name is added to one of your implementation's
standard headers or libraries.
 
K

Keith Thompson

Richard said:
Without trying it, do compilers warn about things like that?

In my experience, typically not. It would be nice if they did. Of
course, this would require the compiler to recognize whether the code
it's compiling is user code or implementation code; any method for
determining this would have to be implementation-specific.
 

Ask a Question

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.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top