Home > Software design >  when reading strings from an input file into a 2d array how do you substitute \n with \0, i.e extr
when reading strings from an input file into a 2d array how do you substitute \n with \0, i.e extr

Time:02-17

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().

  1. Initialize the array contents in the declaration:
    char array1[MAX_LINES][MAX_CHARS] = {0};
    char array2[MAX_LINES][MAX_CHARS] = {0};
  1. Clear the array contents with memset():
    memset(array1, 0, sizeof array1);
    memset(array2, 0, sizeof array2);
  1. Set the array rows to empty strings with strcpy():
    for (int i = 0; i < MAX_LINES; i  ) {
        strcpy(array1[i], "");
        strcpy(array2[i], "");
    }
  1. 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  ;
    }
  •  Tags:  
  • c
  • Related