keser
keser

Reputation: 2642

Remove last \n from file

I am filtering a .csv file and saving the output to a .txt file. The problem is, I have this extra \n line in my file and my array. I don't want to remove the line with editing the .txt file afterwards.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "input3.h"


int main(int argc, char **argv) {
    if (argc < 3) {
        printf("Aufruf: %s <anzahl> <bundesland>\n", argv[0]);
        printf("Beispiel: %s 100 Bayern\n", argv[0]);
        printf("Klein-/Großschreibung beachten!\n");
        exit(1);
    }
    int anzahl = atoi(argv[1]);
    char *bundesland = argv[2];
    char staedte[MAX_LAENGE_ARR][MAX_LAENGE_STR];
    char laender[MAX_LAENGE_ARR][MAX_LAENGE_STR];
    int bewohner[MAX_LAENGE_ARR];
    int len = read_file("staedte.csv", staedte, laender, bewohner);
    int offset = 0;

     char *a = (char*) malloc(MAX_LAENGE_ARR * sizeof(char));

    for (int i = 0; i < MAX_LAENGE_ARR; ++i) {

        if(strcmp(bundesland,laender[i]) == 0 && bewohner[i] >= anzahl){

            int written = snprintf(a + offset, MAX_LAENGE_STR ,"Die Stadt %s hat %d Einwohner. \n", staedte[i], bewohner[i]);
            offset += written;

        }
    }

    printf("STAEDTE : %s \n", a);
    write_file(&a,1);
    free(a);
}

Output : cat results.txt

Die Stadt München hat 1353186 Einwohner. 
 Die Stadt Nürnberg hat 505664 Einwohner. 
 Die Stadt Augsburg hat 264708 Einwohner. 
 Die Stadt Regensburg hat 135520 Einwohner. 
 Die Stadt Würzburg hat 133799 Einwohner. 
 Die Stadt Ingolstadt hat 125088 Einwohner. 
 Die Stadt Fürth hat 114628 Einwohner. 
 Die Stadt Erlangen hat 105629 Einwohner.
 // a blank line at the end. 

I am not allowed to change the write_file function but here it is.

void write_file(char *result[], int len) {
    FILE *fp = fopen("resultat.txt", "w");
    if (fp == NULL){
        perror("resultat.txt");
        exit(1);
    }
    for (int i=0; i<len; i++) {
        fprintf(fp, "%s\n", result[i]);
    }
    fclose(fp);
}

EDIT 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "input3.h"


int main(int argc, char **argv) {
    if (argc < 3) {
        printf("Aufruf: %s <anzahl> <bundesland>\n", argv[0]);
        printf("Beispiel: %s 100 Bayern\n", argv[0]);
        printf("Klein-/Großschreibung beachten!\n");
        exit(1);
    }
    int anzahl = atoi(argv[1]);
    char *bundesland = argv[2];
    char staedte[MAX_LAENGE_ARR][MAX_LAENGE_STR];
    char laender[MAX_LAENGE_ARR][MAX_LAENGE_STR];
    int bewohner[MAX_LAENGE_ARR];
    int len = read_file("staedte.csv", staedte, laender, bewohner);
    int count = 0;

    char **a = malloc(MAX_LAENGE_ARR * sizeof(char*));

    for (int i = 0; i < MAX_LAENGE_ARR; ++i) {

        if(strcmp(bundesland,laender[i]) == 0 && bewohner[i] >= anzahl){
            a[i] = malloc(MAX_LAENGE_STR * sizeof(char));
            snprintf(a[i], MAX_LAENGE_STR ,"Die Stadt %s hat %d Einwohner.", staedte[i], bewohner[i]);
            count++;
        }
    }
    write_file(a, count);
    free(a);
}

result.txt

(null)
(null)
Die Stadt München hat 1353186 Einwohner.
(null)
(null)
(null)
(null)
(null)

Upvotes: 1

Views: 278

Answers (2)

Sander De Dycker
Sander De Dycker

Reputation: 16243

Your write_file function already adds a '\n' :

fprintf(fp, "%s\n", result[i]);

So, when you fill the array that you pass to that function you should not add additional newlines.

Ie. instead of building a as a single string with all lines concatenated, build it as an array of strings, with an item in the array for each line (without the '\n').

To achieve that, you'll want to allocate memory for this array, and then replace your current snprintf call with one that writes to the next item in that array, instead of to a + OFFSET :

char **a = malloc(MAX_LAENGE_ARR * sizeof(char*));

and then for each line :

a[count] = malloc(MAX_LAENGE_STR * sizeof(char));
snprintf(a[count], MAX_LAENGE_STR, ...);

Don't forget to free the allocated memory once you no longer need it.

Upvotes: 2

Jabberwocky
Jabberwocky

Reputation: 50775

You basically want this:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "input3.h"

...

int main(int argc, char **argv) {
  if (argc < 3) {
    printf("Aufruf: %s <anzahl> <bundesland>\n", argv[0]);
    printf("Beispiel: %s 100 Bayern\n", argv[0]);
    printf("Klein-/Großschreibung beachten!\n");
    exit(1);
  }
  int anzahl = atoi(argv[1]);
  char *bundesland = argv[2];
  char staedte[MAX_LAENGE_ARR][MAX_LAENGE_STR];
  char laender[MAX_LAENGE_ARR][MAX_LAENGE_STR];
  int bewohner[MAX_LAENGE_ARR];
  int len = read_file("staedte.csv", staedte, laender, bewohner);

  // allocate an array of pointers to char of length MAX_LAENGE_ARR
  char **lines = malloc(MAX_LAENGE_ARR * sizeof(*lines));

  // instead of the line above you could simply write this
  //    char *lines[MAX_LAENGE_ARR];
  // in that case you need to remove the `free(lines);` at the end

  int nboflines = 0; // number of lines processed

  for (int i = 0; i < MAX_LAENGE_ARR; ++i) {

    if (strcmp(bundesland, laender[i]) == 0 && bewohner[i] >= anzahl) {
      // get the size needed for one line (see snprintf documentation for more details)
      int sizeneeded = snprintf(NULL, MAX_LAENGE_STR, "Die Stadt %s hat %d Einwohner. \n", staedte[i], bewohner[i]);

      // allocate the size needed for the line +1 for the NUL terminator
      char *line = malloc(sizeneeded + 1);

      // output to line
      snprintf(line, MAX_LAENGE_STR, "Die Stadt %s hat %d Einwohner. \n", staedte[i], bewohner[i]);    

      lines[nboflines++] = line;
    }
  }


  printf("STAEDTE :");
  for (int i = 0; i < nboflines; ++i)
  {
    printf("%s\n", lines[i]);
  }

  write_file(lines, nboflines);

  // free the individual lines allocated by the malloc
  //  inside the for loop
  for (int i = 0; i < nboflines; ++i)
  {
    free(lines[i]);
  }

  // free the line array allocated just before the for loop
  free(lines);
}
  • See the comments I added for explanations.
  • I changed the name of a to the more meaningful name lines.

Discalaimers:

  • This code has not been tested.
  • No error checking is done in this code.
  • There is still room for further improvement.

Upvotes: 0

Related Questions