0

So I have a big text file with data in it and I would like to rearrange it. The data has a combination of integers and floats per each line but I'm only interested in grabbing the first integer, which is either a 1 or 0, and putting it at the end of the line.

For example, in my data file, I have the following line
1 0.41 1 44
and I would like to be
0.41 1 44 1

This is what I have so far and can't get it to work right. Thanks.

void main() {
FILE *fp;
FILE *out;

char str[15];
char temp;

fp = fopen("dust.txt", "r+");
out = fopen("dust.dat", "w");

while(fgets(str, sizeof(str), fp) != NULL) {
    temp = str[0];
    str[strlen(str)] = ' ';
    str[strlen(str)+1] = temp;
    str[strlen(str)+2] = '\r';
    str[strlen(str)+3] = '\n';

fwrite(str, 1, strlen(str), out);
}   

fclose(fp);
    fclose(out);
}
iFreilicht
  • 13,271
  • 9
  • 43
  • 74
user252836
  • 49
  • 9

2 Answers2

4

This treats the output as a text file (same as input), not a binary. I've put code comments where appropriate. Your most serious error was in calling strlen after overwriting the string terminator. There is only need to call it once anyway.

#include <stdio.h>
#include <string.h>

int main(void)  {                           // main must be type int
    FILE *fp;
    FILE *out;
    char str[100];                          // be generous
    size_t len;

    fp = fopen("dust.txt", "r");
    out = fopen("dust2.txt", "w");          // text file
    if(fp == NULL || out == NULL)
        return 1;

    while(fgets(str, sizeof(str)-3, fp) != NULL) {
        str [ strcspn(str, "\r\n") ] = 0;   // remove trailing newline etc
        len = strlen(str);
        str[len] = ' ';                     // overwrites terminator
        str[len+1] = str[0];                // move digit from front
        str[len+2] = 0;                     // terminate string
        fprintf(out, "%s\n", str + 2);      // write as text
    }   

    fclose(fp);
    fclose(out);
    return 0;
}

Input file:

1 0.41 1 44
0 1.23 2 555

Output file:

0.41 1 44 1
1.23 2 555 0
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • If true, the OP should explain why 1.23 2 555 0 and not 0 1.23 2 555. I do understand that the OP needs the float first and then the rest, but is not quite clear if it is so – Michi Apr 21 '16 at 18:47
  • 1
    @Michi why should he? He has said what he wants, we don't know why, it's irrelavant. – Weather Vane Apr 21 '16 at 18:48
  • You right,sorry I wasn't paying attention to the question :) – Michi Apr 21 '16 at 18:53
  • Did not mean to copy, yet [my answer](http://stackoverflow.com/a/36778562/2410359) suggested `100` and "generous" entirely coincidently to your fine answer. Perhaps I should have used another value like [42](https://en.wikipedia.org/wiki/Phrases_from_The_Hitchhiker%27s_Guide_to_the_Galaxy#Answer_to_the_Ultimate_Question_of_Life.2C_the_Universe.2C_and_Everything_.2842.29)? – chux - Reinstate Monica Apr 21 '16 at 19:32
  • @chux your answer has more [deep thought](https://en.wikipedia.org/wiki/List_of_minor_The_Hitchhiker's_Guide_to_the_Galaxy_characters#Deep_Thought) than my terse answer, esp in discussing the output file format. As you say, it's better not to try emulating the text file format with binary output. – Weather Vane Apr 21 '16 at 19:36
1

Think about these 2 lines

str[strlen(str)] = ' ';
str[strlen(str)+1] = temp;

The first sets the null character to ' '. The 2nd calls strlen(str), yet str no longer has a certain null character which leads to undefined behavior (UB).


Suggest instead

str[strcspn(str, "\r\n")] = '\0'; // lop off potential end-of-line characters.
int prefix;
int n;
if (sscanf(str, "%d %n", &prefix, &n) != 1) Handle_Missing_Lead_int();
fprintf(out, "%s %d\n", &str[n], prefix); 

Opening a file in text mode and then writing "\r\n" is also a problem as code could write the "\r" and then take the "\n" and translate than into "\r\n" resulting in "\r\r\n". Suggest either opening the file in text mode and writing a single "\n" (which will be translated as needed) or opening the file in binary mode and writing explicit "\r\n".


BTW: Consider being more generous than 15 in char str[15];. Maybe 100?

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256