I have this code to scan the strings from a given .txt file into an array:
void readSentences(char inputFilePath[], char inputSentences[][MAX_CHAR]) {
const char *INPUT_FILE_PATH = inputFilePath;
FILE *fp = fopen(INPUT_FILE_PATH, "r ");
int lineNum = 0;
while ( fgets( inputSentences[lineNum], sizeof(inputSentences[lineNum]), fp ) != NULL ) {
lineNum ;
}
fclose (fp);
}
The input file path is just a .txt file containing the names of countries, but when I try to print the array an extra line of nonsense is printed as below:
Hong Kong Ecuador Dominican Republic Taiwan Hong Kong Taiwan Australia Hong Kong Italy Hong Kong Ukraine Republic of Irelandp7Þ♣'☻§Ò♣'☻P☺þ♣'☻
Code that prints the array from main
int main() {
char array1[MAX_LINES][MAX_CHAR];
char array2[MAX_LINES][MAX_CHAR];
readSentences("..//inputFiles/input1.txt", array1);
readSentences("..//inputFiles/input2.txt", array2);
for (int i = 0; i < MAX_LINES; i ) {
printf("%s", array2[i]);
}
CodePudding user response:
You need to modify readSentences
and return the actual number of lines read from the file, either via a return value, or via a pointer parameter and print only the number of lines actually read.
Not knowing how many lines have been read makes the reading completely usless. Whatever code needs to process the lines read for whatever purpuse must know the number of lines read.
Something like this:
void readSentences(char inputFilePath[], char inputSentences[][MAX_CHAR], int *nblines) {
const char* INPUT_FILE_PATH = inputFilePath;
FILE* fp = fopen(INPUT_FILE_PATH, "r ");
int lineNum = 0;
while (fgets(inputSentences[lineNum], sizeof(inputSentences[lineNum]), fp) != NULL) {
lineNum ;
}
fclose(fp);
*nblines = lineNum;
}
int main() {
char array1[MAX_LINES][MAX_CHAR];
int nblines1;
char array2[MAX_LINES][MAX_CHAR];
int nblines2;
readSentences("..//inputFiles/input1.txt", array1, &nblines1);
readSentences("..//inputFiles/input2.txt", array2, &nblines2);
for (int i = 0; i < nblines2; i ) {
printf("%s", array2[i]);
}
}
There is still room for further improvment:
- you need to check if
fopen
fails and act accordingly. - if the number of liens in a file is greater than
MAX_LINES
, you're out of luck and your array index will go out of bounds and you'll get undefined behaviour. - the
//
in"..//inputFiles/....
should probably be/
.
CodePudding user response:
The arrays array1
and array2
have not been initialized before they are passed to readSentences()
. If readSentences
reads less than MAX_LINES
files, the unread rows of the array will still contain uninitialized junk. printf("%s", array2[i]);
is printing that junk, leading to undefined behavior.
There are various ways to initialize the state of array1
and array2
to something sensible before passing them to readSentences()
.
- Initialize the array contents in the declaration:
char array1[MAX_LINES][MAX_CHARS] = {0};
char array2[MAX_LINES][MAX_CHARS] = {0};
- Clear the array contents with
memset()
:
memset(array1, 0, sizeof array1);
memset(array2, 0, sizeof array2);
- Set the array rows to empty strings with
strcpy()
:
for (int i = 0; i < MAX_LINES; i ) {
strcpy(array1[i], "");
strcpy(array2[i], "");
}
- Set the array rows to empty strings by assigning
'\0'
to the first element of each row:
for (int i = 0; i < MAX_LINES; i ) {
array1[i][0] = '\0';
array2[i][0] = '\0';
}
It would be better for readSentences()
to return the number of lines:
char inputFilePath[], char inputSentences[][MAX_CHAR]) {
...
return numLines;
}
Then the loop in main()
can print just the valid lines:
nlines2 = readSentences("..//inputFiles/input2.txt", array2);
for (int i = 0; i < nlines2; i ) {
printf("%s", array2[i]);
}
This has nothing to do with the title of the question, which is about substituting '\n'
with '\0'
, but that was a red herring. If you want to do that anyway, the usual trick is to use strcspn
to find the index of the '\n'
character if it is present, or the index of the end of the string if not. Either way, the character at that index can be changed to '\0'
:
while ( fgets( inputSentences[lineNum], sizeof(inputSentences[lineNum]), fp ) != NULL ) {
char *s = inputSentences[lineNum]; /* saves typing :-) */
s[strcspn(s, "\n")] = '\0';
lineNum ;
}