Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

CSV(ish) text handling – incorrect output on Windows, works on Linux

I am learning C and I don’t understand why this code doesn’t work.

It’s supposed to skip the first character, separate it in 8,4,4,4,4. But it adds one extra "0" to beginning of the second column and shifts the rest.

Also when I try to run it on Windows I can’t see any results. Sometimes it can’t open the file, sometimes the output is wrong.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

const int MAX_LINES = 10000000;

char s[1000];
int lines;
FILE *fptrIn, *fptrOut;

void convertData(char *s) {
    s[28] = 0;

    char gp1[8 + 1] = {0};
    char gp2[4 + 1] = {0};
    char gp3[4 + 1] = {0};
    char gp4[4 + 1] = {0};
    char gp5[4 + 1] = {0};
    char gp6[4 + 1] = {0};
    
    strncpy(gp1, s + 1, 8);
    strncpy(gp2, s + 8, 4);
    strncpy(gp3, s + 12, 4);
    strncpy(gp4, s + 16, 4);
    strncpy(gp5, s + 20, 4);
    strncpy(gp6, s + 24, 4);
    
    fprintf(fptrOut, "%s;%s;%s;%s;%s;%s\n", gp1, gp2, gp3, gp4, gp5, gp6);
}

int main() {

    if ((fptrIn = fopen("test.txt", "r")) == NULL) {
        printf("Error opening file!");
        return 1;
    }

    fptrOut = fopen("testout1.txt", "w");

    fprintf(fptrOut, "Position;Sens1;Sens2;Sens3;Check;Time\n");

    while(fgets(s, sizeof s, fptrIn) != NULL) {
        lines++;
        if (strlen(s) < 28)
            continue;
        printf("Line %d#:\n", lines);
        printf("%s\n", s);
        convertData(s);
        if (lines == MAX_LINES) {
            break;
        }    
    }

    fclose(fptrIn);
    fclose(fptrOut);

    return 0;
}

input data:

U66ACA1000D8007670000035CBE5Cd;
U66C668000D0A07DA0000037CBF60;
U66DF84000C9908480000038CC05A(;
U66F8A0000C2A08B6000003A9C154Ä;
U67114A800BBB0923000003C9C24E„;
U6729F5000B490991000003D9C348];

The output using Linux:

Position; Sens1; Sens2; Sens3; Check; Time;
66ACA100; 00D8; 0076; 7000; 0035; CBE5;
66C66800;00D0;A07D;A000;0037;CBF6;
66DF8400;00C9;9084;8000;0038;CC05;
66F8A000;00C2;A08B;6000;003A;9C15;
67114A80;00BB;B092;3000;003C;9C24;
6729F500;00B4;9099;1000;003D;9C34;

and here is the whole output on Windows (although WSL is running):

Position;Sens1;Sens2;Sens3;Check;Time;

66ACA100;0D80;0767;0000;035C;BE5
00F3B054;8000;0039;9DDE;2‘
U;69F
27000003;A6FD;687
;U6D1;D3B8;000
3731CEEÕ;
U70;4A17;0002;3901;7A0

U73764;8000;3F20;F570;0000;340

>Solution :

There’s no need to transfer the different fields out of s[ ]
printf() will do what you want…

printf( "%8.8s,%4.4s,%4.4s,%4.4s,%4.4s,%4.4s\n",
    s + 1,
    s + 1+8,
    s + 1+8+4+4,
    s + 1+8+4+4+4,
    s + 1+8+4+4+4+4,
    s + 1+8+4+4+4+4+4
    );

The compiler will ‘do the math’ collapsing those sum’s into single values in the object file. Having all the numbers laid out this way in the source code makes clear the different offsets.
.
One other thing… If the 1st char of each line is ‘skipped’ then you want chars in positions 1 to 28… s[28] = 0 is both wrong and unnecessary.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading