0

I'm new to C coming from Python/Perl background.

I'm writing a C program that will create multiple outputs and the number of outputs is determined from a input description file (basically the number of lines in the description file is the number of outputs) and one ID column in the description file will be used as output name.

What I currently have is that I read the ID column from the description file into an array and use the number of IDs to try to open the same number of FILE stream.

I'm having trouble in getting this to work. I have something like this right now and it complains at the compilation with the message at line 82 and 84:

error: variable-sized object may not be initialized

Part of the code:

 3 #include <stdio.h>
 4 #include <time.h>
 5 #include <zlib.h>
 6 #include <string.h>
 ....
 50 gzFile fi2,fi1,fr1;
 51
 52 fi2 = strcmp(argv[1],"-")? gzopen(argv[1],"r"):gzdopen(fileno(stdin),"r");
 53 fi1 = strcmp(argv[2],"-")? gzopen(argv[2],"r"):gzdopen(fileno(stdin),"r");
 54 FILE *samplelist = fopen(argv[5],"r");
 55 fr1 = strcmp(argv[6],"-")? gzopen(argv[6],"r"):gzdopen(fileno(stdin),"r");
 56 if (fi2 ==0 || fi1 ==0 || samplelist == 0 || fr1 == 0 ) {
 57     fprintf(stderr,"[E:%s] failed to open the input file/stream.\n",__func__);
 58     return 1;
 59 }
 60
 61 char line[100];
 62 char indexseq[10];
 63 char sampleid[5];
 64 char genome[15];
 65 char seqmode[3];
 66 char indexes[10][BUFSIZ];
 67 int lidx = 0;
 68 while (fgets(line, sizeof(line),samplelist)) {
 69      //printf("%s",line);
 70      sscanf(line,"%s\t%s\t%s\t%s\n",indexseq,sampleid,genome,seqmode);
 71      //printf("%s\n",indexseq);
 72      //printf("%s\n",sampleid);
 73      strcpy(indexes[lidx],sampleid);
 74      ++lidx;
 75      strcpy(indexes[lidx],indexseq);
 76      ++lidx;
 77 }
 78 char buf[30] = "";
 79 int i;
 80 for (i = 0; i <lidx; i+=2) {
 81     snprintf(buf, sizeof buf, "%s%s%s%s", argv[3],"_I1_",indexes[i],".fastq");
 82     fo_i1[i] = fopen(buf,"w");
 83     snprintf(buf, sizeof buf, "%s%s%s%s", argv[3],"_R1_",indexes[i],".fastq");
 84     fo_r1[i] = fopen(buf,"w");                    
 85 }

How could I get around the variable-sized FILE streams and get it work? Any suggestions on ways to modify certain lines are also welcome!

olala
  • 4,146
  • 9
  • 34
  • 44

1 Answers1

2

Declare fo_i1 and fo_r1 outside the loop as : FILE *fo_i1[lidx]; FILE *fo_r1[lidx]; and use it inside the loop without the FILE * part.

FILE *fo_i1[lidx];
FILE *fo_r1[lidx];
for (i = 0; i < lidx; i+=2) {
    fo_i1[i] = fopen(concat(concat(concat(argv[3],"_I1_"),indexes[lidx]),"_fastq"),"w");
    fo_r1[i] = fopen(concat(concat(concat(argv[3],"_R1_"),indexes[lidx]),"_fastq"),"w");
}

But note that your i+=2 logic looks wrong. There are two seperate arrays. So probably you really want that to be i++.

Another problem is indexes[lidx]. Because lidx has the value of the number of entries in the indexes array. Which means that lidx is an invalid index for the array - the last valid index is lidx-1.

There are probably other problems.

kaylum
  • 13,833
  • 2
  • 22
  • 31
  • Thanks for the quick feedback! It worked! i+=2 is right because I'm reading two columns from one line into the array and only need to take each ID once, so basically I need to skip another column – olala Feb 09 '17 at 19:48
  • @olala No it still doesn't look right. It means you will have "holes" in your `fo_` arrays. For example, `fo_i1[1]` and `fo_r[1]` will not be set. Is that really what you want? – kaylum Feb 09 '17 at 19:49
  • I see what you mean, maybe I should used `lidx/2` as the size of the `fo_` arrays? – olala Feb 09 '17 at 19:52
  • @wildplasser I got it from here: http://stackoverflow.com/questions/8465006/how-to-concatenate-2-strings-in-c/8465083#8465083, do you know a better way to do this? I can just use '+' to concatenate strings in Python and I'd love to know how to do it in C – olala Feb 09 '17 at 19:53
  • Yes. Just be sure to not use just `i` as the index if you make that change. – kaylum Feb 09 '17 at 19:54
  • 1
    It is terrible. (it even leaks memory) Just use `snprintf()` Cleaner and more readable, too. – wildplasser Feb 09 '17 at 19:56
  • @wildplasser i have modified the code to use `snprintf()`. thanks for the suggestion. – olala Feb 09 '17 at 22:22