Search code examples
cstringfilefwritestrsep

Strange output while using strsep and fwrite in C


I was going to make a python program to read from an XML document and use it as a reference while doing an action. However, the XML document would have been tedious to create by hand, so I decided to make a C program to do the bulk of it, excluding the first line and the root element. Here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
    FILE * fp = fopen("/Users/rajshrimali/Desktop/SPC_CMS.txt", "r");
    FILE * fw = fopen("/Users/rajshrimali/Desktop/SPC_XML", "a");
    char *line = NULL;
    size_t linecap = 0;
    ssize_t linelen;
    while ((linelen = getline(&line, &linecap, fp)) > 0){
        char *token;
        int x = 1; 
        while((token = strsep(&line, ",")) != NULL){
            printf("%s", token);
            if(x == 1){
                fwrite("<item> \n", linelen, 1, fw);
                fwrite("<name> \n", linelen, 1, fw);
                fwrite(token, linelen, 1, fw);
                fwrite("\n </name> \n", linelen, 1, fw);
                x++; 
            }
            if(x == 2) {
                fwrite("<SPC> \n", linelen, 1, fw);
                fwrite(token, linelen, 1, fw);
                fwrite("\n </SPC> \n", linelen, 1, fw);
                fwrite("</item> \n", linelen, 1, fw);
            }
        }
    }
}

The code compiled with no errors. However, when I ran it, the file SPC_XML was not nearly right:

<item> 
�<na<name> 

 <Agate�0.80

 </name> 
�<SPC> 

 </Agate�0.80

 </SPC> 
<</item> 
,�<item> 
<na<name> 

This nonsense continued for some time. The input file, fp, had data in this format:

Agate,0.80
Aluminum bronze,0.436
Aluminum,0.87
Antimony,0.21
Apatite,0.84

I think the error is with fwrite, although I have no idea what it is. What is the problem?


Solution

  • When you call fwrite, the second argument should be the length of the string that you are writing. So, when you do:

    fwrite("<item> \n", linelen, 1, fw);
    

    you will end up writing extra data, or maybe not enough, depending on what linelen is. Instead, you should manually count the size of your strings or call strlen on each of them. So, the call above could be turned into:

    fwrite("<item> \n", 8, 1, fw);
    

    and when you write out the tokens, you should call strlen:

    fwrite(token, strlen(token), 1, fw);