DarkLordoftheMonkeys said:
Okay, I have another very simple program here. It reads the contents of one line of a file into a string. It uses two functions that I've written, both of which work perfectly.
This works:
char *append( char str[], char c ){
char *astr = (char *) malloc( sizeof *str + 1 ); // I needed to create a character
for( int i = 0; i < strlength( str ); i++ ){ // pointer rather than a regular
astr[i] = str[i]; // array because otherwise the array
} // is destroyed when the function
astr[strlength( str )] = c; // exits, making the return value NULL.
return astr;
}
This also works:
// calculates the length of a string using pointers
int strlength( char arr[] ){
int length = 0;
char *arrptr;
arrptr = &arr[0];
for( int i = 0;; i++ ){
if( *(arrptr + i) ){ // if the end of the string
length++; // has not been reached
}
else{
break;
}
}
return length;
}
You can ignore how the two functions are implemented. I just put them there for error checking purposes. The first appends a single character to the end of a string and returns a pointer to that string. The second calculates the length of a string.
Both work perfectly.
This also works perfectly:
char *lineread = "";
char c;
lineread = append( lineread, c );
So does this:
while( i < 5 ){
lineread = append( lineread, c );
i++;
}
This doesn't:
#include <stdio.h>
#include <stdlib.h>
#include "mystrings.h"
#include "files.h"
int main( int argc, char *argv[] ){
FILE *fp;
fp = fopen( argv[1], "r" );
char *lineread = "";
char c;
while( (c = getc( fp )) != '\n' ){ // This is the important line.
lineread = append( lineread, c ); // And this.
}
printf( "%s", lineread );
fclose( fp );
printf( "\n" );
return 0;
}
The program compiles, but when I run it, it just does nothing. It waits for me to type something, and when I type something and enter it, it just does that again and again and again until I type Ctrl+C.
What the hell is going on here?
Actually, your code segfaulted on me right off the bat.
First, you shouldn't be using
char c;
c should be an int because that is what getc returns, and that is how EOF is detected. If you were looking for it. [edit]
And with regard to your code looping forever until you kill it -- well, that's what you coded it to do. D'oh! Ignore that. I didn't see the input file part. Can you post the input file?[/edit]
#include "mystrings.h"
#include "files.h"
It would appear that you are putting active code in your header files. That is a no-no. Don't put variable definitions or function bodies into header files.
Writing your own version of strlen might be an interesting exercise, but you don't really need to do so. The standard version of it and strcpy are going to be better choices.
"This works perfectly". :P As a private aside, just about every bug I've seen new coders go after has been prefixed with these words. I generally shy away from using those terms when I'm chasing a bug, 'cuz it generally tends to bite me in the backside. [/aside]
for( int i = 0; [COLOR="red"]i < strlength( str )[/COLOR]; i++ )
This is an idiom to avoid. You may not notice anything much for large strings, but with long strings it certainly can be. The intended O(n) complexity becomes O(n^2). That is, each loop iteration you once again check the string length. Not once, but each and every loop iteration.
And as a nice little segue, this is the cause of the segfault I find. Fortunately for me, and unfortunately for you, my system has not zeroed out stuff for me. This made the crash happen, which indicated to me that there is a bug.
You see, you don't null terminate your string. Since a strlen or strcpy operation depends on the null terminator, its absence is going to be an issue.
Your append function is quite buggy as well. Let me ask you this: how many times to you malloc? And then how many times do you free? You can ignore the first question, but should have an equal number. In other words, you are leakin' memory like a sieve.
I think you confuse strlen and sizeof:
char *append( char str[], char c ){
char *astr = (char *) malloc( sizeof *str + 1 ); // I needed to create a character
sizeof *str is always 1. You are always allocating your string to be a maximum of 2 characters, one of which must be the null terminator in order to be a string. So you can only have one element in your string. There's not much room for concatenation there. ;)
The loop version of strcpy that you have to follow this fails to null terminate the string.
Are you using a C++ compiler for what is ostensibly C code? I would advise against doing so -- otherwise, especially for language newcomers, you might end up writing a polyglot.