//create the array from file
char *array[100];
char string[80];
FILE * file;
file = fopen( "file.txt" , "r");
if (file) {
int k = 0;
while (fscanf(file, "%s", string)!=EOF){
array[k] = strdup(string);
k++;
}
fclose(file);
}
//print the history array for debugging
for(int k = 0; k<sizeof(array); k++){
printf("the element at %d is: %s\n", k, array[k]);
}
The resulting array has random characters from memory which are not present in the file. Is there any way to prevent this?
There are two problems in the code.
The first is that you are using fscanf
to read the file, instead of fgets
. fscanf
with a format of "%s"
will read one word from the file. fgets
reads a line.
The second problem is the last for
loop which uses sizeof(array)
. On a 32-bit machine, sizeof(array)
is 100*4 = 400. What you want is to count the number of lines that have been read from the file, and then use that count in the for
loop.
With that in mind, here's how I would write the code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
char *array[100];
char string[80];
FILE *fp;
if ( (fp = fopen( "file.txt" , "r")) == NULL )
{
printf( "File not found\n" );
exit( 1 );
}
int count = 0;
while ( fgets( string, sizeof(string), fp ) != NULL )
{
string[strcspn(string,"\n")] = '\0';
if ( count < 100 )
{
array[count] = strdup( string );
count++;
}
}
fclose( fp );
for ( int k = 0; k < count; k++ )
printf( "the element at %d is: %s\n", k, array[k] );
}
The line
string[strcspn(string,"\n")] = '\0';
removes the newline, if any, from the string. This is necessary since fgets
will retain the newline.
If you want to read lines of text, use:
fgets(line, sizeof(line), file);
If a line can contain 80
characters, you need to define line
to be an array of at least 81
characters -- to allow an extra space for the terminating null character.
char line[81];
You need to store the number of lines read so that when writing the lines out, you don't try to write any more than you read. Make sure you don't read any more than the number of lines array
is capable of holding.
int numLinesRead = 0; if (file) { int k = 0; while (fscanf(file, "%s", string)!=EOF && k < 100 ){ array[k] = strdup(string); k++; } fclose(file); numLinesRead = k; }
Don't write any more than the number of lines read.
for(int k = 0; k<numberOfLinesRead; k++){ printf("the element at %d is: %s\\n", k, array[k]); }
There are several issues in this code ...
char *array[100];
char string[80];
so far, so good, now let's look at this:
int k = 0;
while (fscanf(file, "%s", string)!=EOF){
array[k] = strdup(string);
k++;
}
Issues here:
k
. This should stop if k
reached 100
EOF
is wrong. Other things could fail, too. %s
will only read up to the next whitespace, probably not what you want. %s
will read as long as there are non-whitespace characters, so it will overflow your string
, given malicious input. A correct version would eg look like this:
int k = 0;
while (k < 100 && fgets(string, 80, file)){
array[k] = strdup(string);
k++;
}
Then to the next problematic part:
for(int k = 0; k<sizeof(array); k++){
printf("the element at %d is: %s\n", k, array[k]);
}
sizeof()
gives you the size in bytes of its argument. The size of an array is fixed , it doesn't matter how many elements you actually stored. The elements are pointers, so taking more than 1 byte.
Correct version:
int lines = 0; // nothing read
if (file) {
int k = 0;
while (k < 100 && fgets(string, 80, file)){
array[k] = strdup(string);
k++;
}
fclose(file);
lines = k;
}
for(int k = 0; k<lines; k++){
printf("the element at %d is: %s\n", k, array[k]);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.