File I/O difficulties in C
I'm writing a version of the Unix expand
utility that replaces tabs with spaces in a file. To do this, I'm reading in each character and testing if it is a tab character. If it is, it replaces the tab with the given amount of spaces, otherwise the character gets printed.
My main method goes like
int main(int argc, char *argv[]){
FILE *fp;
char *help1="-help";
char *help2开发者_开发百科= "--help";
//int spaces; //number of spaces to replace tabs
fp= fopen(argv[1], "rw");
parse_file(fp, 4);
fclose(fp);
return 0;
}
the parse_file method goes like
void parse_file(FILE *fp, int spaces)
{
int i; //loop counter
char c; //current character
while (c!= EOF)
{
c= getchar(); //get char from stream
if (c=='\t') //if char is a tab
{
for (i=0; i< spaces; i++)
putchar(" "); //replace with spaces
}
else
putchar(c); //otherwise, print the character
}
}
When compiling, I get an integer from pointer without cast warning for putchar(" ");
and the program hits a segfault when executing.
So, my questions:
1- What is the warning "makes integer from pointer without cast" all about? What can I do to resolve it?
2- The code generates a segfault on execution with a text file passed in as an argument. Is there anything in this code that would cause that?
you must use
putchar(' ')
instead
putchar(" ")
You're calling
putchar
on a string (" "
), but it wants achar
argument (' '
). (Actually anint
, but only passing achar
is safe.)The segfault is probably due to the
fclose
onfp
, which may beNULL
. You should check the return value fromfopen
. The reason you only notice afterparse_file
is that it doesn't touchfp
at all (it reads fromstdin
and writes tostdout
). To use the streamfp
, you should usegetc(fp)
andputc(fp)
instead. (That still won't work because you'd overwrite the stream with more data than you're reading from it, so you'll get garbage out.)
In fact, the program is sure to segfault when no command line argument is given. Either fopen
segfaults because it is handed the null pointer argv[1]
, or it returns a null pointer itself.
When writing these kinds of programs, please adhere to the Unix philosophy and write them as filters: read from stdin
, write to stdout
. Don't modify a file in-place if you don't have to.
In C string literals are of type char *
, a pointer to some area containing string characters.
" "
is a string literal, not a character. Use ' '
when you need a single character
As everyone else says, re. The use of char vs. string. As for the logic behind the actual error message you see, the string is a pointer to a const array of characters. Hence the error is saying it is converting the pointer to an int. Most of the char functions work with ints.
To summarise the issues (I'm repeating stuff other people have said, but issues 5 and 6 havehas not been mentioned so far):
putchar()
does not take a string pointer as an argument but an int - the constant' '
is an acceptable parameter- you don't check that
argc > 1
before usingargv[1]
- you don't check that
fopen()
successfully opens the file c
should be defined as anint
since in some character sets(char) -1
(0xFF) is a legitimate character and also the comparisonc == EOF
may fail ifc
is not sign extendedThe first time through the loop
c
is used uninitialised and in the loop you also treatEOF
as a normal character. The normal idiom in C programs isint c; while ((c = fgetc(fp)) != EOF) { // do stuff with c }
You are getting your characters from
stdin
and notfp
hence usefgetc()
notgetchar()
I think that covers everything.
To answer your explicit question, you get the warning "makes integer from pointer without cast" when an int is expected but you use a pointer (in this case the type of " "
is const char*
).
In addition to what has already been said, getchar() returns int not char. EOF is an int constant. You will need to read the result from getchar() into an int, check for EOF, and if not found, cast the int into a char.
精彩评论