18542

Error using fprintf and fscanf

Question:

I have an archive results.csv and I need to read the first line of this archive and print it out on output.txt. Somehow it's printing random characters after everything and I couldn't figure out what is wrong.

Command: a.c results.csv

First line: date,home_team,away_team,home_score,away_score,tournament,city,country,neutral

output.txt: date,home_team,away_team,home_score,away_score,tournament,city,country,neutral,(!£,(!£,(!£,(!£,(!£,@,£,(!£,(!£

#include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> typedef struct { char *line1; char *line1a; char *line1b; char *team1; char *team2; char *reason; char *city; char *country; char *neutral_field; }data; void open_input(char *argv[], FILE **input) { if((*input=fopen(argv[1], "r")) == NULL) { printf("%s not found\n", argv[1]); exit(1); } } void open_output(char *string, FILE **output) { if((*output=fopen(string, "w")) == NULL) { printf("%s not found\n", string); exit(1); } } void alloc_data(data *d, int size) { d->line1 = (char*)malloc(4*sizeof(char)); d->team1 = (char*)malloc(9*sizeof(char)); d->team2 = (char*)malloc(9*sizeof(char)); d->line1a = (char*)malloc(10*sizeof(char)); d->line1b = (char*)malloc(10*sizeof(char)); d->reason = (char*)malloc(10*sizeof(char)); d->city = (char*)malloc(4*sizeof(char)); d->country = (char*)malloc(7*sizeof(char)); d->neutral_field = (char*)malloc(7*sizeof(char)); } void store(data *d, FILE *input, FILE **output) { fscanf(input, "%s,%s,%s,%s,%s,%s,%s,%s,%s", d[0].line1, d[0].team1, d[0].team2, d[0].line1a, d[0].line1b, d[0].reason, d[0].city, d[0].country, d[0].neutral_field ); fprintf(*output, "%s,%s,%s,%s,%s,%s,%s,%s,%s\n", d[0].line1, d[0].team1, d[0].team2, d[0].line1a, d[0].line1b, d[0].reason, d[0].city, d[0].country, d[0].neutral_field ); } int main(int argc, char *argv[]) { FILE *input; FILE *output; char *string = "output.txt"; int size = 1000; open_input(argv, &input); open_output(string, &output); data *d; d = (data*)malloc(size*sizeof(data)); alloc_data(d, size); store(d, input, &output); free(d); return 0; }

Answer1:

<blockquote>

fscanf(input, "%s,%s,%s,%s,%s,%s,%s,%s,%s", d[0].line1, d[0].team1,...

</blockquote>

The above code tries to read the whole line in to d[0].line1 which causes buffer overflow. team1 and the rest will contain uninitialized data.

You have to change fscanf as follows:

fscanf(input, "%3[^ ,\n\t],%9[^ ,\n\t],...

Where 3 is 4 - 1, and 4 is the size of d[0].line1

Alternatively you can use strtok

#include <stdio.h> #include <stdlib.h> #include <string.h> void store(FILE *input, FILE *output) { char buf[500]; while(fgets(buf, sizeof(buf), input)) { //strip end-of-line from `buf` if(strlen(buf)) if(buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = 0; //tokenize with strtok char *token = strtok(buf, ","); while(token) { fprintf(output, "%s", token); token = strtok(NULL, ","); } fprintf(output, "\n"); } } int main(int argc, char *argv[]) { FILE *input = fopen("input.txt", "r"); FILE *output = fopen("output.txt", "w"); store(input, output); return 0; }

With above code you don't need an additional structure.

<hr /> If you do use a structure for data, you have to be more careful. It seems you are trying to create an array of 1000 data, but the following only creates one oversized pointer, not an array of data int size = 1000; data *d; d = (data*)malloc(size*sizeof(data)); alloc_data(d, size);

Additionally, for each malloc there should be a corresponding free.

Answer2:

Your buffers aren't big enough to hold the terminating NUL byte. scanf stores that NUL byte (overrunning the buffer), but then the object that really owns that byte may overwrite it, so when printf looks for the NUL it doesn't find it until much later in memory.

The buffer overruns are a bigger problem than what you've seen, who knows what objects those NUL bytes you didn't make space for are smashing? And what happens when you read a data file with slightly different header spelling? Suddenly your hard-coded allocations sizes will be even more wrong than they are already.

Recommend

  • Should I use for loop? OR apply? [duplicate]
  • Angular Object.key - Retrieve,get only one property from object
  • Defining two references to the same column in another table [duplicate]
  • Make jQuery datatables keep the row number assigned when searching/sorting
  • Receiving an error when requesting members for an array
  • Is there a parser equivalent of 'fragment' marking in ANTLR4?
  • C++ Single function pointer for all template instances
  • Simple linked list-C
  • Trying to get the char code of ENTER key
  • Using Sax parsing to edit and write XML in VB6
  • Appending Character to Character Array In C
  • Unable to decode certificate at client new X509Certificate2()
  • OOP Javascript - Is “get property” method necessary?
  • Date Conversion from yyyy-mm-dd to dd-mm-yyyy
  • Debug.DrawLine not showing in the GameView
  • Passing 1 of 3 values to a Sub
  • How to test if a URL from an Eclipse bundle is a directory?
  • ActiveRecord query for a count of new users by day
  • Set the selected item in dropdownlist in MVC3
  • Yii2: Config params vs. const/define
  • How to create a file in java without a extension
  • Spring Data JPA custom method causing PropertyReferenceException
  • Splitting given String into two variables - php
  • What is Eclipse's Declaration View used for?
  • Counter field in MS Access, how to generate?
  • Possible to stop flickering java tooltip in heavyweight mode?
  • sending/ receiving email in Java
  • How to set my toolbar fixed while scrolling android
  • AT Commands to Send SMS not working in Windows 8.1
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • embed rChart in Markdown
  • apache spark aggregate function using min value
  • EntityFramework adding new object to nested object collection
  • Checking variable from a different class in C#
  • Sorting a 2D array using the second column C++
  • How to get NHibernate ISession to cache entity not retrieved by primary key
  • How can I use `wmic` in a Windows PE script?
  • failed to connect to specific WiFi in android programmatically
  • Unable to use reactive element in my shiny app
  • How can I use threading to 'tick' a timer to be accessed by other threads?